From 451b7c33cb3c9ec6272c36870adb4d4f5649aae2 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 14 Dec 2012 15:30:38 +0000 Subject: [PATCH] gdb * 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) : New case. --- bfd/ChangeLog | 4 + bfd/elf.c | 4 + gdb/ChangeLog | 24 +++ gdb/NEWS | 2 + gdb/corelow.c | 14 ++ gdb/doc/ChangeLog | 4 + gdb/doc/gdb.texinfo | 18 ++- gdb/gdbarch.c | 33 ++++ gdb/gdbarch.h | 10 ++ gdb/gdbarch.sh | 5 + gdb/infcmd.c | 11 +- gdb/linux-tdep.c | 303 ++++++++++++++++++++++++++++++++++- gdb/target.c | 6 +- gdb/target.h | 7 +- gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.base/info-proc.exp | 14 ++ 16 files changed, 444 insertions(+), 19 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1ff8574..87cc9d7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,7 @@ +2012-12-14 Tom Tromey + + * elf.c (elfcore_grok_note) : New case. + 2012-12-13 H.J. Lu PR ld/14956 diff --git a/bfd/elf.c b/bfd/elf.c index f010f5a..a92dd5d 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -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); diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d3c886d..b8dee93 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2012-12-14 Tom Tromey + + * 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 * windows-nat.c (windows_xfer_shared_libraries): Avoid diff --git a/gdb/NEWS b/gdb/NEWS index 7c467f8..775e7d3 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -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. diff --git a/gdb/corelow.c b/gdb/corelow.c index 99611ba..589f231 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -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) diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 535f266..f65e4b7 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2012-12-14 Tom Tromey + + * gdb.texinfo (SVR4 Process Information): Mention core files. + 2012-12-12 Mircea Gherzan * gdb.texinfo (GDB/MI Catchpoint Commands): New section. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c23e5de..f96d498 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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 diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 6ae453e..32fe26b 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -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); @@ -868,6 +871,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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)); fprintf_unfiltered (file, @@ -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) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 3d9dc79..572aca3 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -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. diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 8a56106..daa1228 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -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. # diff --git a/gdb/infcmd.c b/gdb/infcmd.c index db9b9b5..4e38725 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -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. */ diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index dbeed36..d5ad6e3 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -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 @@ -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, diff --git a/gdb/target.c b/gdb/target.c index 5015e51..ebd8085 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -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 diff --git a/gdb/target.h b/gdb/target.h index 7907ee1..a832ef8 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 9044a76..f584518 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-12-14 Tom Tromey + + * gdb.base/info-proc.exp: Add core file tests. + 2012-12-14 Yufeng Zhang * gdb.base/kill-after-signal.exp: Disable if gdb,nosignals. diff --git a/gdb/testsuite/gdb.base/info-proc.exp b/gdb/testsuite/gdb.base/info-proc.exp index 1cefb6d..0ac0b6e 100644 --- a/gdb/testsuite/gdb.base/info-proc.exp +++ b/gdb/testsuite/gdb.base/info-proc.exp @@ -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" + } +} -- 2.7.4