* NEWS: Mention "info proc" and core files.
        * corelow.c (core_info_proc): New function.
        (init_core_ops): Set to_info_proc.
        * gdbarch.c, gdbarch.h: Rebuild.
        * gdbarch.sh (core_info_proc): New method.
        * infcmd.c (info_proc_cmd_1): Invoke target_info_proc first.
        * linux-tdep.c (linux_core_info_proc_mappings)
        (linux_core_info_proc): New functions.
        (linux_find_memory_region_ftype): New typedef.
        (linux_find_memory_regions_full): New function, from
        linux_find_memory_regions.
        (struct linux_find_memory_regions_data): New.
        (linux_find_memory_regions_thunk): New function.
        (linux_find_memory_regions): Rewrite.
        (struct linux_make_mappings_data): New.
        (linux_make_mappings_callback)
        (linux_make_mappings_corefile_notes): New functions.
        (linux_make_corefile_notes): Call linux_make_mappings_corefile_notes.
        (linux_init_abi): Call set_gdbarch_core_info_proc.
        * target.c (target_info_proc): Return 'int'.
        * target.h (target_info_proc): Update.
gdb/doc
        * gdb.texinfo (SVR4 Process Information): Mention core files.
gdb/testsuite
        * gdb.base/info-proc.exp: Add core file tests.
bfd
        * elf.c (elfcore_grok_note) <NT_FILE>: New case.
This commit is contained in:
Tom Tromey 2012-12-14 15:30:38 +00:00
parent 83a2341852
commit 451b7c33cb
16 changed files with 444 additions and 19 deletions

View File

@ -1,3 +1,7 @@
2012-12-14 Tom Tromey <tromey@redhat.com>
* elf.c (elfcore_grok_note) <NT_FILE>: New case.
2012-12-13 H.J. Lu <hongjiu.lu@intel.com>
PR ld/14956

View File

@ -8626,6 +8626,10 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
return TRUE;
}
case NT_FILE:
return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file",
note);
case NT_SIGINFO:
return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
note);

View File

@ -1,3 +1,27 @@
2012-12-14 Tom Tromey <tromey@redhat.com>
* NEWS: Mention "info proc" and core files.
* corelow.c (core_info_proc): New function.
(init_core_ops): Set to_info_proc.
* gdbarch.c, gdbarch.h: Rebuild.
* gdbarch.sh (core_info_proc): New method.
* infcmd.c (info_proc_cmd_1): Invoke target_info_proc first.
* linux-tdep.c (linux_core_info_proc_mappings)
(linux_core_info_proc): New functions.
(linux_find_memory_region_ftype): New typedef.
(linux_find_memory_regions_full): New function, from
linux_find_memory_regions.
(struct linux_find_memory_regions_data): New.
(linux_find_memory_regions_thunk): New function.
(linux_find_memory_regions): Rewrite.
(struct linux_make_mappings_data): New.
(linux_make_mappings_callback)
(linux_make_mappings_corefile_notes): New functions.
(linux_make_corefile_notes): Call linux_make_mappings_corefile_notes.
(linux_init_abi): Call set_gdbarch_core_info_proc.
* target.c (target_info_proc): Return 'int'.
* target.h (target_info_proc): Update.
2012-12-14 Pierre Muller <muller@sourceware.org>
* windows-nat.c (windows_xfer_shared_libraries): Avoid

View File

@ -18,6 +18,8 @@
* The 'ptype' and 'whatis' commands now accept an argument to control
type formatting.
* 'info proc' now works on some core files.
* Python scripting
** Vectors can be created with gdb.Type.vector.

View File

@ -927,6 +927,19 @@ core_has_registers (struct target_ops *ops)
return (core_bfd != NULL);
}
/* Implement the to_info_proc method. */
static void
core_info_proc (struct target_ops *ops, char *args, enum info_proc_what request)
{
struct gdbarch *gdbarch = get_current_arch ();
/* Since this is the core file target, call the 'core_info_proc'
method on gdbarch, not 'info_proc'. */
if (gdbarch_core_info_proc_p (gdbarch))
gdbarch_core_info_proc (gdbarch, args, request);
}
/* Fill in core_ops with its defined operations and properties. */
static void
@ -953,6 +966,7 @@ init_core_ops (void)
core_ops.to_has_memory = core_has_memory;
core_ops.to_has_stack = core_has_stack;
core_ops.to_has_registers = core_has_registers;
core_ops.to_info_proc = core_info_proc;
core_ops.to_magic = OPS_MAGIC;
if (core_target)

View File

