* Examining copied stack contents @ 2010-07-03 10:48 Martin Schröder 2010-07-05 4:54 ` support biarch gcore? Jon Zhou 2010-07-05 18:50 ` Examining copied stack contents Petr Hluzín 0 siblings, 2 replies; 18+ messages in thread From: Martin Schröder @ 2010-07-03 10:48 UTC (permalink / raw) To: gdb Hello everyone. I'm currently implementing a high-level debugger based on GDB for a coroutine-based simulation framework. The platform is GNU/Linux on x86. That framework implements coroutines by using the C/C++ setjmp/longjmp instructions and by copying the call stack that is used by each coroutine to dynamically allocated memory on the heap. It's this latter aspect that gives me terrible headaches in GDB. My question is simply: Is it possible to point GDB to the copied contents of the call stack and tell it to print out the information contained therein? The documentation [1] does contain the following note: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - frame addr f addr Select the frame at address addr. This is useful mainly if the chaining of stack frames has been damaged by a bug, making it impossible for gdb to assign numbers properly to all frames. In addition, this can be useful when your program has multiple stacks and switches between them. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Additionally, the docs about the "info frame" command also say that it accepts memory addresses as arguments. Unfortunately, this does not seem to work as well as I anticipated. I tried several versions of the GDB, from 6.8 to the newest 7.1, but they all exhibit the same issues. When I stop the program directly after the call stack was saved, the situation presents itself as follows: The stack pointer register is at 0xbfffeec0. The first two stack frames return the following data: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (gdb) info frame 0 Stack frame at 0xbfffeef0: eip = 0x805a972 in [CODE LINE]; saved eip 0x805a588 called by frame at 0xbfffef30 source language c++. Arglist at 0xbfffeee8, args: this=0x80b3238 Locals at 0xbfffeee8, Previous frame's sp is 0xbfffeef0 Saved registers: ebp at 0xbfffeee8, eip at 0xbfffeeec (gdb) info frame 1 Stack frame at 0xbfffef30: eip = 0x805a588 in [CODE LINE]; saved eip 0x806b2a6 called by frame at 0xbfffef70, caller of frame at 0xbfffeef0 source language c++. Arglist at 0xbfffef28, args: this=0x80b2bd8 Locals at 0xbfffef28, Previous frame's sp is 0xbfffef30 Saved registers: ebx at 0xbfffef20, ebp at 0xbfffef28, esi at 0xbfffef24, eip at 0xbfffef2c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The program copied the whole stack (including a bit of safety margin) beginning with the address 0xbfffeedf to the address 0x80b39c8. Now, if I tell GDB to print information about the stack frame located at 0xbfffeef0, it does so correctly: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (gdb) info frame 0xbfffeef0 Stack frame at 0xbfffeef0: eip = 0x805a972 in [CODE LINE]; saved eip 0x805a588 called by frame at 0xbfffef30 source language c++. Arglist at 0xbfffeee8, args: this=0x80b3238 Locals at 0xbfffeee8, Previous frame's sp is 0xbfffeef0 Saved registers: ebp at 0xbfffeee8, eip at 0xbfffeeec - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - But if I point it to the exact copy of that frame, beginning with 0x80b39d9, I get the following "fail safe" information that the GDB also prints when I point it to *any* arbitrary address: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (gdb) info frame 0x80b39d9 Stack frame at 0x80b39d9: eip = 0x0; saved eip 0x80b39c8 called by frame at 0xbfffeef0 Arglist at 0xbfffeebc, args: Locals at 0xbfffeebc, Previous frame's sp is 0xbfffeec4 Saved registers: eip at 0xbfffeec0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - But if I examine the memory ranges, they are absolutely identical: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (gdb) x/8x 0x80b39d9 0x80b39d9: 0x080b3238 0x080b2bd8 0x080b2ca4 0x080b2ca4 0x80b39e9: 0x0021a73c 0x080b2bc8 0x080b3238 0x00000000 (gdb) x/8x 0xbfffeef0 0xbfffeef0: 0x080b3238 0x080b2bd8 0x080b2ca4 0x080b2ca4 0xbfffef00: 0x0021a73c 0x080b2bc8 0x080b3238 0x00000000 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Obviously, the GDB doesn't even attempt to interpret the given address as a stack frame. I am aware that the GDB needs debugging symbols to make any sense out of the stack (after all, the frame size depends on the actual call they represent); and also that the addresses inside the copied stack can't be followed, because they still point to the original memory addresses. But I'm also aware that the GDB *should be* able to do what I want it to do. For one, the documentation explicitly mentions that the feature works with programs that utilize multiple stacks. Furthermore, the GDB is also able to debug Multi-Threaded programs, which also need to save the call stack to dynamic heap memory. So, my question is: Is it possible to examine the copied stack? And if yes, what do I need to give to the GDB to allow it? Thanks in advance, Martin Schröder. [1] - http://sourceware.org/gdb/current/onlinedocs/gdb/Selection.html ^ permalink raw reply [flat|nested] 18+ messages in thread
* support biarch gcore? 2010-07-03 10:48 Examining copied stack contents Martin Schröder @ 2010-07-05 4:54 ` Jon Zhou 2010-07-05 7:12 ` Jan Kratochvil 2010-07-05 18:50 ` Examining copied stack contents Petr Hluzín 1 sibling, 1 reply; 18+ messages in thread From: Jon Zhou @ 2010-07-05 4:54 UTC (permalink / raw) To: gdb Hi there Regarding this case, does the current release solve it ? I just tried the patch but looks it doesn't work Thanks jon http://sourceware.org/ml/gdb/2009-03/msg00010.html Re: Problem viewing gcore of 32 bit binary on 64 bit SLES 10.1, gdb 6.6 From: Jan Kratochvil <jan dot kratochvil at redhat dot com> To: Shane G <pachoo at gmail dot com> Cc: gdb at sourceware dot org Date: Tue, 3 Mar 2009 00:10:28 +0100 Subject: Re: Problem viewing gcore of 32 bit binary on 64 bit SLES 10.1, gdb 6.6 References: <985ad4e70903021500u594a4c4w30eff9ae287f5e8d@mail.gmail.com> -------------------------------------------------------------------------------- On Tue, 03 Mar 2009 00:00:57 +0100, Shane G wrote: > I'm unable to view any usable information from a gcore that I've run > against a 32 bit binary running on a 64 bit version of SLES 10.1. from your description IMO the core file is primarily generated wrong by gcore. If you somewhere get a correct 32bit core file expecting gdb-x86_64 probably reads it fine on your system. > This GDB was configured as "x86_64-suse-linux"... At least in http://download.opensuse.org/repositories/home:/dgollub/openSUSE_Factory/src/gdb-6.8-14.80.src.rpm I see no gcore biarch patch and FSF GDB does not support biarch gcore (in this case i386-on-x86_64). You may port there the patch: http://cvs.fedora.redhat.com/viewvc/rpms/gdb/devel/gdb-6.5-gcore-i386-on-amd64.patch?revision=1.6 Regards, Jan ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-05 4:54 ` support biarch gcore? Jon Zhou @ 2010-07-05 7:12 ` Jan Kratochvil 2010-07-05 11:55 ` Mark Kettenis 0 siblings, 1 reply; 18+ messages in thread From: Jan Kratochvil @ 2010-07-05 7:12 UTC (permalink / raw) To: Jon Zhou; +Cc: gdb On Mon, 05 Jul 2010 06:52:37 +0200, Jon Zhou wrote: > Regarding this case, does the current release solve it ? I just tried the > patch but looks it doesn't work Issue is tracked at: amd64 gdb generates corrupted 32bit core file http://sourceware.org/bugzilla/show_bug.cgi?id=11467 There was a patchset by H.J.Lu but it did not make it in FSF GDB: PATCH: PR corefiles/11467: amd64 gdb generates corrupted 32bit core file http://sourceware.org/ml/gdb-patches/2010-04/msg00315.html with the last mail of this thread: http://sourceware.org/ml/gdb-patches/2010-04/msg00427.html > Please stop sending diffs until you understand how the code is > supposed to work. The Fedora patch http://cvs.fedoraproject.org/viewvc/rpms/gdb/devel/gdb-6.5-gcore-i386-on-amd64.patch?content-type=text%2Fplain&view=co will be rebased or replaced by H.J.Lu's one for gdb-7.2-pre by 2010-07-27. Thanks, Jan > References: <4A25DE879BC24E8DAEAEBD722E363025@igor> > In-Reply-To: <4A25DE879BC24E8DAEAEBD722E363025@igor> Please do not reply to the existing mail "Examining copied stack contents" when you start a new thread. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-05 7:12 ` Jan Kratochvil @ 2010-07-05 11:55 ` Mark Kettenis 2010-07-06 20:48 ` Ulrich Weigand 0 siblings, 1 reply; 18+ messages in thread From: Mark Kettenis @ 2010-07-05 11:55 UTC (permalink / raw) To: jan.kratochvil; +Cc: Jon.Zhou, gdb > Date: Mon, 5 Jul 2010 09:12:35 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > > On Mon, 05 Jul 2010 06:52:37 +0200, Jon Zhou wrote: > > Regarding this case, does the current release solve it ? I just tried the > > patch but looks it doesn't work > > Issue is tracked at: > amd64 gdb generates corrupted 32bit core file > http://sourceware.org/bugzilla/show_bug.cgi?id=11467 > > There was a patchset by H.J.Lu but it did not make it in FSF GDB: > PATCH: PR corefiles/11467: amd64 gdb generates corrupted 32bit core file > http://sourceware.org/ml/gdb-patches/2010-04/msg00315.html > with the last mail of this thread: > http://sourceware.org/ml/gdb-patches/2010-04/msg00427.html > > Please stop sending diffs until you understand how the code is > > supposed to work. > > The Fedora patch > http://cvs.fedoraproject.org/viewvc/rpms/gdb/devel/gdb-6.5-gcore-i386-on-amd64.patch?content-type=text%2Fplain&view=co > > will be rebased or replaced by H.J.Lu's one for gdb-7.2-pre by 2010-07-27. The proper way to fix the issue is to add proper cross-core support to BFD for i386 and amd64 like was done for powerpc/powerpc64 a couple of years ago. See the thread starting at: http://sourceware.org/ml/binutils/2010-04/msg00225.html Perhaps I need to resubmit that diff now that things have settled down a bit. With that diff in, there still is a GDB issue that needs to be resolved. The core generation code in linux-nat.c:linux_nat_do_thread_registers() allocates a buffer of type gdb_gregset_t to store the registers. Since its size differs between i386 and amd64 the size passed to _reget_from_core_section() is always the size of the amd64 gdb_gregset_t. Since the current code checks for an exact match, it fails to return a regset, and things go downhill from there. Fixing the code in linux-nat.c is a bit nasty: * The definition of the 32-bit version of gdb_gregset_t isn't readily available on 64-bit systems. * The code is used on all Linux platforms and only a few of them are bi-arch. An alternative solution would be to make _regset_from_core_section() a little bit more forgiving. The diff below works since the size of the amd64 gdb_gregset_t is larger than the i386-version. 2010-07-05 Mark Kettenis <kettenis@gnu.org> * i386-tdep.c (i386_supply_gregset, i386_collect_gregset) (i386_regset_from_core_section): Relax check for size of .reg section. Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.316 diff -u -p -r1.316 i386-tdep.c --- i386-tdep.c 22 Jun 2010 02:15:45 -0000 1.316 +++ i386-tdep.c 5 Jul 2010 11:50:55 -0000 @@ -2775,7 +2775,7 @@ i386_supply_gregset (const struct regset const gdb_byte *regs = gregs; int i; - gdb_assert (len == tdep->sizeof_gregset); + gdb_assert (len >= tdep->sizeof_gregset); for (i = 0; i < tdep->gregset_num_regs; i++) { @@ -2799,7 +2799,7 @@ i386_collect_gregset (const struct regse gdb_byte *regs = gregs; int i; - gdb_assert (len == tdep->sizeof_gregset); + gdb_assert (len >= tdep->sizeof_gregset); for (i = 0; i < tdep->gregset_num_regs; i++) { @@ -2880,7 +2880,7 @@ i386_regset_from_core_section (struct gd { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset) + if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset) { if (tdep->gregset == NULL) tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset, ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-05 11:55 ` Mark Kettenis @ 2010-07-06 20:48 ` Ulrich Weigand 2010-07-06 21:29 ` Mark Kettenis 0 siblings, 1 reply; 18+ messages in thread From: Ulrich Weigand @ 2010-07-06 20:48 UTC (permalink / raw) To: Mark Kettenis; +Cc: jan.kratochvil, Jon.Zhou, gdb Mark Kettenis wrote: > Fixing the code in linux-nat.c is a bit nasty: > > * The definition of the 32-bit version of gdb_gregset_t isn't readily > available on 64-bit systems. > > * The code is used on all Linux platforms and only a few of them are > bi-arch. This was really supposed to be fixed by the gdbarch_core_regset_sections mechanism, which provides the names and sizes of all register sets expected in a core file for the current architecture. However, it seems that this mechanism isn't currently used for .reg itself, only for the other sections. While it is true that .reg needs to be handled somewhat specially, it should still be possible to get its size from gdbarch_core_regset_sections, and thus avoid the need to use the gdb_gregset_t type. Unfortunately, it also turned out that the section sizes provided for .reg in those targets that have gdbarch_core_regset_sections, while currently unused, were also nearly all wrong ... The following patch fixes those sizes, and changes linux-nat.c to use them. Tested on powerpc64-linux (-m64 / -m32), amd64-linux (-m64 / -m32), and i386-linux with no regressions. In fact, it appears to fix all pre-existing gcore-related failures on amd64 -m32 ... Thoughts? Bye, Ulrich ChangeLog: * linux-nat.c (linux_nat_do_thread_registers): Use section size from gdbarch_core_regset_sections also for .reg if present. * amd64-linux-tdep.c (amd64_linux_regset_sections): Fix incorrect section size for .reg. * ppc-linux-tdep.c (ppc_linux_vsx_regset_sections): Likewise. (ppc_linux_vmx_regset_sections): Likewise. (ppc_linux_fp_regset_sections): Likewise. (ppc64_linux_vsx_regset_sections): New variable. (ppc64_linux_vmx_regset_sections): Likewise. (ppc64_linux_fp_regset_sections): Likewise. (ppc_linux_init_abi): Install core_regset_section lists appropriate for current word size. Index: gdb/amd64-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/amd64-linux-tdep.c,v retrieving revision 1.37 diff -u -p -r1.37 amd64-linux-tdep.c --- gdb/amd64-linux-tdep.c 22 Apr 2010 20:02:55 -0000 1.37 +++ gdb/amd64-linux-tdep.c 6 Jul 2010 20:24:45 -0000 @@ -52,7 +52,7 @@ /* Supported register note sections. */ static struct core_regset_section amd64_linux_regset_sections[] = { - { ".reg", 144, "general-purpose" }, + { ".reg", 27 * 8, "general-purpose" }, { ".reg2", 512, "floating-point" }, { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" }, { NULL, 0 } Index: gdb/linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/linux-nat.c,v retrieving revision 1.172 diff -u -p -r1.172 linux-nat.c --- gdb/linux-nat.c 1 Jul 2010 15:36:16 -0000 1.172 +++ gdb/linux-nat.c 6 Jul 2010 20:24:46 -0000 @@ -4134,8 +4134,6 @@ linux_nat_do_thread_registers (bfd *obfd char *note_data, int *note_size, enum target_signal stop_signal) { - gdb_gregset_t gregs; - gdb_fpregset_t fpregs; unsigned long lwp = ptid_get_lwp (ptid); struct gdbarch *gdbarch = target_gdbarch; struct regcache *regcache = get_thread_arch_regcache (ptid, gdbarch); @@ -4153,21 +4151,6 @@ linux_nat_do_thread_registers (bfd *obfd core_regset_p = gdbarch_regset_from_core_section_p (gdbarch); sect_list = gdbarch_core_regset_sections (gdbarch); - if (core_regset_p - && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg", - sizeof (gregs))) != NULL - && regset->collect_regset != NULL) - regset->collect_regset (regset, regcache, -1, - &gregs, sizeof (gregs)); - else - fill_gregset (regcache, &gregs, -1); - - note_data = (char *) elfcore_write_prstatus (obfd, - note_data, - note_size, - lwp, - stop_signal, &gregs); - /* The loop below uses the new struct core_regset_section, which stores the supported section names and sizes for the core file. Note that note PRSTATUS needs to be treated specially. But the other notes are @@ -4175,12 +4158,6 @@ linux_nat_do_thread_registers (bfd *obfd if (core_regset_p && sect_list != NULL) while (sect_list->sect_name != NULL) { - /* .reg was already handled above. */ - if (strcmp (sect_list->sect_name, ".reg") == 0) - { - sect_list++; - continue; - } regset = gdbarch_regset_from_core_section (gdbarch, sect_list->sect_name, sect_list->size); @@ -4188,12 +4165,16 @@ linux_nat_do_thread_registers (bfd *obfd gdb_regset = xmalloc (sect_list->size); regset->collect_regset (regset, regcache, -1, gdb_regset, sect_list->size); - note_data = (char *) elfcore_write_register_note (obfd, - note_data, - note_size, - sect_list->sect_name, - gdb_regset, - sect_list->size); + + if (strcmp (sect_list->sect_name, ".reg") == 0) + note_data = (char *) elfcore_write_prstatus + (obfd, note_data, note_size, + lwp, stop_signal, gdb_regset); + else + note_data = (char *) elfcore_write_register_note + (obfd, note_data, note_size, + sect_list->sect_name, gdb_regset, + sect_list->size); xfree (gdb_regset); sect_list++; } @@ -4203,6 +4184,24 @@ linux_nat_do_thread_registers (bfd *obfd the new support, the code below should be deleted. */ else { + gdb_gregset_t gregs; + gdb_fpregset_t fpregs; + + if (core_regset_p + && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg", + sizeof (gregs))) != NULL + && regset->collect_regset != NULL) + regset->collect_regset (regset, regcache, -1, + &gregs, sizeof (gregs)); + else + fill_gregset (regcache, &gregs, -1); + + note_data = (char *) elfcore_write_prstatus (obfd, + note_data, + note_size, + lwp, + stop_signal, &gregs); + if (core_regset_p && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", sizeof (fpregs))) != NULL Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.121 diff -u -p -r1.121 ppc-linux-tdep.c --- gdb/ppc-linux-tdep.c 15 Apr 2010 20:19:24 -0000 1.121 +++ gdb/ppc-linux-tdep.c 6 Jul 2010 20:24:46 -0000 @@ -516,7 +516,7 @@ ppc64_standard_linkage1_target (struct f static struct core_regset_section ppc_linux_vsx_regset_sections[] = { - { ".reg", 268, "general-purpose" }, + { ".reg", 48 * 4, "general-purpose" }, { ".reg2", 264, "floating-point" }, { ".reg-ppc-vmx", 544, "ppc Altivec" }, { ".reg-ppc-vsx", 256, "POWER7 VSX" }, @@ -525,7 +525,7 @@ static struct core_regset_section ppc_li static struct core_regset_section ppc_linux_vmx_regset_sections[] = { - { ".reg", 268, "general-purpose" }, + { ".reg", 48 * 4, "general-purpose" }, { ".reg2", 264, "floating-point" }, { ".reg-ppc-vmx", 544, "ppc Altivec" }, { NULL, 0} @@ -533,7 +533,31 @@ static struct core_regset_section ppc_li static struct core_regset_section ppc_linux_fp_regset_sections[] = { - { ".reg", 268, "general-purpose" }, + { ".reg", 48 * 4, "general-purpose" }, + { ".reg2", 264, "floating-point" }, + { NULL, 0} +}; + +static struct core_regset_section ppc64_linux_vsx_regset_sections[] = +{ + { ".reg", 48 * 8, "general-purpose" }, + { ".reg2", 264, "floating-point" }, + { ".reg-ppc-vmx", 544, "ppc Altivec" }, + { ".reg-ppc-vsx", 256, "POWER7 VSX" }, + { NULL, 0} +}; + +static struct core_regset_section ppc64_linux_vmx_regset_sections[] = +{ + { ".reg", 48 * 8, "general-purpose" }, + { ".reg2", 264, "floating-point" }, + { ".reg-ppc-vmx", 544, "ppc Altivec" }, + { NULL, 0} +}; + +static struct core_regset_section ppc64_linux_fp_regset_sections[] = +{ + { ".reg", 48 * 8, "general-purpose" }, { ".reg2", 264, "floating-point" }, { NULL, 0} }; @@ -1507,6 +1531,19 @@ ppc_linux_init_abi (struct gdbarch_info set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpcle"); else set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); + + /* Supported register sections. */ + if (tdesc_find_feature (info.target_desc, + "org.gnu.gdb.power.vsx")) + set_gdbarch_core_regset_sections (gdbarch, + ppc_linux_vsx_regset_sections); + else if (tdesc_find_feature (info.target_desc, + "org.gnu.gdb.power.altivec")) + set_gdbarch_core_regset_sections (gdbarch, + ppc_linux_vmx_regset_sections); + else + set_gdbarch_core_regset_sections (gdbarch, + ppc_linux_fp_regset_sections); } if (tdep->wordsize == 8) @@ -1533,20 +1570,23 @@ ppc_linux_init_abi (struct gdbarch_info set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpcle"); else set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); + + /* Supported register sections. */ + if (tdesc_find_feature (info.target_desc, + "org.gnu.gdb.power.vsx")) + set_gdbarch_core_regset_sections (gdbarch, + ppc64_linux_vsx_regset_sections); + else if (tdesc_find_feature (info.target_desc, + "org.gnu.gdb.power.altivec")) + set_gdbarch_core_regset_sections (gdbarch, + ppc64_linux_vmx_regset_sections); + else + set_gdbarch_core_regset_sections (gdbarch, + ppc64_linux_fp_regset_sections); } set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); - /* Supported register sections. */ - if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.vsx")) - set_gdbarch_core_regset_sections (gdbarch, ppc_linux_vsx_regset_sections); - else if (tdesc_find_feature (info.target_desc, - "org.gnu.gdb.power.altivec")) - set_gdbarch_core_regset_sections (gdbarch, ppc_linux_vmx_regset_sections); - else - set_gdbarch_core_regset_sections (gdbarch, ppc_linux_fp_regset_sections); - /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-06 20:48 ` Ulrich Weigand @ 2010-07-06 21:29 ` Mark Kettenis 2010-07-07 12:30 ` Ulrich Weigand 0 siblings, 1 reply; 18+ messages in thread From: Mark Kettenis @ 2010-07-06 21:29 UTC (permalink / raw) To: uweigand; +Cc: jan.kratochvil, Jon.Zhou, gdb > Date: Tue, 6 Jul 2010 22:48:44 +0200 (CEST) > From: "Ulrich Weigand" <uweigand@de.ibm.com> > > Mark Kettenis wrote: > > > Fixing the code in linux-nat.c is a bit nasty: > > > > * The definition of the 32-bit version of gdb_gregset_t isn't readily > > available on 64-bit systems. > > > > * The code is used on all Linux platforms and only a few of them are > > bi-arch. > > This was really supposed to be fixed by the gdbarch_core_regset_sections > mechanism, which provides the names and sizes of all register sets > expected in a core file for the current architecture. > > However, it seems that this mechanism isn't currently used for .reg > itself, only for the other sections. While it is true that .reg needs > to be handled somewhat specially, it should still be possible to get > its size from gdbarch_core_regset_sections, and thus avoid the need > to use the gdb_gregset_t type. > > Unfortunately, it also turned out that the section sizes provided for > .reg in those targets that have gdbarch_core_regset_sections, while > currently unused, were also nearly all wrong ... > > The following patch fixes those sizes, and changes linux-nat.c to > use them. > > Tested on powerpc64-linux (-m64 / -m32), amd64-linux (-m64 / -m32), > and i386-linux with no regressions. In fact, it appears to fix all > pre-existing gcore-related failures on amd64 -m32 ... > > Thoughts? Although I don't feel qualified to judge the powerpc bits, this makes quite a bit of sense to me. And yes, the value for amd64-linux is obviously wrong. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-06 21:29 ` Mark Kettenis @ 2010-07-07 12:30 ` Ulrich Weigand 2010-07-08 2:35 ` Jon Zhou 2010-07-08 4:47 ` H.J. Lu 0 siblings, 2 replies; 18+ messages in thread From: Ulrich Weigand @ 2010-07-07 12:30 UTC (permalink / raw) To: Mark Kettenis; +Cc: jan.kratochvil, Jon.Zhou, gdb, gdb-patches Mark Kettenis wrote: > > Date: Tue, 6 Jul 2010 22:48:44 +0200 (CEST) > > From: "Ulrich Weigand" <uweigand@de.ibm.com> > > > > Unfortunately, it also turned out that the section sizes provided for > > .reg in those targets that have gdbarch_core_regset_sections, while > > currently unused, were also nearly all wrong ... > > > > The following patch fixes those sizes, and changes linux-nat.c to > > use them. > Although I don't feel qualified to judge the powerpc bits, this makes > quite a bit of sense to me. And yes, the value for amd64-linux is > obviously wrong. OK, thanks! I've checked the patch in now. Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: support biarch gcore? 2010-07-07 12:30 ` Ulrich Weigand @ 2010-07-08 2:35 ` Jon Zhou 2010-07-08 11:17 ` Ulrich Weigand 2010-07-08 4:47 ` H.J. Lu 1 sibling, 1 reply; 18+ messages in thread From: Jon Zhou @ 2010-07-08 2:35 UTC (permalink / raw) To: Ulrich Weigand, Mark Kettenis; +Cc: jan.kratochvil, gdb, gdb-patches One more question The patch is enable gdb to read the coredump generated by gcore Or enable gcore to generate a readable coredump Or both? Thanks jon -----Original Message----- From: Ulrich Weigand [mailto:uweigand@de.ibm.com] Sent: Wednesday, July 07, 2010 8:31 PM To: Mark Kettenis Cc: jan.kratochvil@redhat.com; Jon Zhou; gdb@sourceware.org; gdb-patches@sourceware.org Subject: Re: support biarch gcore? Mark Kettenis wrote: > > Date: Tue, 6 Jul 2010 22:48:44 +0200 (CEST) > > From: "Ulrich Weigand" <uweigand@de.ibm.com> > > > > Unfortunately, it also turned out that the section sizes provided for > > .reg in those targets that have gdbarch_core_regset_sections, while > > currently unused, were also nearly all wrong ... > > > > The following patch fixes those sizes, and changes linux-nat.c to > > use them. > Although I don't feel qualified to judge the powerpc bits, this makes > quite a bit of sense to me. And yes, the value for amd64-linux is > obviously wrong. OK, thanks! I've checked the patch in now. Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-08 2:35 ` Jon Zhou @ 2010-07-08 11:17 ` Ulrich Weigand 0 siblings, 0 replies; 18+ messages in thread From: Ulrich Weigand @ 2010-07-08 11:17 UTC (permalink / raw) To: Jon Zhou; +Cc: Mark Kettenis, jan.kratochvil, gdb, gdb-patches Jon Zhou wrote: > One more question > > The patch is enable gdb to read the coredump generated by gcore > Or enable gcore to generate a readable coredump > Or both? The patch fixes the gcore command to generate a coredump in the proper 32-bit format. Reading in a 32-bit format coredump did already work correctly before (e.g. a coredump generated by the kernel). Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-07 12:30 ` Ulrich Weigand 2010-07-08 2:35 ` Jon Zhou @ 2010-07-08 4:47 ` H.J. Lu 2010-07-08 5:05 ` H.J. Lu 1 sibling, 1 reply; 18+ messages in thread From: H.J. Lu @ 2010-07-08 4:47 UTC (permalink / raw) To: Ulrich Weigand; +Cc: Mark Kettenis, jan.kratochvil, Jon.Zhou, gdb, gdb-patches On Wed, Jul 7, 2010 at 5:30 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote: > Mark Kettenis wrote: >> > Date: Tue, 6 Jul 2010 22:48:44 +0200 (CEST) >> > From: "Ulrich Weigand" <uweigand@de.ibm.com> >> > >> > Unfortunately, it also turned out that the section sizes provided for >> > .reg in those targets that have gdbarch_core_regset_sections, while >> > currently unused, were also nearly all wrong ... >> > >> > The following patch fixes those sizes, and changes linux-nat.c to >> > use them. > >> Although I don't feel qualified to judge the powerpc bits, this makes >> quite a bit of sense to me. And yes, the value for amd64-linux is >> obviously wrong. > > OK, thanks! > > I've checked the patch in now. > Does this fix http://sourceware.org/bugzilla/show_bug.cgi?id=11467 You can verify it with the testcase in http://sourceware.org/ml/gdb-patches/2010-04/msg00425.html -- H.J. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-08 4:47 ` H.J. Lu @ 2010-07-08 5:05 ` H.J. Lu 2010-07-08 11:15 ` Ulrich Weigand 0 siblings, 1 reply; 18+ messages in thread From: H.J. Lu @ 2010-07-08 5:05 UTC (permalink / raw) To: Ulrich Weigand; +Cc: Mark Kettenis, jan.kratochvil, Jon.Zhou, gdb, gdb-patches [-- Attachment #1: Type: text/plain, Size: 1107 bytes --] On Wed, Jul 7, 2010 at 9:47 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Wed, Jul 7, 2010 at 5:30 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote: >> Mark Kettenis wrote: >>> > Date: Tue, 6 Jul 2010 22:48:44 +0200 (CEST) >>> > From: "Ulrich Weigand" <uweigand@de.ibm.com> >>> > >>> > Unfortunately, it also turned out that the section sizes provided for >>> > .reg in those targets that have gdbarch_core_regset_sections, while >>> > currently unused, were also nearly all wrong ... >>> > >>> > The following patch fixes those sizes, and changes linux-nat.c to >>> > use them. >> >>> Although I don't feel qualified to judge the powerpc bits, this makes >>> quite a bit of sense to me. And yes, the value for amd64-linux is >>> obviously wrong. >> >> OK, thanks! >> >> I've checked the patch in now. >> > > Does this fix > > http://sourceware.org/bugzilla/show_bug.cgi?id=11467 > It works. Here is a patch to add a testcase. OK to install? Thanks. -- H.J. -- 2010-07-07 H.J. Lu <hongjiu.lu@intel.com> PR corefiles/11467 * gdb.arch/amd64-gcore32.exp: New. [-- Attachment #2: gdb-32bit-8.patch --] [-- Type: text/x-csrc, Size: 7530 bytes --] 2010-07-07 H.J. Lu <hongjiu.lu@intel.com> PR corefiles/11467 * gdb.arch/amd64-gcore32.exp: New. diff --git a/gdb/testsuite/gdb.arch/amd64-gcore32.exp b/gdb/testsuite/gdb.arch/amd64-gcore32.exp new file mode 100644 index 0000000..66f733d --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-gcore32.exp @@ -0,0 +1,227 @@ +# Copyright 2010 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if $tracelevel then { + strace $tracelevel +} + +if { ![istarget x86_64-*-linux* ] } { + verbose "Skipping amd64-linux 32bit gcore tests." + return +} + +set testfile "amd64-gcore32" +set srcfile gcore.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-m32"]] != "" } { + untested amd64-gcore32.exp + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Does this gdb support gcore? +send_gdb "help gcore\n" +gdb_expect { + -re "Undefined command: .gcore.*$gdb_prompt $" { + # gcore command not supported -- nothing to test here. + unsupported "gdb does not support gcore on this target" + return -1; + } + -re "Save a core file .*$gdb_prompt $" { + pass "help gcore" + } + -re ".*$gdb_prompt $" { + fail "help gcore" + } + timeout { + fail "help gcore (timeout)" + } +} + +if { ! [ runto_main ] } then { + untested amd64-gcore32.exp + return -1 +} + +proc capture_command_output { command prefix } { + global gdb_prompt + global expect_out + + set output_string "" + gdb_test_multiple "$command" "capture_command_output for $command" { + -re "${command}\[\r\n\]+${prefix}(.*)\[\r\n\]+$gdb_prompt $" { + set output_string $expect_out(1,string) + } + } + return $output_string +} + +gdb_test "break terminal_func" "Breakpoint .* at .*${srcfile}, line .*" \ + "set breakpoint at terminal_func" + +gdb_test "continue" "Breakpoint .* terminal_func.*" \ + "continue to terminal_func" + +set print_prefix ".\[0123456789\]* = " + +set pre_corefile_backtrace [capture_command_output "backtrace" ""] +set pre_corefile_regs [capture_command_output "info registers" ""] +set pre_corefile_allregs [capture_command_output "info all-reg" ""] +set pre_corefile_static_array \ + [capture_command_output "print static_array" "$print_prefix"] +set pre_corefile_uninit_array \ + [capture_command_output "print un_initialized_array" "$print_prefix"] +set pre_corefile_heap_string \ + [capture_command_output "print heap_string" "$print_prefix"] +set pre_corefile_local_array \ + [capture_command_output "print array_func::local_array" "$print_prefix"] +set pre_corefile_extern_array \ + [capture_command_output "print extern_array" "$print_prefix"] + +set escapedfilename [string_to_regexp ${objdir}/${subdir}/gcore.test] + +set core_supported 0 +gdb_test_multiple "gcore ${objdir}/${subdir}/gcore.test" \ + "save a corefile" \ +{ + -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" { + pass "save a corefile" + global core_supported + set core_supported 1 + } + -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" { + unsupported "save a corefile" + global core_supported + set core_supported 0 + } +} + +if {!$core_supported} { + return -1 +} + +# Now restart gdb and load the corefile. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +send_gdb "core ${objdir}/${subdir}/gcore.test\n" +gdb_expect { + -re ".* is not a core dump:.*$gdb_prompt $" { + fail "re-load generated corefile (bad file format)" + # No use proceeding from here. + return; + } + -re ".*: No such file or directory.*$gdb_prompt $" { + fail "re-load generated corefile (file not found)" + # No use proceeding from here. + return; + } + -re ".*Couldn't find .* registers in core file.*$gdb_prompt $" { + fail "re-load generated corefile (incomplete note section)" + } + -re "Core was generated by .*$gdb_prompt $" { + pass "re-load generated corefile" + } + -re ".*$gdb_prompt $" { + fail "re-load generated corefile" + } + timeout { + fail "re-load generated corefile (timeout)" + } +} + +send_gdb "where\n" +gdb_expect_list "where in corefile" ".*$gdb_prompt $" { + ".*\[\r\n\]+#0 .* terminal_func \\(\\) at " + ".*\[\r\n\]+#1 .* array_func \\(\\) at " + ".*\[\r\n\]+#2 .* factorial_func \\(value=1\\) at " + ".*\[\r\n\]+#3 .* factorial_func \\(value=2\\) at " + ".*\[\r\n\]+#4 .* factorial_func \\(value=3\\) at " + ".*\[\r\n\]+#5 .* factorial_func \\(value=4\\) at " + ".*\[\r\n\]+#6 .* factorial_func \\(value=5\\) at " + ".*\[\r\n\]+#7 .* factorial_func \\(value=6\\) at " + ".*\[\r\n\]+#8 .* main \\(.*\\) at " +} + +set post_corefile_regs [capture_command_output "info registers" ""] +if ![string compare $pre_corefile_regs $post_corefile_regs] then { + pass "corefile restored general registers" +} else { + fail "corefile restored general registers" +} + +set post_corefile_allregs [capture_command_output "info all-reg" ""] +if ![string compare $pre_corefile_allregs $post_corefile_allregs] then { + pass "corefile restored all registers" +} else { + fail "corefile restored all registers" +} + +set post_corefile_extern_array \ + [capture_command_output "print extern_array" "$print_prefix"] +if ![string compare $pre_corefile_extern_array $post_corefile_extern_array] { + pass "corefile restored extern array" +} else { + fail "corefile restored extern array" +} + +set post_corefile_static_array \ + [capture_command_output "print static_array" "$print_prefix"] +if ![string compare $pre_corefile_static_array $post_corefile_static_array] { + pass "corefile restored static array" +} else { + fail "corefile restored static array" +} + +set post_corefile_uninit_array \ + [capture_command_output "print un_initialized_array" "$print_prefix"] +if ![string compare $pre_corefile_uninit_array $post_corefile_uninit_array] { + pass "corefile restored un-initialized array" +} else { + fail "corefile restored un-initialized array" +} + +set post_corefile_heap_string \ + [capture_command_output "print heap_string" "$print_prefix"] +if ![string compare $pre_corefile_heap_string $post_corefile_heap_string] { + pass "corefile restored heap array" +} else { + fail "corefile restored heap array" +} + +set post_corefile_local_array \ + [capture_command_output "print array_func::local_array" "$print_prefix"] +if ![string compare $pre_corefile_local_array $post_corefile_local_array] { + pass "corefile restored stack array" +} else { + fail "corefile restored stack array" +} + +set post_corefile_backtrace [capture_command_output "backtrace" ""] +if ![string compare $pre_corefile_backtrace $post_corefile_backtrace] { + pass "corefile restored backtrace" +} else { + fail "corefile restored backtrace" +} ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-08 5:05 ` H.J. Lu @ 2010-07-08 11:15 ` Ulrich Weigand 2010-07-08 13:52 ` H.J. Lu 0 siblings, 1 reply; 18+ messages in thread From: Ulrich Weigand @ 2010-07-08 11:15 UTC (permalink / raw) To: H.J. Lu; +Cc: Mark Kettenis, jan.kratochvil, Jon.Zhou, gdb, gdb-patches H.J. Lu wrote: > It works. Here is a patch to add a testcase. OK to install? Maybe I'm missing something, but it looks like this is an identical copy of the gcore.exp test, except that the executable is built with -m32, right? What does this test check that wouldn't already be checked by running make check RUNTESTFLAGS="--target_board='unix/-m32' gcore.exp" ? Since you should be running the full -m32 testsuite anyway if you care about the bi-arch debugger, I don't think we want to duplicate this test case for no real gain ... Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-08 11:15 ` Ulrich Weigand @ 2010-07-08 13:52 ` H.J. Lu 2010-07-21 22:45 ` Joseph S. Myers 0 siblings, 1 reply; 18+ messages in thread From: H.J. Lu @ 2010-07-08 13:52 UTC (permalink / raw) To: Ulrich Weigand; +Cc: Mark Kettenis, jan.kratochvil, Jon.Zhou, gdb, gdb-patches On Thu, Jul 8, 2010 at 4:15 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote: > H.J. Lu wrote: > >> It works. Here is a patch to add a testcase. OK to install? > > Maybe I'm missing something, but it looks like this is an identical > copy of the gcore.exp test, except that the executable is built > with -m32, right? > > What does this test check that wouldn't already be checked by running > make check RUNTESTFLAGS="--target_board='unix/-m32' gcore.exp" > ? > > Since you should be running the full -m32 testsuite anyway if you care > about the bi-arch debugger, I don't think we want to duplicate this > test case for no real gain ... > Very good point. There are some arch specific tests which are either 32bit or 64bit. Currently, we check target. It doesn't work -m32. We need something like /* { dg-require-effective-target lp64 } */ /* { dg-require-effective-target ilp32 } */ -- H.J. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: support biarch gcore? 2010-07-08 13:52 ` H.J. Lu @ 2010-07-21 22:45 ` Joseph S. Myers 0 siblings, 0 replies; 18+ messages in thread From: Joseph S. Myers @ 2010-07-21 22:45 UTC (permalink / raw) To: H.J. Lu Cc: Ulrich Weigand, Mark Kettenis, jan.kratochvil, Jon.Zhou, gdb, gdb-patches On Thu, 8 Jul 2010, H.J. Lu wrote: > Very good point. There are some arch specific tests which are either > 32bit or 64bit. Currently, we check target. It doesn't work -m32. We > need something like > > /* { dg-require-effective-target lp64 } */ > /* { dg-require-effective-target ilp32 } */ I noted the issue with GDB testcases hardcoding target name tests in a previous discussion <http://sourceware.org/ml/gdb-patches/2010-03/msg00711.html>, and I think adopting GCC-style effective target support would be a good solution. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Examining copied stack contents 2010-07-03 10:48 Examining copied stack contents Martin Schröder 2010-07-05 4:54 ` support biarch gcore? Jon Zhou @ 2010-07-05 18:50 ` Petr Hluzín 2010-07-05 20:18 ` Martin Schröder 2010-07-07 17:29 ` Martin Schröder 1 sibling, 2 replies; 18+ messages in thread From: Petr Hluzín @ 2010-07-05 18:50 UTC (permalink / raw) To: Martin Schröder; +Cc: gdb Hello Martin and list On 3 July 2010 12:46, Martin Schröder <gschroeder@onlinehome.de> wrote: > Hello everyone. > > I'm currently implementing a high-level debugger based on GDB for a > coroutine-based simulation framework. The platform is GNU/Linux on x86. > > That framework implements coroutines by using the C/C++ setjmp/longjmp > instructions and by copying the call stack that is used by each coroutine to > dynamically allocated memory on the heap. It's this latter aspect that gives > me terrible headaches in GDB. > > My question is simply: Is it possible to point GDB to the copied contents of > the call stack and tell it to print out the information contained therein? (Note I am not familiar in x86 stack-walking stuff.) In general a debugger needs at least a stack pointer and an instruction pointer to get a backtrace. If the function containing the IP uses a frame pointer (a debugger should be able to tell you that) then debugger needs to know the FP. Which register contains the FP depends on the prologue type chosen by compiler (on x86 it is always EBP). Command "info frame <address>" may assume IP is pointed to by SP. So there are at least 2 arguments (FP+SP) to be provided on any arch. Therefore I suspect "info frame <address>" is not general enough to be used in your case. > That framework implements coroutines by using the C/C++ setjmp/longjmp > instructions and by copying the call stack that is used by each coroutine to > dynamically allocated memory on the heap. Beware that a function compiled without -fomit-frame-pointer saves SP to stack and gdb uses the value to obtain stack-trace (this is not quite exact). If you copy a stack somewhere and use gdb to walk the stack there then gdb will try to use SP values pointing to the "old" stack memory. (And you cannot resume execution of the stack while in the new memory.) > But I'm also aware that the GDB *should be* able to do what I want it to do. > For one, the documentation explicitly mentions that the feature works with > programs that utilize multiple stacks. Furthermore, the GDB is also able to > debug Multi-Threaded programs, which also need to save the call stack to > dynamic heap memory. When doing multithreaded programs gdb gets register values from pthread library (or linux kernel?) or by remote target command. And the stack frames stay where they were created - they are not copied. > So, my question is: Is it possible to examine the copied stack? And if yes, > what do I need to give to the GDB to allow it? I do not know. Someone else have to answer that. -- Petr Hluzin ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Examining copied stack contents 2010-07-05 18:50 ` Examining copied stack contents Petr Hluzín @ 2010-07-05 20:18 ` Martin Schröder 2010-07-05 20:27 ` Joel Brobecker 2010-07-07 17:29 ` Martin Schröder 1 sibling, 1 reply; 18+ messages in thread From: Martin Schröder @ 2010-07-05 20:18 UTC (permalink / raw) To: gdb Petr HluzÃn wrote: > > (Note I am not familiar in x86 stack-walking stuff.) > > In general a debugger needs at least a stack pointer and an > instruction pointer to get a backtrace. If the function containing the > IP uses a frame pointer (a debugger should be able to tell you that) > then debugger needs to know the FP. Which register contains the FP > depends on the prologue type chosen by compiler (on x86 it is always > EBP). Command "info frame <address>" may assume IP is pointed to by > SP. So there are at least 2 arguments (FP+SP) to be provided on any > arch. > > Therefore I suspect "info frame <address>" is not general enough to be > used in your case. Mhhhm, I also suspected as much, but the docs [1] only point out four architectures where more than just the SP is necessary: SPARC (FP + SP), MIPS & Alpha (PC + SP) and the 29k architecture (Register SP + Memory SP + PC). The docs did not mention x86, which made me abandon that line of thinking. Anyway, I'll try to play around with the additional parameters and see if they change anything. [1] - http://www.circlemud.org/cdp/gdb/gdb_7.html#SEC43 >> That framework implements coroutines by using the C/C++ >> setjmp/longjmp instructions and by copying the call stack that is >> used by each coroutine to dynamically allocated memory on the heap. > > Beware that a function compiled without -fomit-frame-pointer saves SP > to stack and gdb uses the value to obtain stack-trace (this is not > quite exact). If you copy a stack somewhere and use gdb to walk the > stack there then gdb will try to use SP values pointing to the "old" > stack memory. > (And you cannot resume execution of the stack while in the new > memory.) I also assumed that GDB will parse the contents of the stack to get the proper sequence of frames. But that's why I deliberately chose to break the simulation when the stack contents were copied but not yet overwritten. Thus, even *if* the GDB parses the new stack and subsequently accesses the old areas, everything should still work, because the old stack's still in place. It seems to me that the stack walking algorithm notices some kind of error, but simply fails to relay it to me. After all, no matter WHAT address I give GDB, it always returns the same, useless data and never even once throws an error. >> But I'm also aware that the GDB *should be* able to do what I want >> it to do. For one, the documentation explicitly mentions that the >> feature works with programs that utilize multiple stacks. >> Furthermore, the GDB is also able to debug Multi-Threaded programs, >> which also need to save the call stack to dynamic heap memory. > > When doing multithreaded programs gdb gets register values from > pthread library (or linux kernel?) or by remote target command. And > the stack frames stay where they were created - they are not copied. Yes, but the app still needs to switch from one stack to another during execution, which is by all means very similar to copying the stack somewhere else and resuming execution from there (something I don't need to do; I merely need to examine the copy, not run it). So, whatevery causes GDB to accept the move to another stack should also enable it to move to the /same/ stack at another memory location. I mean, I could easily live with manipulating a few registers and memory chunks so that the GDB believes that the new stack location is valid. If only the documentation would include which data stores are read during stack traversal! Unfortunately, my attempts at digging around in the source code was equally fruitless in that regard. But thanks for pointing out that GDB most likely analyzes the register values to do its job. I'll see if I can manipulate them to get GDB to do something sensible. >> So, my question is: Is it possible to examine the copied stack? And >> if yes, what do I need to give to the GDB to allow it? > > I do not know. Someone else have to answer that. Thanks anyway. You've already helped me enough so that I found a few more approaches to testing GDB's features. So long, Martin Schröder. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Examining copied stack contents 2010-07-05 20:18 ` Martin Schröder @ 2010-07-05 20:27 ` Joel Brobecker 0 siblings, 0 replies; 18+ messages in thread From: Joel Brobecker @ 2010-07-05 20:27 UTC (permalink / raw) To: Martin Schr?der; +Cc: gdb There are several possible ways to do callstack unwinding on each architecture. The prefered way is to rely on DWARF frame info, but we otherwise fallback on other methods (either native unwinding info, or if all else fails, prologue parsing). That's why the GDB code for each architecture registers "sniffers" which will tell GDB for each frame which unwinder would be best to use. The result also depends on the type of frame, since signal frames often require their own unwinder. I recommend that you have a look at i386-tdep.c, and in particular the various functions specified in the i386_frame_unwind structure. That should help you find out what is actually going on inside GDB. -- Joel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Examining copied stack contents 2010-07-05 18:50 ` Examining copied stack contents Petr Hluzín 2010-07-05 20:18 ` Martin Schröder @ 2010-07-07 17:29 ` Martin Schröder 1 sibling, 0 replies; 18+ messages in thread From: Martin Schröder @ 2010-07-07 17:29 UTC (permalink / raw) To: Petr Hluzín; +Cc: brobecker, gdb Petr HluzÃn wrote: > On 3 July 2010 12:46, Martin Schröder <gschroeder@onlinehome.de> > wrote: > > In general a debugger needs at least a stack pointer and an > instruction pointer to get a backtrace. If the function containing the > IP uses a frame pointer (a debugger should be able to tell you that) > then debugger needs to know the FP. Which register contains the FP > depends on the prologue type chosen by compiler (on x86 it is always > EBP). Command "info frame <address>" may assume IP is pointed to by > SP. So there are at least 2 arguments (FP+SP) to be provided on any > arch. > > Therefore I suspect "info frame <address>" is not general enough to be > used in your case. Hello everyone; and thanks to Petr and Joel. The above comment was exactly what I needed to find a working solution for my problem, at least as long as GDB uses Dwarf2 frame unwinding (but it *probably* should work with the other unwinders, too). Due to the content of the stack being an unaltered copy, it's of course impossible for GDB to properly unwind it at its current location. Thus, you have to copy it back to its original position. But since you almost always want to continue your program properly later on, your first step has to be to save the part of the stack that's going to be overwritten. If you assume that the convenience variable "$base" is the original address of the stack, "$length" its length and "$copyPos" the address of the copy, you have to execute the following commands: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gdb> set $stack = malloc($length) gdb> p memcpy($stack, $base, $length); gdb> p memcpy($base, $copyPos, $length); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Of course, you should check if malloc returns something other than 0. But for brevity's sake, I won't write down the sanity checks. In any case, after you've backed-up the current stack and copied over the old stack, you have to set the $epb and $eip registers to allow GDB to understand the stack. Both should be stored within the jmp_buf struct that's created by the setjmp() statement. Unfortunately, due to security reasons, glibc masks the stack pointer register (which is not needed by GDB, strangely enough) and the eip register on Linux. Their actual values are xor-ed with a fixed pattern and then rotated by 9 bits to the left [1]. After undoing that, you can get the eip and all that remains to do is to fetch the ebp frame pointer. In my case that's simple, because due to the way the stack is copied, the ebp register is always 9 bytes less than the "base" variable. Otherwise, you have to dig around where the ebp is stored inside the jmp_buf or get it from somewhere else (like I did). Anyway, after you have the ebp and eip values, simply back them up and set them with the following commands: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gdb> set $ebpsave = $ebp gdb> set $eipsave = $eip gdb> p $ebp = 0x<Hexadecimal-EBP-Content> gdb> p $eip = 0x<Hexadecimal-EIP-Content> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Now, you can get a full backtrace and explore the frame details. If you later intend to continue execution, just reset your changes: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gdb> p $ebp = $ebpsave gdb> p $eip = $eipsave gdb> p memcpy($base, $stack, $length) gdb> p free($stack) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - That's it. A bit crude since you can't exactly "just" look at it, need to learn the correct values of ebp and eip and it only works like that on x86, but hey, at least it *does* work. :) Thanks again for you help! Martin Schröder. [1] - http://cseweb.ucsd.edu/~hovav/dist/noret.pdf Page 14 ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2010-07-21 22:45 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-07-03 10:48 Examining copied stack contents Martin Schröder 2010-07-05 4:54 ` support biarch gcore? Jon Zhou 2010-07-05 7:12 ` Jan Kratochvil 2010-07-05 11:55 ` Mark Kettenis 2010-07-06 20:48 ` Ulrich Weigand 2010-07-06 21:29 ` Mark Kettenis 2010-07-07 12:30 ` Ulrich Weigand 2010-07-08 2:35 ` Jon Zhou 2010-07-08 11:17 ` Ulrich Weigand 2010-07-08 4:47 ` H.J. Lu 2010-07-08 5:05 ` H.J. Lu 2010-07-08 11:15 ` Ulrich Weigand 2010-07-08 13:52 ` H.J. Lu 2010-07-21 22:45 ` Joseph S. Myers 2010-07-05 18:50 ` Examining copied stack contents Petr Hluzín 2010-07-05 20:18 ` Martin Schröder 2010-07-05 20:27 ` Joel Brobecker 2010-07-07 17:29 ` Martin Schröder
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).