From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15190 invoked by alias); 27 Oct 2011 17:56:34 -0000 Received: (qmail 14773 invoked by uid 22791); 27 Oct 2011 17:56:27 -0000 X-SWARE-Spam-Status: No, hits=-6.7 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_BJ,TW_RG 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; Thu, 27 Oct 2011 17:55:42 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9RHtdm4025331 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 27 Oct 2011 13:55:40 -0400 Received: from psique (ovpn-112-22.phx2.redhat.com [10.3.112.22]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p9RHtZ4w018606; Thu, 27 Oct 2011 13:55:37 -0400 From: Sergio Durigan Junior To: Eli Zaretskii Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] Implement new `info core mappings' command References: Date: Thu, 27 Oct 2011 18:09:00 -0000 In-Reply-To: (Eli Zaretskii's message of "Thu, 27 Oct 2011 03:04:06 -0400") 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-10/txt/msg00742.txt.bz2 Hello Eli, Thanks for the review. Eli Zaretskii writes: >> From: Sergio Durigan Junior >> Date: Wed, 26 Oct 2011 19:07:45 -0200 >> + while (argv != NULL && *argv != NULL) >> + { >> + if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0) >> + { >> + mappings_f = 1; >> + } >> + else if (strncmp (argv[0], "all", strlen (argv[0])) == 0) >> + { >> + all = 1; >> + } >> + argv++; >> + } > > What is this "all" stuff about? Removed. Since it only has 1 valid command (`mappings'), you're right, we don't need the `all'. >> +@cindex core dump file > > This index entry is too general, it sounds like this section describes > everything about core dump files that GDB supports. Better qualify > it, e.g. > > @cindex core dump file, list mapped memory Ok, I did my best to rewrite the @cindex using better sentences. Hope it's good now. >> One thing I am not sure is where to put the entry for this command on >> the documentation. I decided to put it below `info proc', but I'd be >> glad if you could give your opinions. > > I don't think it's good to put it in the same section as "info proc", > because we say at the beginning of the section > > 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. > > But this new command has nothing to do with /proc, and does not need > /proc support to work, right? > > If /proc is indeed irrelevant, then I'd prefer a separate @subsection > alongside this one. You'd need to add some short explanation of the > background and use case(s) for this command, but having that is a good > idea anyway: as written now, this command lands on the reader out of > the blue, more or less. Ok, thanks for the directions. I rewrote this part of the patch (see below) to address all the comments. Please, let me know what you think. Thank you, Sergio. diff --git a/gdb/NEWS b/gdb/NEWS index 5cdb63e..d04fbe6 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB has a new `info core mappings' command. It displays the memory + regions in a corefile, similar to `info proc mappings' command. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/corefile.c b/gdb/corefile.c index ce3b755..3f147f8 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,185 @@ core_file_command (char *filename, int from_tty) } +/* Helper function for `print_core_map'. It is used to iterate + over the corefile's sections and print proper information about + memory-mappings. + + BFD is the bfd used to get the sections. + SECT is the current section being "visited". + OBJ is not used. */ + +static void +print_proc_map_iter (bfd *bfd, 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); + /* Flag to indicate whether we have found something. */ + int found = 0; + /* The section's size. */ + bfd_size_type secsize; + /* We have to know the bitness of this architecture. */ + 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 = NULL; + struct objfile *objfile = NULL; + /* Fields to be printed for the proc map. */ + unsigned long start = 0, end = 0; + unsigned int size = 0; + char *filename = NULL; + + if (strncmp (proc_map_match, sect->name, proc_map_match_size) != 0) + /* This section is not useful. */ + return; + + bitness = gdbarch_addr_bit (gdbarch_from_bfd (bfd)); + + /* Unfortunately, some sections in the corefile don't have any + content inside. This is bad because we need to print, among + other things, its final address in the memory (which is + impossible to know if we don't have a size). That's why we + first need to check if the section's got anything inside it. */ + secsize = bfd_section_size (bfd, sect); + + if (secsize == 0) + { + /* Ok, the section is empty. In this case, we must look inside + ELF's Program Header, because (at least) there we have + information about the section's size. That's what we're doing + here. */ + Elf_Internal_Phdr *p = elf_tdata (bfd)->phdr; + if (p != NULL) + { + int i; + unsigned int n = elf_elfheader (bfd)->e_phnum; + for (i = 0; i < n; i++, p++) + /* For each entry in the Program Header, we have to + check if the section's initial address is equal to + the entry's virtual address. If it is, then we + have just found the section's entry in the Program + Header, and can use the entry's information to + complete missing data from the section. */ + if (sect->vma == p->p_vaddr) + { + found = 1; + break; + } + if (found) + secsize = p->p_memsz; + } + } + + size = secsize; + start = sect->vma; + end = (unsigned long) (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. */ + found = 0; + ALL_OBJSECTIONS (objfile, s) + if (obj_section_addr (s) >= start + && obj_section_addr (s) <= end) + { + found = 1; + break; + } + + if (found) + filename = s->objfile->name; + + if (bitness == 32) + printf_filtered ("\t%#10lx %#10lx %#10x %7s\n", + start, + end, + (int) size, + filename ? filename : ""); + else + printf_filtered (" %#18lx %#18lx %#10x %7s\n", + start, + end, + (int) size, + filename ? filename : ""); +} + +/* Implements the `info proc map' command when the user has provided + a corefile. */ + +static void +print_core_map (void) +{ + const char *exe; + int bitness; + + gdb_assert (core_bfd != NULL); + + bitness = gdbarch_addr_bit (gdbarch_from_bfd (core_bfd)); + + /* Getting the executable name. */ + exe = bfd_core_file_failing_command (core_bfd); + + printf_filtered (_("exe = '%s'\n"), exe); + printf_filtered (_("Mapped address spaces:\n\n")); + if (bitness == 32) + printf_filtered ("\t%10s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", "objfile"); + else + printf_filtered (" %18s %18s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", "objfile"); + + bfd_map_over_sections (core_bfd, + print_proc_map_iter, + NULL); +} + +/* Implement the `info core' command. */ + +static void +info_core_cmd (char *args, int from_tty) +{ + char **argv = NULL; + int mappings_f = 0; + struct cleanup *c = NULL; + + if (!core_bfd) + error (_("You are not using a corefile at the moment.")); + + if (args) + { + /* Break up 'args' into an argv array. */ + argv = gdb_buildargv (args); + c = make_cleanup_freeargv (argv); + } + while (argv != NULL && *argv != NULL) + { + if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0) + { + mappings_f = 1; + } + argv++; + } + + if (mappings_f) + print_core_map (); + + if (c) + do_cleanups (c); +} + /* If there are two or more functions that wish to hook into exec_file_command, this function will call all of the hook functions. */ @@ -450,6 +635,11 @@ _initialize_core (void) { struct cmd_list_element *c; + add_info ("core", info_core_cmd, _("\ +Show information about a corefile.\n\ +Specify any of the following keywords for detailed info:\n\ + mappings -- list of mapped memory regions.")); + c = add_cmd ("core-file", class_files, core_file_command, _("\ Use FILE as core dump for examining memory and registers.\n\ No arg means have no core file. This command has been superseded by the\n\ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3e78832..427811e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -17713,6 +17713,56 @@ 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 +exe = '/tmp/a.out' +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/lib64/ld-2.13.so.debug + 0x397e01e000 0x397e01f000 0x1000 /usr/lib/debug/lib64/ld-2.13.so.debug + 0x397e01f000 0x397e020000 0x1000 /usr/lib/debug/lib64/ld-2.13.so.debug + 0x397e020000 0x397e021000 0x1000 /usr/lib/debug/lib64/ld-2.13.so.debug + 0x397e200000 0x397e391000 0x191000 /usr/lib/debug/lib64/libc-2.13.so.debug + 0x397e591000 0x397e595000 0x4000 /usr/lib/debug/lib64/libc-2.13.so.debug + 0x397e595000 0x397e596000 0x1000 /usr/lib/debug/lib64/libc-2.13.so.debug + 0x397e596000 0x397e59c000 0x6000 + 0x7ffff7fd1000 0x7ffff7fd4000 0x3000 + 0x7ffff7ffd000 0x7ffff7ffe000 0x1000 + 0x7ffff7ffe000 0x7ffff7fff000 0x1000 system-supplied DSO at 0x7ffff7ffe000 + 0x7ffffffde000 0x7ffffffff000 0x21000 + 0xffffffffff600000 0xffffffffff601000 0x1000 +@end smallexample +@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..190281c 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 mapping' command. +set ws "\[ \t\]+" +set test "test info core mapping" +gdb_test "info core mapping" \ + ".*Mapped address spaces:.*${hex}${ws}${hex}${ws}${hex}.*" \ + $test + # test reinit_frame_cache gdb_load ${binfile}