@ -1,3 +1,7 @@
2012-12-14 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (SVR4 Process Information): Mention core files.
2012-12-12 Mircea Gherzan <mircea.gherzan@intel.com>
* gdb.texinfo (GDB/MI Catchpoint Commands): New section.

View File

@ -18649,13 +18649,17 @@ modern FreeBSD systems.
Many versions of SVR4 and compatible systems provide a facility called
@samp{/proc} that can be used to examine the image of a running
process using file-system subroutines. If @value{GDBN} is configured
for an operating system with this facility, the command @code{info
proc} is available to report information about the process running
your program, or about any process running on your system. @code{info
proc} works only on SVR4 systems that include the @code{procfs} code.
This includes, as of this writing, @sc{gnu}/Linux, OSF/1 (Digital
Unix), Solaris, Irix, but not HP-UX, for example.
process using file-system subroutines.
If @value{GDBN} is configured for an operating system with this
facility, the command @code{info proc} is available to report
information about the process running your program, or about any
process running on your system. This includes, as of this writing,
@sc{gnu}/Linux, OSF/1 (Digital Unix), Solaris, and Irix, but
not HP-UX, for example.
This command may also work on core files that were created on a system
that has the @samp{/proc} facility.
@table @code
@kindex info proc

View File

@ -283,6 +283,7 @@ struct gdbarch
int has_dos_based_file_system;
gdbarch_gen_return_address_ftype *gen_return_address;
gdbarch_info_proc_ftype *info_proc;
gdbarch_core_info_proc_ftype *core_info_proc;
gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order;
};
@ -451,6 +452,7 @@ struct gdbarch startup_gdbarch =
0, /* has_dos_based_file_system */
default_gen_return_address, /* gen_return_address */
0, /* info_proc */
0, /* core_info_proc */
default_iterate_over_objfiles_in_search_order, /* iterate_over_objfiles_in_search_order */
/* startup_gdbarch() */
};
@ -750,6 +752,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of has_dos_based_file_system, invalid_p == 0 */
/* Skip verify of gen_return_address, invalid_p == 0 */
/* Skip verify of info_proc, has predicate. */
/* Skip verify of core_info_proc, has predicate. */
/* Skip verify of iterate_over_objfiles_in_search_order, invalid_p == 0 */
buf = ui_file_xstrdup (log, &length);
make_cleanup (xfree, buf);
@ -867,6 +870,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: convert_register_p = <%s>\n",
host_address_to_string (gdbarch->convert_register_p));
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_core_info_proc_p() = %d\n",
gdbarch_core_info_proc_p (gdbarch));
fprintf_unfiltered (file,
"gdbarch_dump: core_info_proc = <%s>\n",
host_address_to_string (gdbarch->core_info_proc));
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_core_pid_to_str_p() = %d\n",
gdbarch_core_pid_to_str_p (gdbarch));
@ -4250,6 +4259,30 @@ set_gdbarch_info_proc (struct gdbarch *gdbarch,
gdbarch->info_proc = info_proc;
}
int
gdbarch_core_info_proc_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
return gdbarch->core_info_proc != NULL;
}
void
gdbarch_core_info_proc (struct gdbarch *gdbarch, char *args, enum info_proc_what what)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->core_info_proc != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_core_info_proc called\n");
gdbarch->core_info_proc (gdbarch, args, what);
}
void
set_gdbarch_core_info_proc (struct gdbarch *gdbarch,
gdbarch_core_info_proc_ftype core_info_proc)
{
gdbarch->core_info_proc = core_info_proc;
}
void
gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype *cb, void *cb_data, struct objfile *current_objfile)
{

View File

@ -1193,6 +1193,16 @@ typedef void (gdbarch_info_proc_ftype) (struct gdbarch *gdbarch, char *args, enu
extern void gdbarch_info_proc (struct gdbarch *gdbarch, char *args, enum info_proc_what what);
extern void set_gdbarch_info_proc (struct gdbarch *gdbarch, gdbarch_info_proc_ftype *info_proc);
/* Implement the "info proc" command for core files. Noe that there
are two "info_proc"-like methods on gdbarch -- one for core files,
one for live targets. */
extern int gdbarch_core_info_proc_p (struct gdbarch *gdbarch);
typedef void (gdbarch_core_info_proc_ftype) (struct gdbarch *gdbarch, char *args, enum info_proc_what what);
extern void gdbarch_core_info_proc (struct gdbarch *gdbarch, char *args, enum info_proc_what what);
extern void set_gdbarch_core_info_proc (struct gdbarch *gdbarch, gdbarch_core_info_proc_ftype *core_info_proc);
/* Iterate over all objfiles in the order that makes the most sense
for the architecture to make global symbol searches.

View File

@ -943,6 +943,11 @@ m:void:gen_return_address:struct agent_expr *ax, struct axs_value *value, CORE_A
# Implement the "info proc" command.
M:void:info_proc:char *args, enum info_proc_what what:args, what
# Implement the "info proc" command for core files. Noe that there
# are two "info_proc"-like methods on gdbarch -- one for core files,
# one for live targets.
M:void:core_info_proc:char *args, enum info_proc_what what:args, what
# Iterate over all objfiles in the order that makes the most sense
# for the architecture to make global symbol searches.
#

View File

@ -2883,10 +2883,13 @@ info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty)
{
struct gdbarch *gdbarch = get_current_arch ();
if (gdbarch_info_proc_p (gdbarch))
gdbarch_info_proc (gdbarch, args, what);
else
target_info_proc (args, what);
if (!target_info_proc (args, what))
{
if (gdbarch_info_proc_p (gdbarch))
gdbarch_info_proc (gdbarch, args, what);
else
error (_("Not supported on this target."));
}
}
/* Implement `info proc' when given without any futher parameters. */

View File

@ -30,6 +30,8 @@
#include "elf-bfd.h" /* for elfcore_write_* */
#include "inferior.h"
#include "cli/cli-utils.h"
#include "arch-utils.h"
#include "gdb_obstack.h"
#include <ctype.h>
@ -533,11 +535,149 @@ linux_info_proc (struct gdbarch *gdbarch, char *args,
}
}
/* Implement "info proc mappings" for a corefile. */
static void
linux_core_info_proc_mappings (struct gdbarch *gdbarch, char *args)
{
asection *section;
ULONGEST count, page_size;
unsigned char *descdata, *filenames, *descend, *contents;
size_t note_size;
unsigned int addr_size_bits, addr_size;
struct cleanup *cleanup;
struct gdbarch *core_gdbarch = gdbarch_from_bfd (core_bfd);
/* We assume this for reading 64-bit core files. */
gdb_static_assert (sizeof (ULONGEST) >= 8);
section = bfd_get_section_by_name (core_bfd, ".note.linuxcore.file");
if (section == NULL)
{
warning (_("unable to find mappings in core file"));
return;
}
addr_size_bits = gdbarch_addr_bit (core_gdbarch);
addr_size = addr_size_bits / 8;
note_size = bfd_get_section_size (section);
if (note_size < 2 * addr_size)
error (_("malformed core note - too short for header"));
contents = xmalloc (note_size);
cleanup = make_cleanup (xfree, contents);
if (!bfd_get_section_contents (core_bfd, section, contents, 0, note_size))
error (_("could not get core note contents"));
descdata = contents;
descend = descdata + note_size;
if (descdata[note_size - 1] != '\0')
error (_("malformed note - does not end with \\0"));
count = bfd_get (addr_size_bits, core_bfd, descdata);
descdata += addr_size;
page_size = bfd_get (addr_size_bits, core_bfd, descdata);
descdata += addr_size;
if (note_size < 2 * addr_size + count * 3 * addr_size)
error (_("malformed note - too short for supplied file count"));
printf_filtered (_("Mapped address spaces:\n\n"));
if (gdbarch_addr_bit (gdbarch) == 32)
{
printf_filtered ("\t%10s %10s %10s %10s %s\n",
"Start Addr",
" End Addr",
" Size", " Offset", "objfile");
}
else
{
printf_filtered (" %18s %18s %10s %10s %s\n",
"Start Addr",
" End Addr",
" Size", " Offset", "objfile");
}
filenames = descdata + count * 3 * addr_size;
while (--count > 0)
{
ULONGEST start, end, file_ofs;
if (filenames == descend)
error (_("malformed note - filenames end too early"));
start = bfd_get (addr_size_bits, core_bfd, descdata);
descdata += addr_size;
end = bfd_get (addr_size_bits, core_bfd, descdata);
descdata += addr_size;
file_ofs = bfd_get (addr_size_bits, core_bfd, descdata);
descdata += addr_size;
file_ofs *= page_size;
if (gdbarch_addr_bit (gdbarch) == 32)
printf_filtered ("\t%10s %10s %10s %10s %s\n",
paddress (gdbarch, start),
paddress (gdbarch, end),
hex_string (end - start),
hex_string (file_ofs),
filenames);
else
printf_filtered (" %18s %18s %10s %10s %s\n",
paddress (gdbarch, start),
paddress (gdbarch, end),
hex_string (end - start),
hex_string (file_ofs),
filenames);
filenames += 1 + strlen ((char *) filenames);
}
do_cleanups (cleanup);
}
/* Implement "info proc" for a corefile. */
static void
linux_core_info_proc (struct gdbarch *gdbarch, char *args,
enum info_proc_what what)
{
int exe_f = (what == IP_MINIMAL || what == IP_EXE || what == IP_ALL);
int mappings_f = (what == IP_MAPPINGS || what == IP_ALL);
if (exe_f)
{
const char *exe;
exe = bfd_core_file_failing_command (core_bfd);
if (exe != NULL)
printf_filtered ("exe = '%s'\n", exe);
else
warning (_("unable to find command name in core file"));
}
if (mappings_f)
linux_core_info_proc_mappings (gdbarch, args);
if (!exe_f && !mappings_f)
error (_("unable to handle request"));
}
typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
ULONGEST offset, ULONGEST inode,
int read, int write,
int exec, int modified,
const char *filename,
void *data);
/* List memory regions in the inferior for a corefile. */
static int
linux_find_memory_regions (struct gdbarch *gdbarch,
find_memory_region_ftype func, void *obfd)
linux_find_memory_regions_full (struct gdbarch *gdbarch,
linux_find_memory_region_ftype *func,
void *obfd)
{
char filename[100];
gdb_byte *data;
@ -606,7 +746,8 @@ linux_find_memory_regions (struct gdbarch *gdbarch,
modified = 1;
/* Invoke the callback function to create the corefile segment. */
func (addr, endaddr - addr, read, write, exec, modified, obfd);
func (addr, endaddr - addr, offset, inode,
read, write, exec, modified, filename, obfd);
}
do_cleanups (cleanup);
@ -616,6 +757,51 @@ linux_find_memory_regions (struct gdbarch *gdbarch,
return 1;
}
/* A structure for passing information through
linux_find_memory_regions_full. */
struct linux_find_memory_regions_data
{
/* The original callback. */
find_memory_region_ftype func;
/* The original datum. */
void *obfd;
};
/* A callback for linux_find_memory_regions that converts between the
"full"-style callback and find_memory_region_ftype. */
static int
linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,
ULONGEST offset, ULONGEST inode,
int read, int write, int exec, int modified,
const char *filename, void *arg)
{
struct linux_find_memory_regions_data *data = arg;
return data->func (vaddr, size, read, write, exec, modified, data->obfd);
}
/* A variant of linux_find_memory_regions_full that is suitable as the
gdbarch find_memory_regions method. */
static int
linux_find_memory_regions (struct gdbarch *gdbarch,
find_memory_region_ftype func, void *obfd)
{
struct linux_find_memory_regions_data data;
data.func = func;
data.obfd = obfd;
return linux_find_memory_regions_full (gdbarch,
linux_find_memory_regions_thunk,
&data);
}
/* Determine which signal stopped execution. */
static int
@ -712,6 +898,112 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
return note_data;
}
/* This is used to pass information from
linux_make_mappings_corefile_notes through
linux_find_memory_regions_full. */
struct linux_make_mappings_data
{
/* Number of files mapped. */
ULONGEST file_count;
/* The obstack for the main part of the data. */
struct obstack *data_obstack;
/* The filename obstack. */
struct obstack *filename_obstack;
/* The architecture's "long" type. */
struct type *long_type;
};
static linux_find_memory_region_ftype linux_make_mappings_callback;
/* A callback for linux_find_memory_regions_full that updates the
mappings data for linux_make_mappings_corefile_notes. */
static int
linux_make_mappings_callback (ULONGEST vaddr, ULONGEST size,
ULONGEST offset, ULONGEST inode,
int read, int write, int exec, int modified,
const char *filename, void *data)
{
struct linux_make_mappings_data *map_data = data;
gdb_byte buf[sizeof (ULONGEST)];
if (*filename == '\0' || inode == 0)
return 0;
++map_data->file_count;
pack_long (buf, map_data->long_type, vaddr);
obstack_grow (map_data->data_obstack, buf, TYPE_LENGTH (map_data->long_type));
pack_long (buf, map_data->long_type, vaddr + size);
obstack_grow (map_data->data_obstack, buf, TYPE_LENGTH (map_data->long_type));
pack_long (buf, map_data->long_type, offset);
obstack_grow (map_data->data_obstack, buf, TYPE_LENGTH (map_data->long_type));
obstack_grow_str0 (map_data->filename_obstack, filename);
return 0;
}
/* Write the file mapping data to the core file, if possible. OBFD is
the output BFD. NOTE_DATA is the current note data, and NOTE_SIZE
is a pointer to the note size. Returns the new NOTE_DATA and
updates NOTE_SIZE. */
static char *
linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
char *note_data, int *note_size)
{
struct cleanup *cleanup;
struct obstack data_obstack, filename_obstack;
struct linux_make_mappings_data mapping_data;
struct type *long_type
= arch_integer_type (gdbarch, gdbarch_long_bit (gdbarch), 0, "long");
gdb_byte buf[sizeof (ULONGEST)];
obstack_init (&data_obstack);
cleanup = make_cleanup_obstack_free (&data_obstack);
obstack_init (&filename_obstack);
make_cleanup_obstack_free (&filename_obstack);
mapping_data.file_count = 0;
mapping_data.data_obstack = &data_obstack;
mapping_data.filename_obstack = &filename_obstack;
mapping_data.long_type = long_type;
/* Reserve space for the count. */
obstack_blank (&data_obstack, TYPE_LENGTH (long_type));
/* We always write the page size as 1 since we have no good way to
determine the correct value. */
pack_long (buf, long_type, 1);
obstack_grow (&data_obstack, buf, TYPE_LENGTH (long_type));
linux_find_memory_regions_full (gdbarch, linux_make_mappings_callback,
&mapping_data);
if (mapping_data.file_count != 0)
{
/* Write the count to the obstack. */
pack_long (obstack_base (&data_obstack), long_type,
mapping_data.file_count);
/* Copy the filenames to the data obstack. */
obstack_grow (&data_obstack, obstack_base (&filename_obstack),
obstack_object_size (&filename_obstack));
note_data = elfcore_write_note (obfd, note_data, note_size,
"CORE", NT_FILE,
obstack_base (&data_obstack),
obstack_object_size (&data_obstack));
}
do_cleanups (cleanup);
return note_data;
}
/* Records the thread's register state for the corefile note
section. */
@ -923,6 +1215,10 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
if (!note_data)
return NULL;
/* File mappings. */
note_data = linux_make_mappings_corefile_notes (gdbarch, obfd,
note_data, note_size);
make_cleanup (xfree, note_data);
return note_data;
}
@ -949,6 +1245,7 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str);
set_gdbarch_info_proc (gdbarch, linux_info_proc);
set_gdbarch_core_info_proc (gdbarch, linux_core_info_proc);
set_gdbarch_find_memory_regions (gdbarch, linux_find_memory_regions);
set_gdbarch_make_corefile_notes (gdbarch, linux_make_corefile_notes_1);
set_gdbarch_has_shared_address_space (gdbarch,

View File

@ -3144,7 +3144,7 @@ target_supports_non_stop (void)
/* Implement the "info proc" command. */
void
int
target_info_proc (char *args, enum info_proc_what what)
{
struct target_ops *t;
@ -3167,11 +3167,11 @@ target_info_proc (char *args, enum info_proc_what what)
fprintf_unfiltered (gdb_stdlog,
"target_info_proc (\"%s\", %d)\n", args, what);
return;
return 1;
}
}
error (_("Not supported on this target."));
return 0;
}
static int

