From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10763 invoked by alias); 16 Nov 2011 04:10:32 -0000 Received: (qmail 10744 invoked by uid 22791); 16 Nov 2011 04:10:28 -0000 X-SWARE-Spam-Status: No, hits=-7.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_BJ X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 16 Nov 2011 04:10:08 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAG4A8g5014472 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 15 Nov 2011 23:10:08 -0500 Received: from psique (ovpn-112-21.phx2.redhat.com [10.3.112.21]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAG4A3QC004618; Tue, 15 Nov 2011 23:10:05 -0500 From: Sergio Durigan Junior To: Jan Kratochvil Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] Implement new `info core mappings' command References: <20111031001117.GA11608@host1.jankratochvil.net> <20111031070012.GA32610@host1.jankratochvil.net> <20111104162648.GA30571@host1.jankratochvil.net> <20111109203148.GA19625@host1.jankratochvil.net> Date: Wed, 16 Nov 2011 04:10:00 -0000 In-Reply-To: <20111109203148.GA19625@host1.jankratochvil.net> (Jan Kratochvil's message of "Wed, 9 Nov 2011 21:31:48 +0100") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-11/txt/msg00415.txt.bz2 Jan Kratochvil writes: > On Tue, 08 Nov 2011 02:48:54 +0100, Sergio Durigan Junior wrote: >> > On Thu, 03 Nov 2011 21:00:39 +0100, Sergio Durigan Junior wrote: >> > For ELF core files you should rather check also the ELF segments in >> > objfiles->obfd and verify it is fully covered. > [...] >> This one is giving me headaches... > > So I understand in some corner cases without ABRT `info core mappings' may be > useful but I no longer find too much interest in it myself and some > approximate file suggestion may be just good enough there. After all the > whole information about where is which file mapped is just an approximate > suggestion by GDB anyway. Ok, so I would like to ask for another round of review of this patch then. I am aware of Ulrich's work towards a new `info mappings' command, but since I've got no response from him yet, I decided to continue my efforts here. The documentation bits were already approved by Eli, and the code was discussed a lot with Jan. This patch causes no regression, as mentioned earlier. For more details, please read the whole thread. Thanks a lot. 2011-11-16 Sergio Durigan Junior Implement `info core mappings'. * NEWS: Mention new `info core' command, along with its new subcommands `mappings', `exe' and `all'. * corefile.c: Include a bunch of header files needed to implement the `info core mappings'. (info_core_what): New enum. (info_core_print_core_exe): New function. (info_core_print_proc_map_non_elf): Likewise. (info_core_print_core_map_elf): Likewise. (info_core_print_core_map): Likewise. (info_core_cmd_1): Likewise. (info_core_cmd): Likewise. (info_core_cmd_mappings): Likewise. (info_core_cmd_exe): Likewise. (info_core_cmd_all): Likewise. (_initialize_core): Add new `info core' command, along with its new subcommands `mappings', `exe' and `all'. 2011-11-16 Sergio Durigan Junior Implement `info core mappings'. * gdb.texinfo: Add documentation for `info core', and to its new subcommands `mappings', `exe' and `all'. 2011-11-16 Sergio Durigan Junior Implement `info core mappings'. * gdb.base/corefile.exp: Add test for `info core', and for its new subcommands `mappings', `exe' and `all'. diff --git a/gdb/NEWS b/gdb/NEWS index c4e59c4..e649727 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,17 @@ *** Changes since GDB 7.3.1 +* GDB has a new `info core' command, which can be used to display information + from a corefile. Its subcommands are: + + ** `info core mappings': display information about memory mappings + from the corefile. + + ** `info core exe': display the executable filename that generated + the corefile. + + ** `info core all': display all of the above. + * GDB now allows you to skip uninteresting functions and files when stepping with the "skip function" and "skip file" commands. diff --git a/gdb/corefile.c b/gdb/corefile.c index ce3b755..9302476 100644 --- a/gdb/corefile.c +++ b/gdb/corefile.c @@ -24,17 +24,23 @@ #include #include #include +#include #include "inferior.h" #include "symtab.h" +#include "gdbarch.h" +#include "arch-utils.h" #include "command.h" #include "gdbcmd.h" #include "bfd.h" +#include "elf-bfd.h" +#include "elf/internal.h" #include "target.h" #include "gdbcore.h" #include "dis-asm.h" #include "gdb_stat.h" #include "completer.h" #include "exceptions.h" +#include "objfiles.h" /* Local function declarations. */ @@ -83,6 +89,267 @@ core_file_command (char *filename, int from_tty) } +/* Implement the `info core' command. */ + +enum info_core_what + { + /* Display the default exe output. */ + IC_MINIMAL, + + /* Display `info core mappings'. */ + IC_MAPPINGS, + + /* Display `info core exe'. */ + IC_EXE, + + /* Display all of the above. */ + IC_ALL + }; + +/* Implement `info core exe' command. */ + +static void +info_core_print_core_exe (void) +{ + const char *exe; + + /* Getting the executable name. */ + exe = bfd_core_file_failing_command (core_bfd); + + if (exe) + printf_filtered (_("exe = '%s'\n"), exe); + else + warning (_("Could not obtain executable name: %s"), + bfd_errmsg (bfd_get_error ())); +} + +/* Helper function for `info_core_print_proc_map', used for non-ELF objects. + + It is used to iterate over the corefile's BFD sections and print proper + information about memory-mappings. + + ABFD is the bfd used to get the sections. + SECT is the current section being "visited". + OBJ is not used. */ + +static void +info_core_print_proc_map_non_elf (bfd *abfd, asection *sect, void *obj) +{ + /* We're interested in matching sections' names beginning with + `load', because they are the sections containing information + about the process' memory regions. */ + static const char proc_map_match[] = "load"; + int proc_map_match_size = strlen (proc_map_match); + /* We have to know the bitness of this architecture. */ + struct gdbarch *gdbarch; + int bitness; + /* We'll use these later. They are basically used for iterating + over every objfile in the system so that we can find needed + information about the memory region being examinated. */ + struct obj_section *s; + struct objfile *objfile; + /* Fields to be printed for the proc map. */ + CORE_ADDR start; + CORE_ADDR end; + CORE_ADDR size; + char *filename = ""; + + if (strncmp (proc_map_match, sect->name, proc_map_match_size) != 0) + /* This section is not useful. */ + return; + + /* Bitness is important for formatting the text to output. */ + gdbarch = gdbarch_from_bfd (abfd); + bitness = gdbarch_addr_bit (gdbarch); + + /* Retrieving the section size. */ + size = bfd_section_size (bfd, sect); + + start = sect->vma; + end = sect->vma + size; + + /* Now begins a new part of the work. We still don't have complete + information about the memory region. For example, we still need + to know the filename which is represented by the region. Such + info can be gathered from the objfile's data structure, and for + that we must iterate over all the objsections and check if the + objsection's initial address is inside the section we have at hand. + If it is, then we can use this specific objsection to obtain the + missing data. */ + ALL_OBJSECTIONS (objfile, s) + { + if (objfile->separate_debug_objfile_backlink) + continue; + + if (!section_is_overlay (s) && obj_section_addr (s) >= start + && obj_section_addr (s) <= end) + { + filename = s->objfile->name; + break; + } + } + + if (bitness == 32) + printf_filtered ("\t%10s %10s %10s %s\n", + paddress (gdbarch, start), + paddress (gdbarch, end), + paddress (gdbarch, size), filename); + else + printf_filtered (" %18s %18s %10s %s\n", + paddress (gdbarch, start), + paddress (gdbarch, end), + paddress (gdbarch, size), filename); +} + +/* Helper function for `info_core_print_core_map' which handles objects + in the ELF format. */ + +static void +info_core_print_core_map_elf (void) +{ +#ifdef HAVE_ELF + int bitness; + unsigned int n_segs; + Elf_Internal_Phdr *p; + struct gdbarch *gdbarch = gdbarch_from_bfd (core_bfd); + + /* Bitness is important when formatting the text to be printed. */ + bitness = gdbarch_addr_bit (gdbarch); + + p = elf_tdata (core_bfd)->phdr; + if (!p) + error (_("Could not obtain mapped addresses.")); + + printf_filtered (_("Mapped address spaces:\n\n")); + if (bitness == 32) + printf_filtered ("\t%10s %10s %10s %s\n", + "Start Address", + " End Address", + " Size", "objfile"); + else + printf_filtered (" %18s %18s %10s %s\n", + "Start Address", + " End Address", + " Size", "objfile"); + + for (n_segs = elf_elfheader (core_bfd)->e_phnum; + n_segs > 0; n_segs--, p++) + { + /* These are basically used for iterating over every objfile in + the system so that we can find needed information about the + memory region being examinated. */ + struct obj_section *s; + struct objfile *objfile; + /* Information about the segment. */ + CORE_ADDR start; + CORE_ADDR end; + CORE_ADDR size; + /* File associated with this memory region. */ + char *filename = ""; + + if (p->p_type != PT_LOAD) + /* We are only interested in PT_LOAD segments. */ + continue; + + start = p->p_vaddr; + size = p->p_memsz; + end = start + size; + + ALL_OBJSECTIONS (objfile, s) + { + if (objfile->separate_debug_objfile_backlink) + continue; + + if (!section_is_overlay (s) && obj_section_addr (s) >= start + && obj_section_addr (s) <= end) + { + filename = s->objfile->name; + break; + } + } + + if (bitness == 32) + printf_filtered ("\t%10s %10s %10s %s\n", + paddress (gdbarch, start), + paddress (gdbarch, end), + paddress (gdbarch, size), filename); + else + printf_filtered (" %18s %18s %10s %s\n", + paddress (gdbarch, start), + paddress (gdbarch, end), + paddress (gdbarch, size), filename); + } +#else + error (_("Your system does not support ELF format.")); +#endif /* HAVE_ELF */ +} + +/* Implement the `info core map' command. */ + +static void +info_core_print_core_map (void) +{ + gdb_assert (core_bfd != NULL); + + if (bfd_get_flavour (core_bfd) == bfd_target_elf_flavour) + info_core_print_core_map_elf (); + else + bfd_map_over_sections (core_bfd, + info_core_print_proc_map_non_elf, + NULL); +} + +/* Implement the `info core' command. */ + +static void +info_core_cmd_1 (char *args, enum info_core_what what, int from_tty) +{ + char **argv = NULL; + int mappings_f = (what == IC_MAPPINGS || what == IC_ALL); + int exe_f = (what == IC_MINIMAL || what == IC_EXE || what == IC_ALL); + + if (!core_bfd) + error (_("You are not using a corefile at the moment.")); + + if (exe_f) + info_core_print_core_exe (); + + if (mappings_f) + info_core_print_core_map (); +} + +/* Implement `info core' without parameters. */ + +static void +info_core_cmd (char *args, int from_tty) +{ + info_core_cmd_1 (args, IC_MINIMAL, from_tty); +} + +/* Implement `info core mappings'. */ + +static void +info_core_cmd_mappings (char *args, int from_tty) +{ + info_core_cmd_1 (args, IC_MAPPINGS, from_tty); +} + +/* Implement `info core exe'. */ + +static void +info_core_cmd_exe (char *args, int from_tty) +{ + info_core_cmd_1 (args, IC_EXE, from_tty); +} + +/* Implement `info core all'. */ + +static void +info_core_cmd_all (char *args, int from_tty) +{ + info_core_cmd_1 (args, IC_ALL, from_tty); +} + /* If there are two or more functions that wish to hook into exec_file_command, this function will call all of the hook functions. */ @@ -449,6 +716,26 @@ void _initialize_core (void) { struct cmd_list_element *c; + static struct cmd_list_element *info_core_cmdlist; + + add_prefix_cmd ("core", class_info, info_core_cmd, + _("\ +Show information about a corefile.\n\ +The command uses the corefile loaded."), + &info_core_cmdlist, "info core ", + 1/*allow-unknown*/, &infolist); + + add_cmd ("mappings", class_info, info_core_cmd_mappings, _("\ +List of mapped memory regions."), + &info_core_cmdlist); + + add_cmd ("exe", class_info, info_core_cmd_exe, _("\ +List absolute filename for executable which generated the corefile."), + &info_core_cmdlist); + + add_cmd ("all", class_info, info_core_cmd_all, _("\ +List all available corefile information."), + &info_core_cmdlist); c = add_cmd ("core-file", class_files, core_file_command, _("\ Use FILE as core dump for examining memory and registers.\n\ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index f4f7f1e..eb2bdc8 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -17885,6 +17885,62 @@ processes and all the threads within each process. For QNX Neutrino only, this command displays the list of all mapinfos. @end table +@node Process Information from Core Dump File +@subsection Process Information from Core Dump File +@cindex examine core dump file process information +@cindex process info via core dump file + +If your system supports the generation of core dump files (core files), you +can use them to obtain information about processes. For that, you can use +the command @code{info core} inside @value{GDBN} to report information like +the memory mappings of the process when the core dump was generated. +@code{info core} works only on systems that support core dump files, and only +when you are using a core dump file inside @value{GDBN}. + +@xref{Core File Generation}, for information on how to generate core dump +files inside @value{GDBN}. @xref{Files}, for information on invoking +@value{GDBN} in the post-mortem debugging mode. + +@table @code +@kindex info core +@cindex core dump file, process information +@item info core +@itemx info core mappings +@cindex memory address space mappings inside a core dump file +Report the memory address ranges accessible in the core dump file. Assuming +you have a core dump file and it is loaded into @value{GDBN}, the output of +the command will be similar to: + +@smallexample +(@value{GDBP}) info core mappings +Mapped address spaces: + + Start Addr End Addr Size objfile + 0x400000 0x401000 0x1000 /tmp/a.out + 0x600000 0x601000 0x1000 /tmp/a.out +0x397de00000 0x397de1f000 0x1f000 /usr/lib/debug/lib/ld.so +0x397e01e000 0x397e01f000 0x1000 /usr/lib/debug/lib/ld.so +0x397e01f000 0x397e020000 0x1000 /usr/lib/debug/lib/ld.so +0x397e020000 0x397e021000 0x1000 /usr/lib/debug/lib/ld.so +0x397e200000 0x397e391000 0x191000 /usr/lib/debug/lib/libc.so +0x397e591000 0x397e595000 0x4000 /usr/lib/debug/lib/libc.so +0x397e595000 0x397e596000 0x1000 /usr/lib/debug/lib/libc.so +0x397e596000 0x397e59c000 0x6000 +@end smallexample + +@item info core exe +Show the filename of the process that generated this core dump file. + +@smallexample +(@value{GDBP}) info core exe +exe = '/tmp/a.out' +@end smallexample + +@item info core all +Show all the information about the core dump file described under all of +the above @code{info core} subcommands. +@end table + @node DJGPP Native @subsection Features for Debugging @sc{djgpp} Programs @cindex @sc{djgpp} debugging diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp index 5b0cdf1..364a018 100644 --- a/gdb/testsuite/gdb.base/corefile.exp +++ b/gdb/testsuite/gdb.base/corefile.exp @@ -171,6 +171,13 @@ gdb_test_multiple "x/8bd buf2" "$test" { } } +# Test the `info core mappings' command. +set ws "\[ \t\]+" +set test "test info core mappings" +gdb_test "info core mappings" \ + "Mapped address spaces:.*${hex}${ws}${hex}${ws}${hex}.*" \ + $test + # test reinit_frame_cache gdb_load ${binfile}