View File

@ -976,9 +976,12 @@ extern void target_store_registers (struct regcache *regcache, int regs);
struct address_space *target_thread_address_space (ptid_t);
/* Implement the "info proc" command. */
/* Implement the "info proc" command. This returns one if the request
was handled, and zero otherwise. It can also throw an exception if
an error was encountered while attempting to handle the
request. */
void target_info_proc (char *, enum info_proc_what);
int target_info_proc (char *, enum info_proc_what);
/* Returns true if this target can debug multiple processes
simultaneously. */

View File

@ -1,3 +1,7 @@
2012-12-14 Tom Tromey <tromey@redhat.com>
* gdb.base/info-proc.exp: Add core file tests.
2012-12-14 Yufeng Zhang <yufeng.zhang@arm.com>
* gdb.base/kill-after-signal.exp: Disable if gdb,nosignals.

View File

@ -68,3 +68,17 @@ gdb_test "info proc" "process ${decimal}.*" "info proc with process"
gdb_test "info proc mapping" \
".*Mapped address spaces:.*${hex}${ws}${hex}${ws}${hex}${ws}${hex}.*" \
"info proc mapping"
if {[istarget "*-*-linux*"]} {
set gcorefile [standard_output_file $testfile.gcore]
if {[gdb_gcore_cmd $gcorefile "save a core file"]} {
clean_restart $binfile
gdb_test "core $gcorefile" "Core was generated by.*" \
"core [file tail $gcorefile]"
gdb_test "info proc mapping" \
".*Mapped address spaces:.*${hex}${ws}${hex}${ws}${hex}${ws}${hex}.*" \
"info proc mapping with core file"
}
}