* [patch RFC] Re: Notes on a frame_unwind_address_in_block problem [not found] ` <20060718183910.GB17864@nevyn.them.org> @ 2007-01-01 19:19 ` Daniel Jacobowitz 2007-01-01 19:54 ` Mark Kettenis 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-01 19:19 UTC (permalink / raw) To: gdb-patches; +Cc: Mark Kettenis Now that the CFI issue in glibc is fixed, I'm back to this discussion from July. Quoted below for reference, since it's been a while. Here's a patch, that I'm looking for comments on. It's not the most gorgeous code I've ever written, but it's the simplest solution I could come up with for a complicated problem. It fixes eight failures in the x86-64 GNU/Linux testsuite and I believe it will fix those same failures for i386 also. Test results for this platform are starting to look really good. I hope I can get it to no failures during the next two weeks, and then move on to do the same for another platform. Problem ======= The problem is a function which looks like this: <fde start> nop function_label: code <fde end> <function end> Such functions are interesting to me because glibc and the Linux kernel both use them to provide unwind information for signal handlers. The nop allows pc-1 to work, at least for libgcc's unwinder, even though function_label is pushed directly onto the stack as if it were a return address. But GDB ends up subtracting one from the PC in some places it would be better not to. We decide that get_frame_func for that frame should return the func associated with the fde start if the next frame is a normal frame, but the func associated with the function_label if the next frame is the sentinel frame. This inconsistency breaks "finish" out of a signal handler, because the unwound frame ID when the command is issued doesn't match the current frame ID when we hit the temporary breakpoint. We have several tests for this case. Solution ======== I spent a little while thinking about it today. I want the decision to be made by frame_unwind_address_in_block, because that function has a bunch of callers that might rely on its result being in the right block. My previous nasty hack made that function right some of the time, but not all of the time, for the same frame. Here's a bigger patch, which makes it right consistently. After the patch, the unwound address in block is decremented only if there are two consecutive normal frames. If either the next or current frame is a signal frame, we leave it alone. This is basically the same as my original nasty hack, except that there are better safety measures in place: frame_unwind_address_in_block does not change during unwinding, and if you use it too early you get a clear assertion failure. The complicated part is avoiding recursion. frame_unwind_address_in_block is no longer safe to use during sniffers. I broke it apart into two functions. The new one assumes that the unwound frame will be normal. This does the right thing when called in sniffers for normal frames. Then, I audited every single frame unwind sniffer, and adjusted all the sniffers for normal frames to use it. Several of them should have been using address_in_block already, but weren't. Signal frame unwinders still use frame_pc_unwind directly. There were surprisingly few changes necessary. Of course, I might have missed one, but I added an assertion and some comments that should make the problem easy to recognize. On Tue, Jul 18, 2006 at 02:39:10PM -0400, Daniel Jacobowitz wrote: > > > Another solution would be to use the FDE start address as the code address > > > for dwarf2 signal frame IDs, instead of the function. This would work on > > > the assumption that a single FDE would generally cover the entire trampoline > > > - a reasonable assumption, I think, and the consequences for the frame ID > > > changing while single-stepping are less disruptive here than the > > > alternative. > > > > > > Mark, what do you think of that idea? It seems to work. It looks like the > > > patch at the end of this message. > > > > In general, I think it's a bad idea to do this, but for the special > > case of a signal frame, especially in the presence of the 'S" > > augmentation, that might be a reasonable thing to do. However, I > > think we can do better than that. What about checking whether the > > address returned by frame_unwind_address_in_block() is equal to the > > FDE start address and add one bytes if that's the case before looking > > up the function corresponding to that address? > > Unfortunately we can't readily; we'd have to add a bit of new code, > since all that's there is a call to frame_func_unwind (next_frame) > and that has no way to do the right thing. > > I'd like to trigger off the signal augmentation. If you'd prefer to > check the FDE start address, could you show me exactly what you have in > mind? > > With that patch plus the fixed unwind information gdb.base/*.exp > results are basically clean for x86_64 - best I've ever seen them. > There is a corefile issue which I think is kernel related, and two > annotation tests fail because they don't account for a glibc with debug > information enabled. -- Daniel Jacobowitz CodeSourcery 2007-01-01 Daniel Jacobowitz <dan@codesourcery.com> * frame-unwind.c (searching_for_unwind): New. (clear_searching_flag): New. (frame_unwind_find_by_frame): Assert that this function is not entered recursively. * frame.c (normal_frame_unwind_address_in_block): Renamed from frame_unwind_address_in_block. Doc update. (frame_unwind_address_in_block): Use the new function. Also check the previous frame's type. * frame.h (normal_frame_unwind_address_in_block): New prototype. * alpha-mdebug-tdep.c (alpha_mdebug_frame_sniffer): Use normal_frame_unwind_address_in_block. (alpha_mdebug_frame_base_sniffer): Likewise. * arm-tdep.c (arm_stub_unwind_sniffer): Likewise. * dwarf2-frame.c (dwarf2_frame_sniffer): Likewise. (dwarf2_frame_base_sniffer): Likewise. * hppa-tdep.c (hppa_find_unwind_entry_in_block): Likewise. (hppa_stub_unwind_sniffer): Likewise. * mips-mdebug-tdep.c (mips_mdebug_frame_sniffer): Likewise. * mips-tdep.c (mips_insn16_frame_sniffer, mips_insn32_frame_sniffer) (mips_stub_frame_sniffer): Likewise. * s390-tdep.c (s390_stub_frame_sniffer): Likewise. * sparc64obsd-tdep.c (sparc64obsd_trapframe_sniffer): Likewise. (sparc64obsd_trapframe_cache): Whitespace fix. Index: alpha-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-mdebug-tdep.c,v retrieving revision 1.11 diff -u -p -r1.11 alpha-mdebug-tdep.c --- alpha-mdebug-tdep.c 17 Dec 2005 22:33:59 -0000 1.11 +++ alpha-mdebug-tdep.c 1 Jan 2007 19:06:21 -0000 @@ -307,7 +307,7 @@ static const struct frame_unwind alpha_m const struct frame_unwind * alpha_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an @@ -364,7 +364,7 @@ static const struct frame_base alpha_mde static const struct frame_base * alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.217 diff -u -p -r1.217 arm-tdep.c --- arm-tdep.c 22 Nov 2006 18:51:58 -0000 1.217 +++ arm-tdep.c 1 Jan 2007 19:06:22 -0000 @@ -993,7 +993,7 @@ arm_stub_unwind_sniffer (struct frame_in { char dummy[4]; - if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL) + if (in_plt_section (normal_frame_unwind_address_in_block (next_frame), NULL) || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0) return &arm_stub_unwind; Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.64 diff -u -p -r1.64 dwarf2-frame.c --- dwarf2-frame.c 28 Nov 2006 17:28:29 -0000 1.64 +++ dwarf2-frame.c 1 Jan 2007 19:06:22 -0000 @@ -1104,8 +1104,11 @@ dwarf2_frame_sniffer (struct frame_info { /* Grab an address that is guarenteed to reside somewhere within the function. frame_pc_unwind(), for a no-return next function, can - end up returning something past the end of this function's body. */ - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); + end up returning something past the end of this function's body. + If the frame we're sniffing for is a signal frame whose start + address is placed on the stack by the OS, its FDE must + extend one byte before its start address or we will miss it. */ + CORE_ADDR block_addr = normal_frame_unwind_address_in_block (next_frame); struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); if (!fde) return NULL; @@ -1149,8 +1152,8 @@ static const struct frame_base dwarf2_fr const struct frame_base * dwarf2_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - if (dwarf2_frame_find_fde (&pc)) + CORE_ADDR block_addr = normal_frame_unwind_address_in_block (next_frame); + if (dwarf2_frame_find_fde (&block_addr)) return &dwarf2_frame_base; return NULL; Index: frame-unwind.c =================================================================== RCS file: /cvs/src/src/gdb/frame-unwind.c,v retrieving revision 1.17 diff -u -p -r1.17 frame-unwind.c --- frame-unwind.c 17 Dec 2005 22:33:59 -0000 1.17 +++ frame-unwind.c 1 Jan 2007 19:06:22 -0000 @@ -28,6 +28,8 @@ static struct gdbarch_data *frame_unwind_data; +static int searching_for_unwind; + struct frame_unwind_table_entry { frame_unwind_sniffer_ftype *sniffer; @@ -83,6 +85,12 @@ frame_unwind_prepend_unwinder (struct gd (*table->osabi_head) = entry; } +static void +clear_searching_flag (void *arg) +{ + searching_for_unwind = 0; +} + const struct frame_unwind * frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache) { @@ -90,6 +98,16 @@ frame_unwind_find_by_frame (struct frame struct gdbarch *gdbarch = get_frame_arch (next_frame); struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); struct frame_unwind_table_entry *entry; + struct cleanup *back_to; + + /* Ensure we were not re-entered. This happens if the sniffer calls + anything which requires NEXT_FRAME's unwinder, for instance by + calling frame_unwind_address_in_block instead of frame_pc_unwind or + normal_frame_unwind_address_in_block. */ + gdb_assert (!searching_for_unwind); + searching_for_unwind = 1; + back_to = make_cleanup (clear_searching_flag, NULL); + for (entry = table->list; entry != NULL; entry = entry->next) { if (entry->sniffer != NULL) @@ -97,15 +115,22 @@ frame_unwind_find_by_frame (struct frame const struct frame_unwind *desc = NULL; desc = entry->sniffer (next_frame); if (desc != NULL) - return desc; + { + do_cleanups (back_to); + return desc; + } } if (entry->unwinder != NULL) { if (entry->unwinder->sniffer (entry->unwinder, next_frame, this_cache)) - return entry->unwinder; + { + do_cleanups (back_to); + return entry->unwinder; + } } } + do_cleanups (back_to); internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed")); } Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.215 diff -u -p -r1.215 frame.c --- frame.c 10 Nov 2006 20:11:35 -0000 1.215 +++ frame.c 1 Jan 2007 19:06:22 -0000 @@ -1412,10 +1412,13 @@ get_frame_pc (struct frame_info *frame) return frame_pc_unwind (frame->next); } -/* Return an address of that falls within the frame's code block. */ +/* Return an address that falls within NEXT_FRAME's caller's code + block, assuming that the caller is a normal function (i.e. not + a signal trampoline). This function should only be called from + frame unwind sniffers. */ CORE_ADDR -frame_unwind_address_in_block (struct frame_info *next_frame) +normal_frame_unwind_address_in_block (struct frame_info *next_frame) { /* A draft address. */ CORE_ADDR pc = frame_pc_unwind (next_frame); @@ -1425,7 +1428,7 @@ frame_unwind_address_in_block (struct fr frame's PC ends up pointing at the instruction fallowing the "call". Adjust that PC value so that it falls on the call instruction (which, hopefully, falls within THIS frame's code - block. So far it's proved to be a very good approximation. See + block). So far it's proved to be a very good approximation. See get_frame_type() for why ->type can't be used. */ if (next_frame->level >= 0 && get_frame_type (next_frame) == NORMAL_FRAME) @@ -1433,6 +1436,28 @@ frame_unwind_address_in_block (struct fr return pc; } +/* Return an address that falls within NEXT_FRAME's caller's code + block. This function must not be called from frame unwind + sniffers, because it relies on both NEXT_FRAME and its + caller. */ + +CORE_ADDR +frame_unwind_address_in_block (struct frame_info *next_frame) +{ + struct frame_info *this_frame; + + /* If this frame was called by a signal frame or dummy frame, then + we shold not adjust the unwound PC. These frames may not call + their next frame in the normal way; the operating system or GDB + may have pushed their resume address manually onto the stack, + so it may be the very first instruction. */ + this_frame = get_prev_frame_1 (next_frame); + if (this_frame != NULL && get_frame_type (this_frame) != NORMAL_FRAME) + return frame_pc_unwind (next_frame); + + return normal_frame_unwind_address_in_block (next_frame); +} + CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame) { Index: frame.h =================================================================== RCS file: /cvs/src/src/gdb/frame.h,v retrieving revision 1.150 diff -u -p -r1.150 frame.h --- frame.h 10 Nov 2006 20:11:35 -0000 1.150 +++ frame.h 1 Jan 2007 19:06:22 -0000 @@ -266,6 +266,14 @@ extern CORE_ADDR get_frame_pc (struct fr extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); +/* Similar to frame_unwind_address_in_block, find an address in the + block which logically called NEXT_FRAME. This function is a + support routine for frame unwind sniffers, and should not be called + from anywhere else. */ + +extern CORE_ADDR + normal_frame_unwind_address_in_block (struct frame_info *next_frame); + /* The frame's inner-most bound. AKA the stack-pointer. Confusingly known as top-of-stack. */ Index: hppa-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/hppa-tdep.c,v retrieving revision 1.223 diff -u -p -r1.223 hppa-tdep.c --- hppa-tdep.c 8 Aug 2006 21:32:48 -0000 1.223 +++ hppa-tdep.c 1 Jan 2007 19:06:23 -0000 @@ -1786,9 +1786,14 @@ hppa_skip_prologue (CORE_ADDR pc) static struct unwind_table_entry * hppa_find_unwind_entry_in_block (struct frame_info *f) { - CORE_ADDR pc; + CORE_ADDR pc = normal_frame_unwind_address_in_block (f); - pc = frame_unwind_address_in_block (f); + /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the + result of normal_frame_unwind_address_in_block implies a problem. + The bits should have been removed earlier, before the return + value of frame_pc_unwind. That might be happening already; + if it isn't, it should be fixed. Then this call can be + removed. */ pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc); return find_unwind_entry (pc); } @@ -2440,7 +2445,7 @@ static const struct frame_unwind hppa_st static const struct frame_unwind * hppa_stub_unwind_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); struct gdbarch *gdbarch = get_frame_arch (next_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); Index: mips-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-mdebug-tdep.c,v retrieving revision 1.7 diff -u -p -r1.7 mips-mdebug-tdep.c --- mips-mdebug-tdep.c 25 Apr 2006 18:58:09 -0000 1.7 +++ mips-mdebug-tdep.c 1 Jan 2007 19:06:23 -0000 @@ -412,7 +412,7 @@ static const struct frame_unwind mips_md static const struct frame_unwind * mips_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); CORE_ADDR startaddr = 0; struct mdebug_extra_func_info *proc_desc; int kernel_trap; Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.399 diff -u -p -r1.399 mips-tdep.c --- mips-tdep.c 28 Nov 2006 22:14:31 -0000 1.399 +++ mips-tdep.c 1 Jan 2007 19:06:23 -0000 @@ -1698,7 +1698,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn16_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); if (mips_pc_is_mips16 (pc)) return &mips_insn16_frame_unwind; return NULL; @@ -2018,7 +2018,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn32_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); if (! mips_pc_is_mips16 (pc)) return &mips_insn32_frame_unwind; return NULL; @@ -2113,7 +2113,7 @@ static const struct frame_unwind * mips_stub_frame_sniffer (struct frame_info *next_frame) { struct obj_section *s; - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = normal_frame_unwind_address_in_block (next_frame); if (in_plt_section (pc, NULL)) return &mips_stub_frame_unwind; Index: s390-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/s390-tdep.c,v retrieving revision 1.156 diff -u -p -r1.156 s390-tdep.c --- s390-tdep.c 28 Nov 2006 21:41:02 -0000 1.156 +++ s390-tdep.c 1 Jan 2007 19:06:24 -0000 @@ -1575,14 +1575,13 @@ static const struct frame_unwind s390_st static const struct frame_unwind * s390_stub_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); bfd_byte insn[S390_MAX_INSTR_SIZE]; /* If the current PC points to non-readable memory, we assume we have trapped due to an invalid function pointer call. We handle the non-existing current function like a PLT stub. */ - if (in_plt_section (pc, NULL) - || s390_readinstruction (insn, pc) < 0) + if (in_plt_section (normal_frame_unwind_address_in_block (next_frame), NULL) + || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0) return &s390_stub_frame_unwind; return NULL; } Index: sparc64obsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc64obsd-tdep.c,v retrieving revision 1.20 diff -u -p -r1.20 sparc64obsd-tdep.c --- sparc64obsd-tdep.c 31 Dec 2006 01:28:07 -0000 1.20 +++ sparc64obsd-tdep.c 1 Jan 2007 19:06:24 -0000 @@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru /* Kernel debugging support. */ static struct sparc_frame_cache * -sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) +sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; CORE_ADDR sp, trapframe_addr; @@ -267,15 +267,17 @@ static const struct frame_unwind sparc64 static const struct frame_unwind * sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) { + CORE_ADDR pc; ULONGEST pstate; char *name; /* Check whether we are in privileged mode, and bail out if we're not. */ - pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM); + pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); if ((pstate & SPARC64_PSTATE_PRIV) == 0) return NULL; - find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); + pc = normal_frame_unwind_address_in_block (next_frame); + find_pc_partial_function (pc, &name, NULL, NULL); if (name && strcmp (name, "Lslowtrap_reenter") == 0) return &sparc64obsd_trapframe_unwind; ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 19:19 ` [patch RFC] Re: Notes on a frame_unwind_address_in_block problem Daniel Jacobowitz @ 2007-01-01 19:54 ` Mark Kettenis 2007-01-01 20:02 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-01 19:54 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Mon, 1 Jan 2007 14:19:27 -0500 > From: Daniel Jacobowitz <drow@false.org> > > Now that the CFI issue in glibc is fixed, I'm back to this discussion > from July. Quoted below for reference, since it's been a while. > > Here's a patch, that I'm looking for comments on. It's not the most > gorgeous code I've ever written, but it's the simplest solution I could > come up with for a complicated problem. Well, I really can't say I like it. The problem is that it's been several months since we last discussed this problem, so I'll have to start to think again from scratch :(. Isn't it just a matter of making sure we set the right function address for signal trampolines? That is, shouldn't we have a dwarf2_signal_frame_this_id() that chooses a more sensible code address than frame_func_unwind()? > It fixes eight failures in the x86-64 GNU/Linux testsuite and I > believe it will fix those same failures for i386 also. Test results > for this platform are starting to look really good. I hope I can > get it to no failures during the next two weeks, and then move on to > do the same for another platform. Optimist! We'll only have to wait for the GCC/glibc/kernel people to come up with the next smart hack that they don't bother to test GDB with and you'll have lots of failures to fix again ;-) > Problem > ======= > > The problem is a function which looks like this: > > <fde start> nop > function_label: code > <fde end> <function end> > > Such functions are interesting to me because glibc and the Linux kernel > both use them to provide unwind information for signal handlers. The > nop allows pc-1 to work, at least for libgcc's unwinder, even though > function_label is pushed directly onto the stack as if it were a return > address. > > But GDB ends up subtracting one from the PC in some places it would be > better not to. We decide that get_frame_func for that frame should > return the func associated with the fde start if the next frame is a > normal frame, but the func associated with the function_label if the > next frame is the sentinel frame. This inconsistency breaks "finish" > out of a signal handler, because the unwound frame ID when the command > is issued doesn't match the current frame ID when we hit the temporary > breakpoint. We have several tests for this case. But we have no stand-alone testcase. You really need the right version of glibc to be able to test this. Could you come up with a testcase that works everywhere, or at least on all targets? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 19:54 ` Mark Kettenis @ 2007-01-01 20:02 ` Daniel Jacobowitz 2007-01-01 20:27 ` Mark Kettenis 2007-01-03 11:37 ` Mark Kettenis 0 siblings, 2 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-01 20:02 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Mon, Jan 01, 2007 at 08:54:08PM +0100, Mark Kettenis wrote: > Well, I really can't say I like it. The problem is that it's been > several months since we last discussed this problem, so I'll have to > start to think again from scratch :(. Isn't it just a matter of Yeah, sorry about that. Anyway, I'm happy to discuss alternatives; I don't like it much either. > making sure we set the right function address for signal trampolines? > That is, shouldn't we have a dwarf2_signal_frame_this_id() that > chooses a more sensible code address than frame_func_unwind()? That would fix the failing tests, but I'm worried about problems elsewhere. That's what I did in the patch I posted in July, I think. But get_frame_func would still return different values depending on whether the frame was topmost or not. That's called all over GDB - I can't figure out whether it will leave other bugs for us to stumble on later. > Optimist! We'll only have to wait for the GCC/glibc/kernel people to > come up with the next smart hack that they don't bother to test GDB > with and you'll have lots of failures to fix again ;-) Well yeah :-) But the first step in keeping up is definitely catching up. > But we have no stand-alone testcase. You really need the right > version of glibc to be able to test this. Could you come up with a > testcase that works everywhere, or at least on all targets? Hmm... I don't think it's possible, but it depends what qualifier you meant to put on "all targets". The only way I can see to do it would be with hand-written assembly and CFI and stack manipulation. I might be able to write a test which worked on all x86-64 systems and pretended to have create a signal frame, if that's what you wanted. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 20:02 ` Daniel Jacobowitz @ 2007-01-01 20:27 ` Mark Kettenis 2007-01-01 20:35 ` Daniel Jacobowitz 2007-01-03 11:37 ` Mark Kettenis 1 sibling, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-01 20:27 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Mon, 1 Jan 2007 15:02:48 -0500 > From: Daniel Jacobowitz <drow@false.org> > > > making sure we set the right function address for signal trampolines? > > That is, shouldn't we have a dwarf2_signal_frame_this_id() that > > chooses a more sensible code address than frame_func_unwind()? > > That would fix the failing tests, but I'm worried about problems > elsewhere. That's what I did in the patch I posted in July, I think. > But get_frame_func would still return different values depending > on whether the frame was topmost or not. That's called all over GDB - > I can't figure out whether it will leave other bugs for us to > stumble on later. But if you're calling get_frame_func() you've already got a frame, so you should know everything about it. The place to fix things is probably get_frame_address_in_block(). For one thing it's probably not a good idea to return an address that's lower than the code address in the frame ID. Or perhaps it is enough to look at the frame's type and simply call frame_pc_unwind for SIGTRAMP_FRAMEs. > Hmm... I don't think it's possible, but it depends what qualifier you > meant to put on "all targets". The only way I can see to do it would > be with hand-written assembly and CFI and stack manipulation. I might > be able to write a test which worked on all x86-64 systems and > pretended to have create a signal frame, if that's what you wanted. Hmm, sorry yes, a test that would work on all i386 or x86-64 target was what I actually meant. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 20:27 ` Mark Kettenis @ 2007-01-01 20:35 ` Daniel Jacobowitz 2007-01-02 0:51 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-01 20:35 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Mon, Jan 01, 2007 at 09:26:45PM +0100, Mark Kettenis wrote: > But if you're calling get_frame_func() you've already got a frame, so > you should know everything about it. The place to fix things is > probably get_frame_address_in_block(). For one thing it's probably > not a good idea to return an address that's lower than the code > address in the frame ID. Or perhaps it is enough to look at the > frame's type and simply call frame_pc_unwind for SIGTRAMP_FRAMEs. Hmm, get_frame_func may have been an ill-chosen example. A better one is frame_func_unwind. get_frame_func just wraps frame_func_unwind, and get_frame_address_in_block just wraps frame_unwind_address_in_block. I think that's a generally good thing - it encourages consistency in their results. The unwind variants are used all over GDB, not just during unwinding; this matters e.g. around main, where get_prev_frame might return NULL. And that's why my solution ended up complicated. When you're in frame_func_unwind you have to call frame_unwind_address_in_block, and at that point you might not know the type or even the unwinder of the previous frame. So I made frame_unwind_address_in_block do pretty much what you suggested above, and forbid calling it before we know the type of the previous frame. > > Hmm... I don't think it's possible, but it depends what qualifier you > > meant to put on "all targets". The only way I can see to do it would > > be with hand-written assembly and CFI and stack manipulation. I might > > be able to write a test which worked on all x86-64 systems and > > pretended to have create a signal frame, if that's what you wanted. > > Hmm, sorry yes, a test that would work on all i386 or x86-64 target > was what I actually meant. I can probably do that. I'll try this evening. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 20:35 ` Daniel Jacobowitz @ 2007-01-02 0:51 ` Daniel Jacobowitz 2007-01-02 19:16 ` Mark Kettenis 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-02 0:51 UTC (permalink / raw) To: Mark Kettenis, gdb-patches On Mon, Jan 01, 2007 at 03:35:33PM -0500, Daniel Jacobowitz wrote: > > Hmm, sorry yes, a test that would work on all i386 or x86-64 target > > was what I actually meant. > > I can probably do that. I'll try this evening. Here you go. It requires binutils 2.17 or later; before committing it I would have to make sure it's quiet with an older version. I could write it without the binutils dependency, but it's a lot bigger and messier that way. This testcase should be roughly OS independent, fails without the patch, and passes with it. -- Daniel Jacobowitz CodeSourcery 2007-01-01 Daniel Jacobowitz <dan@codesourcery.com> * gdb.arch/i386-signal.c, gdb.arch/i386-signal.exp: New files. Index: testsuite/gdb.arch/i386-signal.c =================================================================== RCS file: testsuite/gdb.arch/i386-signal.c diff -N testsuite/gdb.arch/i386-signal.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.arch/i386-signal.c 2 Jan 2007 00:48:36 -0000 @@ -0,0 +1,55 @@ +/* Unwinder test program for signal frames. + + Copyright 2007 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +void sigframe (void); +void setup (void); + +void +func (void) +{ +} + +int +main (void) +{ + setup (); +} + +/* Create an imitation signal frame. This will work on any x86 or + x86-64 target which uses a version of GAS recent enough for + .cfi_signal_frame (added 2006-02-27 and included in binutils 2.17). + The default CIE created by gas suffices to unwind from an empty + function. */ + +asm(".text\n" + " .align 8\n" + " .globl setup\n" + "setup:\n" + " push $sigframe\n" + " jmp func\n" + "\n" + " .cfi_startproc\n" + " .cfi_signal_frame\n" + " nop\n" + " .globl sigframe\n" + "sigframe:\n" + " ret\n" + " .cfi_endproc"); Index: testsuite/gdb.arch/i386-signal.exp =================================================================== RCS file: testsuite/gdb.arch/i386-signal.exp diff -N testsuite/gdb.arch/i386-signal.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.arch/i386-signal.exp 2 Jan 2007 00:48:36 -0000 @@ -0,0 +1,43 @@ +# Copyright 2007 Free Software Foundation, Inc. + +# This file is part of the GDB testsuite. + +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then { + verbose "Skipping i386 unwinder tests." + return +} + +set testfile "i386-signal" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + untested i386-sigframe.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +runto func +gdb_test "backtrace 10" \ + "#0 ($hex in )?func.*\r\n#1 <signal handler called>\r\n#2 ($hex in)?main.*" + +gdb_test "finish" "Run till exit from \#0 func.*<signal handler called>" ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-02 0:51 ` Daniel Jacobowitz @ 2007-01-02 19:16 ` Mark Kettenis 2007-01-02 19:18 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-02 19:16 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Mon, 1 Jan 2007 19:50:55 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Mon, Jan 01, 2007 at 03:35:33PM -0500, Daniel Jacobowitz wrote: > > > Hmm, sorry yes, a test that would work on all i386 or x86-64 target > > > was what I actually meant. > > > > I can probably do that. I'll try this evening. > > Here you go. It requires binutils 2.17 or later; before committing it > I would have to make sure it's quiet with an older version. I could > write it without the binutils dependency, but it's a lot bigger and > messier that way. Thanks. Unfortunately I don't seem to have a system around with binutils 2.17 :( Well, time will probably solve that problem... ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-02 19:16 ` Mark Kettenis @ 2007-01-02 19:18 ` Daniel Jacobowitz 2007-01-02 19:20 ` Daniel Jacobowitz 2007-01-02 21:32 ` Mark Kettenis 0 siblings, 2 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-02 19:18 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Tue, Jan 02, 2007 at 08:16:15PM +0100, Mark Kettenis wrote: > Thanks. Unfortunately I don't seem to have a system around with > binutils 2.17 :( Well, time will probably solve that problem... Do you think it's worth my hand-writing the necessary CFI so that you can try it? If you're interested in helping me with these failures, I'm interested in helping you help :-) -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-02 19:18 ` Daniel Jacobowitz @ 2007-01-02 19:20 ` Daniel Jacobowitz 2007-01-02 21:32 ` Mark Kettenis 1 sibling, 0 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-02 19:20 UTC (permalink / raw) To: gdb-patches; +Cc: Mark Kettenis On Tue, Jan 02, 2007 at 02:18:07PM -0500, Daniel Jacobowitz wrote: > Do you think it's worth my hand-writing the necessary CFI so that you > can try it? Alternatively, many native GCC configurations will use whichever version of gas is in your $PATH; you can build and install it somewhere else. Don't try this with a version older than your GCC was configured with, but newer should be fine. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-02 19:18 ` Daniel Jacobowitz 2007-01-02 19:20 ` Daniel Jacobowitz @ 2007-01-02 21:32 ` Mark Kettenis 1 sibling, 0 replies; 25+ messages in thread From: Mark Kettenis @ 2007-01-02 21:32 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Tue, 2 Jan 2007 14:18:07 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Tue, Jan 02, 2007 at 08:16:15PM +0100, Mark Kettenis wrote: > > Thanks. Unfortunately I don't seem to have a system around with > > binutils 2.17 :( Well, time will probably solve that problem... > > Do you think it's worth my hand-writing the necessary CFI so that you > can try it? Probably not. Mark ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-01 20:02 ` Daniel Jacobowitz 2007-01-01 20:27 ` Mark Kettenis @ 2007-01-03 11:37 ` Mark Kettenis 2007-01-03 14:43 ` Daniel Jacobowitz 2007-01-03 16:13 ` Daniel Jacobowitz 1 sibling, 2 replies; 25+ messages in thread From: Mark Kettenis @ 2007-01-03 11:37 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Mon, 1 Jan 2007 15:02:48 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Mon, Jan 01, 2007 at 08:54:08PM +0100, Mark Kettenis wrote: > > Well, I really can't say I like it. The problem is that it's been > > several months since we last discussed this problem, so I'll have to > > start to think again from scratch :(. Isn't it just a matter of > > Yeah, sorry about that. Anyway, I'm happy to discuss alternatives; > I don't like it much either. I have thought about this for a bit now, and I think I have found a way out. But let me first start by being a bit more specific about why I think your change is so bad: The basic principle of unwinding is that you get information about THIS_FRAME from NEXT_FRAME; you always walk the frame chain in one direction. This means that the only requirement for calling frame_unwind_xxx functions is that you have a NEXT_FRAME. Your change introduces a function that breaks this rule, by requiring THIS_FRAME to be there, walking the frame chain in the other direction. And it didn't take you very long to hit the problem with that: infinite recursion. Now the problem we're facing is that frame_unwind_address_in_block() (frame_func_unwind() is nothing but a fancy wrapper around that call) cannot be implemented reliably without knowledge about THIS_FRAME; it needs to know whether THIS_FRAME could be a fake frame set up by the kernel in order to determine whether it is a good idea to adjust the unwound PC or not. In our current implementation that information is carried by the frame type. The solution I think, is to pass this information explicitly to frame_unwind_address_in_block(), i.e. we change it's prototype from: CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); into CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, enum frame_type *this_type); Of course get_frame_address_in_block() doesn't need this extra argument, and would be implemented as: CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame) { return frame_unwind_address_in_block (this_frame->next, get_frame_type (this_frame)); } If you think a bit further (almost) all cases where we currently call frame_unwind_address_in_block() in sniffers, we really need to specify THIS_FRAME's type explicitly. So signal frame sniffers would need to do call frame_unwind_address_in_block (next_frame, SIGTRAMP_FRAME). Doing so in the dwarf2_signal_frame_this_id() would fix the bug we're trying to fix. Mark ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 11:37 ` Mark Kettenis @ 2007-01-03 14:43 ` Daniel Jacobowitz 2007-01-03 16:13 ` Daniel Jacobowitz 1 sibling, 0 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-03 14:43 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Wed, Jan 03, 2007 at 12:37:00PM +0100, Mark Kettenis wrote: > If you think a bit further (almost) all cases where we currently call > frame_unwind_address_in_block() in sniffers, we really need to specify > THIS_FRAME's type explicitly. So signal frame sniffers would need to > do call frame_unwind_address_in_block (next_frame, SIGTRAMP_FRAME). > Doing so in the dwarf2_signal_frame_this_id() would fix the bug we're > trying to fix. That's much more elegant than what I had. Thanks a lot! I'll try it. In dwarf2_frame_cache I'll need to fetch the type from THIS frame; normally unwinders avoid looking at that, but there's no iron reason why they must, so it should be fine. I think that this will convert most calls to either pass NORMAL_FRAME or call the non-unwind version - there's a lot of potential call sites which call frame_pc_unwind instead, because they know that the function doesn't do anything for signal frames, so there won't be any hardcoded uses of the unwind version with SIGNAL_FRAME. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 11:37 ` Mark Kettenis 2007-01-03 14:43 ` Daniel Jacobowitz @ 2007-01-03 16:13 ` Daniel Jacobowitz 2007-01-03 20:28 ` Mark Kettenis 1 sibling, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-03 16:13 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Wed, Jan 03, 2007 at 12:37:00PM +0100, Mark Kettenis wrote: > The basic principle of unwinding is that you get information about > THIS_FRAME from NEXT_FRAME; you always walk the frame chain in one > direction. This means that the only requirement for calling > frame_unwind_xxx functions is that you have a NEXT_FRAME. Your change > introduces a function that breaks this rule, by requiring THIS_FRAME > to be there, walking the frame chain in the other direction. And it > didn't take you very long to hit the problem with that: infinite > recursion. > > Now the problem we're facing is that frame_unwind_address_in_block() > (frame_func_unwind() is nothing but a fancy wrapper around that call) > cannot be implemented reliably without knowledge about THIS_FRAME; it > needs to know whether THIS_FRAME could be a fake frame set up by the > kernel in order to determine whether it is a good idea to adjust the > unwound PC or not. In our current implementation that information is > carried by the frame type. > > The solution I think, is to pass this information explicitly to > frame_unwind_address_in_block(), i.e. we change it's prototype from: I've hit one hiccup with this... dwarf2_frame_this_id isn't calling frame_unwind_address_in_block, just frame_func_unwind. So, if we want frame_func_unwind to do the right thing, that's the call site which needs to know the right frame type. The calls to frame_unwind_address_in_block in dwarf2-frame.c don't matter; they're just trying to find the right FDE. In fact, when I was finished, the only calls to frame_unwind_address_in_block anywhere in GDB which didn't hardcode NORMAL_FRAME were the ones in get_frame_address_in_block and frame_func_unwind (as I'd expect; the others are from unwinding except for one oddball). I made frame_func_unwind look at THIS_FRAME, if one can be found. That's OK in practice, given where all the calls to frame_func_unwind are (all after the frame unwinder has been chosen), but it has the same theoretical problem. - CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi); + struct frame_info *prev_frame = get_prev_frame_1 (fi); + enum frame_type prev_type = NORMAL_FRAME; + CORE_ADDR addr_in_block; + + if (prev_frame != NULL) + prev_type = get_frame_type (prev_frame); + addr_in_block = frame_unwind_address_in_block (fi, prev_type); + Options that I see: - Add the argument to frame_func_unwind. Big, messy, hard to test, but mostly mechanical. I don't much like it, because it pushes this special case out to all the callers of that interface. - Use the version in this patch. - Add an assertion to frame_func_unwind that next_frame->prev and next_frame->prev->unwind are already set. That's a bit of a compromise. They always will be; every call to frame_func_unwind is during unwinding. Unlike frame_unwind_address_in_block it is never called from a sniffer. - Define both frame_func_unwind and frame_unwind_address_in_block to assume that THIS_FRAME will be a normal frame and have them assume that. Just a rearrangement of deck chairs from the other suggestions really. What do you think? -- Daniel Jacobowitz CodeSourcery Index: alpha-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-mdebug-tdep.c,v retrieving revision 1.11 diff -u -p -r1.11 alpha-mdebug-tdep.c --- alpha-mdebug-tdep.c 17 Dec 2005 22:33:59 -0000 1.11 +++ alpha-mdebug-tdep.c 3 Jan 2007 15:53:13 -0000 @@ -307,7 +307,7 @@ static const struct frame_unwind alpha_m const struct frame_unwind * alpha_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an @@ -364,7 +364,7 @@ static const struct frame_base alpha_mde static const struct frame_base * alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.217 diff -u -p -r1.217 arm-tdep.c --- arm-tdep.c 22 Nov 2006 18:51:58 -0000 1.217 +++ arm-tdep.c 3 Jan 2007 15:53:14 -0000 @@ -991,9 +991,11 @@ struct frame_unwind arm_stub_unwind = { static const struct frame_unwind * arm_stub_unwind_sniffer (struct frame_info *next_frame) { + CORE_ADDR addr_in_block; char dummy[4]; - if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0) return &arm_stub_unwind; Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.64 diff -u -p -r1.64 dwarf2-frame.c --- dwarf2-frame.c 28 Nov 2006 17:28:29 -0000 1.64 +++ dwarf2-frame.c 3 Jan 2007 15:53:15 -0000 @@ -770,7 +770,7 @@ dwarf2_frame_cache (struct frame_info *n frame_unwind_address_in_block does just this. It's not clear how reliable the method is though; there is the potential for the register state pre-call being different to that on return. */ - fs->pc = frame_unwind_address_in_block (next_frame); + fs->pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); /* Find the correct FDE. */ fde = dwarf2_frame_find_fde (&fs->pc); @@ -1104,8 +1104,12 @@ dwarf2_frame_sniffer (struct frame_info { /* Grab an address that is guarenteed to reside somewhere within the function. frame_pc_unwind(), for a no-return next function, can - end up returning something past the end of this function's body. */ - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); + end up returning something past the end of this function's body. + If the frame we're sniffing for is a signal frame whose start + address is placed on the stack by the OS, its FDE must + extend one byte before its start address or we will miss it. */ + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); if (!fde) return NULL; @@ -1149,8 +1153,9 @@ static const struct frame_base dwarf2_fr const struct frame_base * dwarf2_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - if (dwarf2_frame_find_fde (&pc)) + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); + if (dwarf2_frame_find_fde (&block_addr)) return &dwarf2_frame_base; return NULL; Index: frame-unwind.c =================================================================== RCS file: /cvs/src/src/gdb/frame-unwind.c,v retrieving revision 1.17 diff -u -p -r1.17 frame-unwind.c --- frame-unwind.c 17 Dec 2005 22:33:59 -0000 1.17 +++ frame-unwind.c 3 Jan 2007 15:53:15 -0000 @@ -28,6 +28,8 @@ static struct gdbarch_data *frame_unwind_data; +static int searching_for_unwind; + struct frame_unwind_table_entry { frame_unwind_sniffer_ftype *sniffer; @@ -83,6 +85,12 @@ frame_unwind_prepend_unwinder (struct gd (*table->osabi_head) = entry; } +static void +clear_searching_flag (void *arg) +{ + searching_for_unwind = 0; +} + const struct frame_unwind * frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache) { @@ -90,6 +98,15 @@ frame_unwind_find_by_frame (struct frame struct gdbarch *gdbarch = get_frame_arch (next_frame); struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); struct frame_unwind_table_entry *entry; + struct cleanup *back_to; + + /* Check if we were re-entered, and assert instead of running out + of stack. This happens if the sniffer calls anything which + requires NEXT_FRAME's unwinder, for instance frame_func_unwind. */ + gdb_assert (!searching_for_unwind); + searching_for_unwind = 1; + back_to = make_cleanup (clear_searching_flag, NULL); + for (entry = table->list; entry != NULL; entry = entry->next) { if (entry->sniffer != NULL) @@ -97,15 +114,22 @@ frame_unwind_find_by_frame (struct frame const struct frame_unwind *desc = NULL; desc = entry->sniffer (next_frame); if (desc != NULL) - return desc; + { + do_cleanups (back_to); + return desc; + } } if (entry->unwinder != NULL) { if (entry->unwinder->sniffer (entry->unwinder, next_frame, this_cache)) - return entry->unwinder; + { + do_cleanups (back_to); + return entry->unwinder; + } } } + do_cleanups (back_to); internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed")); } Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.215 diff -u -p -r1.215 frame.c --- frame.c 10 Nov 2006 20:11:35 -0000 1.215 +++ frame.c 3 Jan 2007 15:53:15 -0000 @@ -477,7 +477,14 @@ frame_func_unwind (struct frame_info *fi { /* Make certain that this, and not the adjacent, function is found. */ - CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi); + struct frame_info *prev_frame = get_prev_frame_1 (fi); + enum frame_type prev_type = NORMAL_FRAME; + CORE_ADDR addr_in_block; + + if (prev_frame != NULL) + prev_type = get_frame_type (prev_frame); + addr_in_block = frame_unwind_address_in_block (fi, prev_type); + fi->prev_func.p = 1; fi->prev_func.addr = get_pc_function_start (addr_in_block); if (frame_debug) @@ -1412,20 +1419,31 @@ get_frame_pc (struct frame_info *frame) return frame_pc_unwind (frame->next); } -/* Return an address of that falls within the frame's code block. */ +/* Return an address that falls within NEXT_FRAME's caller's code + block, assuming that the caller is a THIS_TYPE frame. */ CORE_ADDR -frame_unwind_address_in_block (struct frame_info *next_frame) +frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type) { /* A draft address. */ CORE_ADDR pc = frame_pc_unwind (next_frame); + /* If NEXT_FRAME was called by a signal frame or dummy frame, then + we shold not adjust the unwound PC. These frames may not call + their next frame in the normal way; the operating system or GDB + may have pushed their resume address manually onto the stack, so + it may be the very first instruction. Even if the resume address + was not manually pushed, they expect to be returned to. */ + if (this_type != NORMAL_FRAME) + return pc; + /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel), and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS frame's PC ends up pointing at the instruction fallowing the "call". Adjust that PC value so that it falls on the call instruction (which, hopefully, falls within THIS frame's code - block. So far it's proved to be a very good approximation. See + block). So far it's proved to be a very good approximation. See get_frame_type() for why ->type can't be used. */ if (next_frame->level >= 0 && get_frame_type (next_frame) == NORMAL_FRAME) @@ -1436,7 +1454,8 @@ frame_unwind_address_in_block (struct fr CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame) { - return frame_unwind_address_in_block (this_frame->next); + return frame_unwind_address_in_block (this_frame->next, + get_frame_type (this_frame)); } static int Index: frame.h =================================================================== RCS file: /cvs/src/src/gdb/frame.h,v retrieving revision 1.150 diff -u -p -r1.150 frame.h --- frame.h 10 Nov 2006 20:11:35 -0000 1.150 +++ frame.h 3 Jan 2007 15:53:15 -0000 @@ -183,6 +183,25 @@ extern int frame_id_inner (struct frame_ extern void fprint_frame_id (struct ui_file *file, struct frame_id id); +/* Frame types. Some are real, some are signal trampolines, and some + are completely artificial (dummy). */ + +enum frame_type +{ + /* A true stack frame, created by the target program during normal + execution. */ + NORMAL_FRAME, + /* A fake frame, created by GDB when performing an inferior function + call. */ + DUMMY_FRAME, + /* In a signal handler, various OSs handle this in various ways. + The main thing is that the frame may be far from normal. */ + SIGTRAMP_FRAME, + /* Sentinel or registers frame. This frame obtains register values + direct from the inferior's registers. */ + SENTINEL_FRAME +}; + /* For every stopped thread, GDB tracks two frames: current and selected. Current frame is the inner most frame of the selected thread. Selected frame is the one being examined by the the GDB @@ -264,7 +283,13 @@ extern CORE_ADDR get_frame_pc (struct fr the frame's block. */ extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); -extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); + +/* Similar to get_frame_address_in_block, find an address in the + block which logically called NEXT_FRAME, assuming it was a THIS_TYPE + frame. */ + +extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type); /* The frame's inner-most bound. AKA the stack-pointer. Confusingly known as top-of-stack. */ @@ -374,24 +399,8 @@ extern CORE_ADDR get_frame_args_address for an invalid frame). */ extern int frame_relative_level (struct frame_info *fi); -/* Return the frame's type. Some are real, some are signal - trampolines, and some are completely artificial (dummy). */ +/* Return the frame's type. */ -enum frame_type -{ - /* A true stack frame, created by the target program during normal - execution. */ - NORMAL_FRAME, - /* A fake frame, created by GDB when performing an inferior function - call. */ - DUMMY_FRAME, - /* In a signal handler, various OSs handle this in various ways. - The main thing is that the frame may be far from normal. */ - SIGTRAMP_FRAME, - /* Sentinel or registers frame. This frame obtains register values - direct from the inferior's registers. */ - SENTINEL_FRAME -}; extern enum frame_type get_frame_type (struct frame_info *); /* For frames where we can not unwind further, describe why. */ Index: hppa-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/hppa-tdep.c,v retrieving revision 1.223 diff -u -p -r1.223 hppa-tdep.c --- hppa-tdep.c 8 Aug 2006 21:32:48 -0000 1.223 +++ hppa-tdep.c 3 Jan 2007 15:53:16 -0000 @@ -1786,9 +1786,14 @@ hppa_skip_prologue (CORE_ADDR pc) static struct unwind_table_entry * hppa_find_unwind_entry_in_block (struct frame_info *f) { - CORE_ADDR pc; + CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME); - pc = frame_unwind_address_in_block (f); + /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the + result of frame_unwind_address_in_block implies a problem. + The bits should have been removed earlier, before the return + value of frame_pc_unwind. That might be happening already; + if it isn't, it should be fixed. Then this call can be + removed. */ pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc); return find_unwind_entry (pc); } @@ -2440,7 +2445,7 @@ static const struct frame_unwind hppa_st static const struct frame_unwind * hppa_stub_unwind_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct gdbarch *gdbarch = get_frame_arch (next_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); Index: m88k-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m88k-tdep.c,v retrieving revision 1.19 diff -u -p -r1.19 m88k-tdep.c --- m88k-tdep.c 17 Dec 2005 22:34:01 -0000 1.19 +++ m88k-tdep.c 3 Jan 2007 15:53:16 -0000 @@ -661,10 +661,7 @@ m88k_frame_cache (struct frame_info *nex cache->pc = frame_func_unwind (next_frame); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - m88k_analyze_prologue (cache->pc, addr_in_block, cache); - } + m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); /* Calculate the stack pointer used in the prologue. */ if (cache->fp_offset != -1) Index: mips-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-mdebug-tdep.c,v retrieving revision 1.7 diff -u -p -r1.7 mips-mdebug-tdep.c --- mips-mdebug-tdep.c 25 Apr 2006 18:58:09 -0000 1.7 +++ mips-mdebug-tdep.c 3 Jan 2007 15:53:16 -0000 @@ -412,7 +412,7 @@ static const struct frame_unwind mips_md static const struct frame_unwind * mips_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); CORE_ADDR startaddr = 0; struct mdebug_extra_func_info *proc_desc; int kernel_trap; Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.399 diff -u -p -r1.399 mips-tdep.c --- mips-tdep.c 28 Nov 2006 22:14:31 -0000 1.399 +++ mips-tdep.c 3 Jan 2007 15:53:16 -0000 @@ -1698,7 +1698,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn16_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (mips_pc_is_mips16 (pc)) return &mips_insn16_frame_unwind; return NULL; @@ -2018,7 +2018,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn32_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (! mips_pc_is_mips16 (pc)) return &mips_insn32_frame_unwind; return NULL; @@ -2113,7 +2113,7 @@ static const struct frame_unwind * mips_stub_frame_sniffer (struct frame_info *next_frame) { struct obj_section *s; - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (in_plt_section (pc, NULL)) return &mips_stub_frame_unwind; Index: s390-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/s390-tdep.c,v retrieving revision 1.156 diff -u -p -r1.156 s390-tdep.c --- s390-tdep.c 28 Nov 2006 21:41:02 -0000 1.156 +++ s390-tdep.c 3 Jan 2007 15:53:16 -0000 @@ -1575,14 +1575,15 @@ static const struct frame_unwind s390_st static const struct frame_unwind * s390_stub_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR addr_in_block; bfd_byte insn[S390_MAX_INSTR_SIZE]; /* If the current PC points to non-readable memory, we assume we have trapped due to an invalid function pointer call. We handle the non-existing current function like a PLT stub. */ - if (in_plt_section (pc, NULL) - || s390_readinstruction (insn, pc) < 0) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) + || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0) return &s390_stub_frame_unwind; return NULL; } Index: sparc-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.c,v retrieving revision 1.175 diff -u -p -r1.175 sparc-tdep.c --- sparc-tdep.c 29 Dec 2006 21:00:47 -0000 1.175 +++ sparc-tdep.c 3 Jan 2007 15:53:17 -0000 @@ -701,10 +701,7 @@ sparc_frame_cache (struct frame_info *ne cache->pc = frame_func_unwind (next_frame); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - sparc_analyze_prologue (cache->pc, addr_in_block, cache); - } + sparc_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); if (cache->frameless_p) { @@ -1054,7 +1051,7 @@ sparc32_stabs_argument_has_addr (struct static int sparc32_dwarf2_struct_return_p (struct frame_info *next_frame) { - CORE_ADDR pc = frame_unwind_address_in_block (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct symbol *sym = find_pc_function (pc); if (sym) Index: sparc64obsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc64obsd-tdep.c,v retrieving revision 1.20 diff -u -p -r1.20 sparc64obsd-tdep.c --- sparc64obsd-tdep.c 31 Dec 2006 01:28:07 -0000 1.20 +++ sparc64obsd-tdep.c 3 Jan 2007 15:53:17 -0000 @@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru /* Kernel debugging support. */ static struct sparc_frame_cache * -sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) +sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; CORE_ADDR sp, trapframe_addr; @@ -267,15 +267,17 @@ static const struct frame_unwind sparc64 static const struct frame_unwind * sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) { + CORE_ADDR pc; ULONGEST pstate; char *name; /* Check whether we are in privileged mode, and bail out if we're not. */ - pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM); + pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); if ((pstate & SPARC64_PSTATE_PRIV) == 0) return NULL; - find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); + pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + find_pc_partial_function (pc, &name, NULL, NULL); if (name && strcmp (name, "Lslowtrap_reenter") == 0) return &sparc64obsd_trapframe_unwind; ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 16:13 ` Daniel Jacobowitz @ 2007-01-03 20:28 ` Mark Kettenis 2007-01-03 20:30 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-03 20:28 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Wed, 3 Jan 2007 11:12:57 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Wed, Jan 03, 2007 at 12:37:00PM +0100, Mark Kettenis wrote: > > The basic principle of unwinding is that you get information about > > THIS_FRAME from NEXT_FRAME; you always walk the frame chain in one > > direction. This means that the only requirement for calling > > frame_unwind_xxx functions is that you have a NEXT_FRAME. Your change > > introduces a function that breaks this rule, by requiring THIS_FRAME > > to be there, walking the frame chain in the other direction. And it > > didn't take you very long to hit the problem with that: infinite > > recursion. > > > > Now the problem we're facing is that frame_unwind_address_in_block() > > (frame_func_unwind() is nothing but a fancy wrapper around that call) > > cannot be implemented reliably without knowledge about THIS_FRAME; it > > needs to know whether THIS_FRAME could be a fake frame set up by the > > kernel in order to determine whether it is a good idea to adjust the > > unwound PC or not. In our current implementation that information is > > carried by the frame type. > > > > The solution I think, is to pass this information explicitly to > > frame_unwind_address_in_block(), i.e. we change it's prototype from: > > I've hit one hiccup with this... dwarf2_frame_this_id isn't calling > frame_unwind_address_in_block, just frame_func_unwind. So, if > we want frame_func_unwind to do the right thing, that's the > call site which needs to know the right frame type. Oh sorry Daniel, I thought it was obvious that frame_func_unwind() needed the same treatment as frame_unwind_address_in_block(). Mark ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 20:28 ` Mark Kettenis @ 2007-01-03 20:30 ` Daniel Jacobowitz 2007-01-03 21:58 ` Mark Kettenis 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-03 20:30 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Wed, Jan 03, 2007 at 09:27:57PM +0100, Mark Kettenis wrote: > Oh sorry Daniel, I thought it was obvious that frame_func_unwind() > needed the same treatment as frame_unwind_address_in_block(). Bother, 55 call sites in 37 files. Well, if you think this is the right change, I'll do it in a bit. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 20:30 ` Daniel Jacobowitz @ 2007-01-03 21:58 ` Mark Kettenis 2007-01-03 22:02 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-03 21:58 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Wed, 3 Jan 2007 15:30:07 -0500 > From: Daniel Jacobowitz <drow@false.org> > Cc: gdb-patches@sourceware.org > Mail-Followup-To: Mark Kettenis <mark.kettenis@xs4all.nl>, > gdb-patches@sourceware.org > Content-Disposition: inline > X-XS4ALL-DNSBL-Checked: mxdrop16.xs4all.nl checked 66.93.172.17 against DNS blacklists > X-Virus-Scanned: by XS4ALL Virus Scanner > X-XS4ALL-Spam-Score: 0.0 () DK_POLICY_SIGNSOME > X-XS4ALL-Spam: NO > Envelope-To: mark.kettenis@xs4all.nl > X-UIDL: 1167856210._smtp.mxdrop16.91782,S=1990 > > On Wed, Jan 03, 2007 at 09:27:57PM +0100, Mark Kettenis wrote: > > Oh sorry Daniel, I thought it was obvious that frame_func_unwind() > > needed the same treatment as frame_unwind_address_in_block(). > > Bother, 55 call sites in 37 files. Well, if you think this is > the right change, I'll do it in a bit. Heh, well, if you do the mechanical frame_unwind_address_in_block() changes I'll do frame_func_unwind(). After that we can actually worry about about fixing things. Deal? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 21:58 ` Mark Kettenis @ 2007-01-03 22:02 ` Daniel Jacobowitz 2007-01-03 22:23 ` Mark Kettenis 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-03 22:02 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Wed, Jan 03, 2007 at 10:58:25PM +0100, Mark Kettenis wrote: > Heh, well, if you do the mechanical frame_unwind_address_in_block() > changes I'll do frame_func_unwind(). > > After that we can actually worry about about fixing things. > > Deal? Absolutely. If you can hand me a patch which adds NORMAL_FRAME to every call to frame_func_unwind, I'll do all the rest. I'm pretty sure all of the existing call sites are NORMAL_FRAME; there won't be a SIGTRAMP_FRAME one until we split out two this_id functions for dwarf2. I've got frame_unwind_address_in_block done locally. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 22:02 ` Daniel Jacobowitz @ 2007-01-03 22:23 ` Mark Kettenis 2007-01-03 22:29 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-01-03 22:23 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Wed, 3 Jan 2007 17:02:24 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Wed, Jan 03, 2007 at 10:58:25PM +0100, Mark Kettenis wrote: > > Heh, well, if you do the mechanical frame_unwind_address_in_block() > > changes I'll do frame_func_unwind(). > > > > After that we can actually worry about about fixing things. > > > > Deal? > > Absolutely. If you can hand me a patch which adds NORMAL_FRAME to > every call to frame_func_unwind, I'll do all the rest. I'm pretty > sure all of the existing call sites are NORMAL_FRAME; there won't be a > SIGTRAMP_FRAME one until we split out two this_id functions for dwarf2. > > I've got frame_unwind_address_in_block done locally. Hmm, well, you need to commit that one first, because the frame_func_unwind() change will depend on it. But perhaps we should give people a few days to comment... Mark ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 22:23 ` Mark Kettenis @ 2007-01-03 22:29 ` Daniel Jacobowitz 2007-02-20 12:39 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-01-03 22:29 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Wed, Jan 03, 2007 at 11:23:08PM +0100, Mark Kettenis wrote: > Hmm, well, you need to commit that one first, because the > frame_func_unwind() change will depend on it. > > But perhaps we should give people a few days to comment... There's a call to frame_unwind_address_in_block in frame_func_unwind, so this is circular - got to break the loop one way or another. It will be simpler if I do both; once I've admitted it's got to be done, the mechanical change won't take but a few minutes. I'll take care of it (but not today). -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-01-03 22:29 ` Daniel Jacobowitz @ 2007-02-20 12:39 ` Daniel Jacobowitz 2007-02-20 15:31 ` Daniel Jacobowitz 2007-02-22 21:28 ` Mark Kettenis 0 siblings, 2 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-02-20 12:39 UTC (permalink / raw) To: Mark Kettenis, gdb-patches On Wed, Jan 03, 2007 at 05:28:54PM -0500, Daniel Jacobowitz wrote: > On Wed, Jan 03, 2007 at 11:23:08PM +0100, Mark Kettenis wrote: > > Hmm, well, you need to commit that one first, because the > > frame_func_unwind() change will depend on it. > > > > But perhaps we should give people a few days to comment... > > There's a call to frame_unwind_address_in_block in frame_func_unwind, > so this is circular - got to break the loop one way or another. > > It will be simpler if I do both; once I've admitted it's got to be > done, the mechanical change won't take but a few minutes. I'll > take care of it (but not today). Here we go. It's not too bad, all considered. Mark, thanks again for your help in finding a less hideous solution to this problem - I really appreciate it. Does this look OK to commit? I've tested it on x86_64-linux (where, with glibc HEAD, it fixes the remaining signal-related failures). And I built everything listed in MAINTAINERS using gdb_mbuild.sh. Related fixes in next message. -- Daniel Jacobowitz CodeSourcery 2007-02-20 Daniel Jacobowitz <dan@codesourcery.com> * dwarf2-frame.c (dwarf2_frame_cache, dwarf2_frame_this_id) (dwarf2_frame_sniffer): Update. (dwarf2_signal_frame_this_id): New function. (dwarf2_signal_frame_unwind): Use it. (dwarf2_frame_base_sniffer): Use frame_unwind_address_in_block. * frame-unwind.c (searching_for_unwind): New. (clear_searching_flag): New. (frame_unwind_find_by_frame): Assert that this function is not entered recursively. * frame.c (frame_func_unwind): Add this_type argument. (get_frame_func): Update. (frame_unwind_address_in_block): Add this_type argument and check it. Fix a typo. (get_frame_address_in_block): Update. * frame.h (enum frame_type): Move higher in the file. (frame_unwind_address_in_block, frame_func_unwind): Add enum frame_type argument. * alpha-mdebug-tdep.c, alpha-tdep.c, amd64-tdep.c, amd64obsd-tdep.c, arm-tdep.c, avr-tdep.c, cris-tdep.c, frv-tdep.c, h8300-tdep.c, hppa-tdep.c, i386-tdep.c, i386obsd-tdep.c, ia64-tdep.c, libunwind-frame.c, m32c-tdep.c, m32r-linux-tdep.c, m32r-tdep.c, m68hc11-tdep.c, m68k-tdep.c, m88k-tdep.c, mips-mdebug-tdep.c, mips-tdep.c, mn10300-tdep.c, mt-tdep.c, rs6000-tdep.c, s390-tdep.c, score-tdep.c, sh-tdep.c, sh64-tdep.c, sparc-tdep.c, sparc64obsd-tdep.c, spu-tdep.c, v850-tdep.c, vax-tdep.c, xstormy16-tdep.c, xtensa-tdep.c: Update calls to frame_func_unwind and frame_unwind_address_in_block to specify the frame type. Use frame_unwind_address_in_block instead of frame_pc_unwind in sniffers. --- gdb/alpha-mdebug-tdep.c | 7 +++--- gdb/alpha-tdep.c | 2 - gdb/amd64-tdep.c | 2 - gdb/amd64obsd-tdep.c | 4 ++- gdb/arm-tdep.c | 6 +++-- gdb/avr-tdep.c | 4 +-- gdb/cris-tdep.c | 8 ++++--- gdb/dwarf2-frame.c | 34 +++++++++++++++++++++++++------- gdb/frame-unwind.c | 28 ++++++++++++++++++++++++-- gdb/frame.c | 26 +++++++++++++++++------- gdb/frame.h | 51 ++++++++++++++++++++++++++++++------------------ gdb/frv-tdep.c | 5 ++-- gdb/h8300-tdep.c | 2 - gdb/hppa-tdep.c | 21 +++++++++++++------ gdb/i386-tdep.c | 2 - gdb/i386obsd-tdep.c | 4 ++- gdb/ia64-tdep.c | 2 - gdb/libunwind-frame.c | 5 +++- gdb/m32c-tdep.c | 5 ++-- gdb/m32r-linux-tdep.c | 2 - gdb/m32r-tdep.c | 4 +-- gdb/m68hc11-tdep.c | 4 +-- gdb/m68k-tdep.c | 2 - gdb/m88k-tdep.c | 7 +----- gdb/mips-mdebug-tdep.c | 5 ++-- gdb/mips-tdep.c | 12 ++++++----- gdb/mn10300-tdep.c | 9 +++++--- gdb/mt-tdep.c | 9 +++----- gdb/rs6000-tdep.c | 5 ++-- gdb/s390-tdep.c | 9 ++++---- gdb/score-tdep.c | 3 +- gdb/sh-tdep.c | 2 - gdb/sh64-tdep.c | 2 - gdb/sparc-tdep.c | 9 ++------ gdb/sparc64obsd-tdep.c | 8 ++++--- gdb/spu-tdep.c | 2 - gdb/v850-tdep.c | 2 - gdb/vax-tdep.c | 3 +- gdb/xstormy16-tdep.c | 2 - gdb/xtensa-tdep.c | 2 - 40 files changed, 208 insertions(+), 113 deletions(-) Index: src/gdb/alpha-mdebug-tdep.c =================================================================== --- src.orig/gdb/alpha-mdebug-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/alpha-mdebug-tdep.c 2007-02-19 14:43:19.000000000 -0500 @@ -246,7 +246,8 @@ alpha_mdebug_frame_this_id (struct frame struct alpha_mdebug_unwind_cache *info = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); - *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame)); + *this_id = frame_id_build (info->vfp, + frame_func_unwind (next_frame, NORMAL_FRAME)); } /* Retrieve the value of REGNUM in FRAME. Don't give up! */ @@ -311,7 +312,7 @@ static const struct frame_unwind alpha_m const struct frame_unwind * alpha_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an @@ -368,7 +369,7 @@ static const struct frame_base alpha_mde static const struct frame_base * alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an Index: src/gdb/alpha-tdep.c =================================================================== --- src.orig/gdb/alpha-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/alpha-tdep.c 2007-02-19 14:43:05.000000000 -0500 @@ -820,7 +820,7 @@ alpha_sigtramp_frame_this_id (struct fra code_addr = 0; } else - code_addr = frame_func_unwind (next_frame); + code_addr = frame_func_unwind (next_frame, SIGTRAMP_FRAME); /* The stack address is trivially read from the sigcontext. */ stack_addr = alpha_sigtramp_register_address (info->sigcontext_addr, Index: src/gdb/amd64-tdep.c =================================================================== --- src.orig/gdb/amd64-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/amd64-tdep.c 2007-02-19 14:42:58.000000000 -0500 @@ -833,7 +833,7 @@ amd64_frame_cache (struct frame_info *ne cache = amd64_alloc_frame_cache (); *this_cache = cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) amd64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: src/gdb/amd64obsd-tdep.c =================================================================== --- src.orig/gdb/amd64obsd-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/amd64obsd-tdep.c 2007-02-19 14:42:47.000000000 -0500 @@ -356,7 +356,9 @@ amd64obsd_trapframe_cache(struct frame_i cache = trad_frame_cache_zalloc (next_frame); *this_cache = cache; - func = frame_func_unwind (next_frame); + /* NORMAL_FRAME matches the type in amd64obsd_trapframe_unwind, but + SIGTRAMP_FRAME might be more appropriate. */ + func = frame_func_unwind (next_frame, NORMAL_FRAME); sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); Index: src/gdb/arm-tdep.c =================================================================== --- src.orig/gdb/arm-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/arm-tdep.c 2007-02-19 14:41:27.000000000 -0500 @@ -929,7 +929,7 @@ arm_prologue_this_id (struct frame_info *this_cache = arm_make_prologue_cache (next_frame); cache = *this_cache; - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* This is meant to halt the backtrace at "_start". Make sure we don't halt it at a generic dummy frame. */ @@ -1034,9 +1034,11 @@ struct frame_unwind arm_stub_unwind = { static const struct frame_unwind * arm_stub_unwind_sniffer (struct frame_info *next_frame) { + CORE_ADDR addr_in_block; char dummy[4]; - if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0) return &arm_stub_unwind; Index: src/gdb/avr-tdep.c =================================================================== --- src.orig/gdb/avr-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/avr-tdep.c 2007-02-19 14:41:19.000000000 -0500 @@ -875,7 +875,7 @@ avr_frame_unwind_cache (struct frame_inf info->size = 0; info->prologue_type = AVR_PROLOGUE_NONE; - pc = frame_func_unwind (next_frame); + pc = frame_func_unwind (next_frame, NORMAL_FRAME); if ((pc > 0) && (pc < frame_pc_unwind (next_frame))) avr_scan_prologue (pc, info); @@ -958,7 +958,7 @@ avr_frame_this_id (struct frame_info *ne struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: src/gdb/cris-tdep.c =================================================================== --- src.orig/gdb/cris-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/cris-tdep.c 2007-02-19 14:41:08.000000000 -0500 @@ -792,9 +792,11 @@ cris_frame_unwind_cache (struct frame_in /* Prologue analysis does the rest... */ if (cris_version () == 32) - crisv32_scan_prologue (frame_func_unwind (next_frame), next_frame, info); + crisv32_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); else - cris_scan_prologue (frame_func_unwind (next_frame), next_frame, info); + cris_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); return info; } @@ -814,7 +816,7 @@ cris_frame_this_id (struct frame_info *n struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: src/gdb/dwarf2-frame.c =================================================================== --- src.orig/gdb/dwarf2-frame.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/dwarf2-frame.c 2007-02-19 14:40:11.000000000 -0500 @@ -848,7 +848,7 @@ dwarf2_frame_cache (struct frame_info *n frame_unwind_address_in_block does just this. It's not clear how reliable the method is though; there is the potential for the register state pre-call being different to that on return. */ - fs->pc = frame_unwind_address_in_block (next_frame); + fs->pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); /* Find the correct FDE. */ fde = dwarf2_frame_find_fde (&fs->pc); @@ -1011,7 +1011,22 @@ dwarf2_frame_this_id (struct frame_info if (cache->undefined_retaddr) return; - (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (cache->cfa, + frame_func_unwind (next_frame, NORMAL_FRAME)); +} + +static void +dwarf2_signal_frame_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct dwarf2_frame_cache *cache = + dwarf2_frame_cache (next_frame, this_cache); + + if (cache->undefined_retaddr) + return; + + (*this_id) = frame_id_build (cache->cfa, + frame_func_unwind (next_frame, SIGTRAMP_FRAME)); } static void @@ -1179,7 +1194,7 @@ static const struct frame_unwind dwarf2_ static const struct frame_unwind dwarf2_signal_frame_unwind = { SIGTRAMP_FRAME, - dwarf2_frame_this_id, + dwarf2_signal_frame_this_id, dwarf2_frame_prev_register }; @@ -1188,8 +1203,12 @@ dwarf2_frame_sniffer (struct frame_info { /* Grab an address that is guarenteed to reside somewhere within the function. frame_pc_unwind(), for a no-return next function, can - end up returning something past the end of this function's body. */ - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); + end up returning something past the end of this function's body. + If the frame we're sniffing for is a signal frame whose start + address is placed on the stack by the OS, its FDE must + extend one byte before its start address or we will miss it. */ + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); if (!fde) return NULL; @@ -1233,8 +1252,9 @@ static const struct frame_base dwarf2_fr const struct frame_base * dwarf2_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - if (dwarf2_frame_find_fde (&pc)) + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); + if (dwarf2_frame_find_fde (&block_addr)) return &dwarf2_frame_base; return NULL; Index: src/gdb/frame-unwind.c =================================================================== --- src.orig/gdb/frame-unwind.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/frame-unwind.c 2007-02-19 14:36:33.000000000 -0500 @@ -28,6 +28,8 @@ static struct gdbarch_data *frame_unwind_data; +static int searching_for_unwind; + struct frame_unwind_table_entry { frame_unwind_sniffer_ftype *sniffer; @@ -83,6 +85,12 @@ frame_unwind_prepend_unwinder (struct gd (*table->osabi_head) = entry; } +static void +clear_searching_flag (void *arg) +{ + searching_for_unwind = 0; +} + const struct frame_unwind * frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache) { @@ -90,6 +98,15 @@ frame_unwind_find_by_frame (struct frame struct gdbarch *gdbarch = get_frame_arch (next_frame); struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); struct frame_unwind_table_entry *entry; + struct cleanup *back_to; + + /* Check if we were re-entered, and assert instead of running out + of stack. This happens if the sniffer calls anything which + requires NEXT_FRAME's unwinder. */ + gdb_assert (!searching_for_unwind); + searching_for_unwind = 1; + back_to = make_cleanup (clear_searching_flag, NULL); + for (entry = table->list; entry != NULL; entry = entry->next) { if (entry->sniffer != NULL) @@ -97,15 +114,22 @@ frame_unwind_find_by_frame (struct frame const struct frame_unwind *desc = NULL; desc = entry->sniffer (next_frame); if (desc != NULL) - return desc; + { + do_cleanups (back_to); + return desc; + } } if (entry->unwinder != NULL) { if (entry->unwinder->sniffer (entry->unwinder, next_frame, this_cache)) - return entry->unwinder; + { + do_cleanups (back_to); + return entry->unwinder; + } } } + do_cleanups (back_to); internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed")); } Index: src/gdb/frame.c =================================================================== --- src.orig/gdb/frame.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/frame.c 2007-02-19 14:36:01.000000000 -0500 @@ -471,13 +471,13 @@ frame_pc_unwind (struct frame_info *this } CORE_ADDR -frame_func_unwind (struct frame_info *fi) +frame_func_unwind (struct frame_info *fi, enum frame_type this_type) { if (!fi->prev_func.p) { /* Make certain that this, and not the adjacent, function is found. */ - CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi); + CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi, this_type); fi->prev_func.p = 1; fi->prev_func.addr = get_pc_function_start (addr_in_block); if (frame_debug) @@ -491,7 +491,7 @@ frame_func_unwind (struct frame_info *fi CORE_ADDR get_frame_func (struct frame_info *fi) { - return frame_func_unwind (fi->next); + return frame_func_unwind (fi->next, get_frame_type (fi)); } static int @@ -1496,20 +1496,31 @@ get_frame_pc (struct frame_info *frame) return frame_pc_unwind (frame->next); } -/* Return an address of that falls within the frame's code block. */ +/* Return an address that falls within NEXT_FRAME's caller's code + block, assuming that the caller is a THIS_TYPE frame. */ CORE_ADDR -frame_unwind_address_in_block (struct frame_info *next_frame) +frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type) { /* A draft address. */ CORE_ADDR pc = frame_pc_unwind (next_frame); + /* If NEXT_FRAME was called by a signal frame or dummy frame, then + we shold not adjust the unwound PC. These frames may not call + their next frame in the normal way; the operating system or GDB + may have pushed their resume address manually onto the stack, so + it may be the very first instruction. Even if the resume address + was not manually pushed, they expect to be returned to. */ + if (this_type != NORMAL_FRAME) + return pc; + /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel), and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS frame's PC ends up pointing at the instruction fallowing the "call". Adjust that PC value so that it falls on the call instruction (which, hopefully, falls within THIS frame's code - block. So far it's proved to be a very good approximation. See + block). So far it's proved to be a very good approximation. See get_frame_type() for why ->type can't be used. */ if (next_frame->level >= 0 && get_frame_type (next_frame) == NORMAL_FRAME) @@ -1520,7 +1531,8 @@ frame_unwind_address_in_block (struct fr CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame) { - return frame_unwind_address_in_block (this_frame->next); + return frame_unwind_address_in_block (this_frame->next, + get_frame_type (this_frame)); } static int Index: src/gdb/frame.h =================================================================== --- src.orig/gdb/frame.h 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/frame.h 2007-02-19 14:34:33.000000000 -0500 @@ -184,6 +184,25 @@ extern int frame_id_inner (struct frame_ extern void fprint_frame_id (struct ui_file *file, struct frame_id id); +/* Frame types. Some are real, some are signal trampolines, and some + are completely artificial (dummy). */ + +enum frame_type +{ + /* A true stack frame, created by the target program during normal + execution. */ + NORMAL_FRAME, + /* A fake frame, created by GDB when performing an inferior function + call. */ + DUMMY_FRAME, + /* In a signal handler, various OSs handle this in various ways. + The main thing is that the frame may be far from normal. */ + SIGTRAMP_FRAME, + /* Sentinel or registers frame. This frame obtains register values + direct from the inferior's registers. */ + SENTINEL_FRAME +}; + /* For every stopped thread, GDB tracks two frames: current and selected. Current frame is the inner most frame of the selected thread. Selected frame is the one being examined by the the GDB @@ -265,7 +284,13 @@ extern CORE_ADDR get_frame_pc (struct fr the frame's block. */ extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); -extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); + +/* Similar to get_frame_address_in_block, find an address in the + block which logically called NEXT_FRAME, assuming it is a THIS_TYPE + frame. */ + +extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type); /* The frame's inner-most bound. AKA the stack-pointer. Confusingly known as top-of-stack. */ @@ -277,9 +302,13 @@ extern CORE_ADDR frame_sp_unwind (struct /* Following on from the `resume' address. Return the entry point address of the function containing that resume address, or zero if that function isn't known. */ -extern CORE_ADDR frame_func_unwind (struct frame_info *fi); extern CORE_ADDR get_frame_func (struct frame_info *fi); +/* Similar to get_frame_func, find the start of the function which + logically called NEXT_FRAME, assuming it is a THIS_TYPE frame. */ +extern CORE_ADDR frame_func_unwind (struct frame_info *next_frame, + enum frame_type this_type); + /* Closely related to the resume address, various symbol table attributes that are determined by the PC. Note that for a normal frame, the PC refers to the resume address after the return, and @@ -375,24 +404,8 @@ extern CORE_ADDR get_frame_args_address for an invalid frame). */ extern int frame_relative_level (struct frame_info *fi); -/* Return the frame's type. Some are real, some are signal - trampolines, and some are completely artificial (dummy). */ +/* Return the frame's type. */ -enum frame_type -{ - /* A true stack frame, created by the target program during normal - execution. */ - NORMAL_FRAME, - /* A fake frame, created by GDB when performing an inferior function - call. */ - DUMMY_FRAME, - /* In a signal handler, various OSs handle this in various ways. - The main thing is that the frame may be far from normal. */ - SIGTRAMP_FRAME, - /* Sentinel or registers frame. This frame obtains register values - direct from the inferior's registers. */ - SENTINEL_FRAME -}; extern enum frame_type get_frame_type (struct frame_info *); /* For frames where we can not unwind further, describe why. */ Index: src/gdb/frv-tdep.c =================================================================== --- src.orig/gdb/frv-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/frv-tdep.c 2007-02-19 16:39:55.000000000 -0500 @@ -1016,7 +1016,8 @@ frv_frame_unwind_cache (struct frame_inf info->saved_regs = trad_frame_alloc_saved_regs (next_frame); /* Prologue analysis does the rest... */ - frv_analyze_prologue (frame_func_unwind (next_frame), next_frame, info); + frv_analyze_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); return info; } @@ -1346,7 +1347,7 @@ frv_frame_this_id (struct frame_info *ne struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); Index: src/gdb/h8300-tdep.c =================================================================== --- src.orig/gdb/h8300-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/h8300-tdep.c 2007-02-19 14:29:32.000000000 -0500 @@ -447,7 +447,7 @@ h8300_frame_cache (struct frame_info *ne cache->saved_regs[E_PC_REGNUM] = -BINWORD; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) h8300_analyze_prologue (cache->pc, current_pc, cache); Index: src/gdb/hppa-tdep.c =================================================================== --- src.orig/gdb/hppa-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/hppa-tdep.c 2007-02-19 14:29:26.000000000 -0500 @@ -1787,9 +1787,14 @@ hppa_skip_prologue (CORE_ADDR pc) static struct unwind_table_entry * hppa_find_unwind_entry_in_block (struct frame_info *f) { - CORE_ADDR pc; + CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME); - pc = frame_unwind_address_in_block (f); + /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the + result of frame_unwind_address_in_block implies a problem. + The bits should have been removed earlier, before the return + value of frame_pc_unwind. That might be happening already; + if it isn't, it should be fixed. Then this call can be + removed. */ pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc); return find_unwind_entry (pc); } @@ -1899,7 +1904,7 @@ hppa_frame_cache (struct frame_info *nex if ((u->Region_description & 0x2) == 0) start_pc = u->region_start; else - start_pc = frame_func_unwind (next_frame); + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); prologue_end = skip_prologue_hard_way (start_pc, 0); end_pc = frame_pc_unwind (next_frame); @@ -2267,7 +2272,7 @@ hppa_fallback_frame_cache (struct frame_ (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - start_pc = frame_func_unwind (next_frame); + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (start_pc) { CORE_ADDR cur_pc = frame_pc_unwind (next_frame); @@ -2326,7 +2331,8 @@ hppa_fallback_frame_this_id (struct fram { struct hppa_frame_cache *info = hppa_fallback_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -2409,7 +2415,8 @@ hppa_stub_frame_this_id (struct frame_in = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache); if (info) - *this_id = frame_id_build (info->base, frame_func_unwind (next_frame)); + *this_id = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); else *this_id = null_frame_id; } @@ -2441,7 +2448,7 @@ static const struct frame_unwind hppa_st static const struct frame_unwind * hppa_stub_unwind_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct gdbarch *gdbarch = get_frame_arch (next_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); Index: src/gdb/i386-tdep.c =================================================================== --- src.orig/gdb/i386-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/i386-tdep.c 2007-02-19 14:28:52.000000000 -0500 @@ -949,7 +949,7 @@ i386_frame_cache (struct frame_info *nex /* For normal frames, %eip is stored at 4(%ebp). */ cache->saved_regs[I386_EIP_REGNUM] = 4; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: src/gdb/i386obsd-tdep.c =================================================================== --- src.orig/gdb/i386obsd-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/i386obsd-tdep.c 2007-02-19 14:28:41.000000000 -0500 @@ -353,7 +353,9 @@ i386obsd_trapframe_cache(struct frame_in cache = trad_frame_cache_zalloc (next_frame); *this_cache = cache; - func = frame_func_unwind (next_frame); + /* NORMAL_FRAME matches the type in i386obsd_trapframe_unwind, but + SIGTRAMP_FRAME might be more appropriate. */ + func = frame_func_unwind (next_frame, NORMAL_FRAME); sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); Index: src/gdb/ia64-tdep.c =================================================================== --- src.orig/gdb/ia64-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/ia64-tdep.c 2007-02-19 14:27:10.000000000 -0500 @@ -1555,7 +1555,7 @@ ia64_frame_cache (struct frame_info *nex cache->cfm = cfm; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) examine_prologue (cache->pc, frame_pc_unwind (next_frame), next_frame, cache); Index: src/gdb/libunwind-frame.c =================================================================== --- src.orig/gdb/libunwind-frame.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/libunwind-frame.c 2007-02-19 14:26:49.000000000 -0500 @@ -141,7 +141,10 @@ libunwind_frame_cache (struct frame_info /* Allocate a new cache. */ cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); - cache->func_addr = frame_func_unwind (next_frame); + /* We can assume we are unwinding a normal frame. Even if this is + for a signal trampoline, ia64 signal "trampolines" use a normal + subroutine call to start the signal handler. */ + cache->func_addr = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->func_addr == 0 && frame_relative_level (next_frame) > 0 && get_frame_type (next_frame) != SIGTRAMP_FRAME) Index: src/gdb/m32c-tdep.c =================================================================== --- src.orig/gdb/m32c-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/m32c-tdep.c 2007-02-19 13:59:05.000000000 -0500 @@ -1836,7 +1836,7 @@ m32c_analyze_frame_prologue (struct fram { if (! *this_prologue_cache) { - CORE_ADDR func_start = frame_func_unwind (next_frame); + CORE_ADDR func_start = frame_func_unwind (next_frame, NORMAL_FRAME); CORE_ADDR stop_addr = frame_pc_unwind (next_frame); /* If we couldn't find any function containing the PC, then @@ -1900,7 +1900,8 @@ m32c_this_id (struct frame_info *next_fr CORE_ADDR base = m32c_frame_base (next_frame, this_prologue_cache); if (base) - *this_id = frame_id_build (base, frame_func_unwind (next_frame)); + *this_id = frame_id_build (base, + frame_func_unwind (next_frame, NORMAL_FRAME)); /* Otherwise, leave it unset, and that will terminate the backtrace. */ } Index: src/gdb/m32r-linux-tdep.c =================================================================== --- src.orig/gdb/m32r-linux-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/m32r-linux-tdep.c 2007-02-19 14:03:30.000000000 -0500 @@ -250,7 +250,7 @@ m32r_linux_sigtramp_frame_cache (struct if (addr) sigcontext_addr += 128; else - addr = frame_func_unwind (next_frame); + addr = frame_func_unwind (next_frame, NORMAL_FRAME); } cache->pc = addr; Index: src/gdb/m32r-tdep.c =================================================================== --- src.orig/gdb/m32r-tdep.c 2007-02-19 13:57:27.000000000 -0500 +++ src/gdb/m32r-tdep.c 2007-02-19 14:03:17.000000000 -0500 @@ -536,7 +536,7 @@ m32r_frame_unwind_cache (struct frame_in info->uses_frame = 0; scan_limit = frame_pc_unwind (next_frame); - for (pc = frame_func_unwind (next_frame); + for (pc = frame_func_unwind (next_frame, NORMAL_FRAME); pc > 0 && pc < scan_limit; pc += 2) { if ((pc & 2) == 0) @@ -835,7 +835,7 @@ m32r_frame_this_id (struct frame_info *n struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); Index: src/gdb/m68hc11-tdep.c =================================================================== --- src.orig/gdb/m68hc11-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/m68hc11-tdep.c 2007-02-19 14:03:01.000000000 -0500 @@ -798,7 +798,7 @@ m68hc11_frame_unwind_cache (struct frame (*this_prologue_cache) = info; info->saved_regs = trad_frame_alloc_saved_regs (next_frame); - info->pc = frame_func_unwind (next_frame); + info->pc = frame_func_unwind (next_frame, NORMAL_FRAME); info->size = 0; info->return_kind = m68hc11_get_return_insn (info->pc); @@ -889,7 +889,7 @@ m68hc11_frame_this_id (struct frame_info struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: src/gdb/m68k-tdep.c =================================================================== --- src.orig/gdb/m68k-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/m68k-tdep.c 2007-02-19 14:02:53.000000000 -0500 @@ -819,7 +819,7 @@ m68k_frame_cache (struct frame_info *nex /* For normal frames, %pc is stored at 4(%fp). */ cache->saved_regs[M68K_PC_REGNUM] = 4; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) m68k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: src/gdb/m88k-tdep.c =================================================================== --- src.orig/gdb/m88k-tdep.c 2007-01-29 12:37:47.000000000 -0500 +++ src/gdb/m88k-tdep.c 2007-02-19 14:02:45.000000000 -0500 @@ -659,12 +659,9 @@ m88k_frame_cache (struct frame_info *nex cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); cache->fp_offset = -1; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - m88k_analyze_prologue (cache->pc, addr_in_block, cache); - } + m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); /* Calculate the stack pointer used in the prologue. */ if (cache->fp_offset != -1) Index: src/gdb/mips-mdebug-tdep.c =================================================================== --- src.orig/gdb/mips-mdebug-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/mips-mdebug-tdep.c 2007-02-19 14:02:39.000000000 -0500 @@ -386,7 +386,8 @@ mips_mdebug_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -412,7 +413,7 @@ static const struct frame_unwind mips_md static const struct frame_unwind * mips_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); CORE_ADDR startaddr = 0; struct mdebug_extra_func_info *proc_desc; int kernel_trap; Index: src/gdb/mips-tdep.c =================================================================== --- src.orig/gdb/mips-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/mips-tdep.c 2007-02-19 16:44:38.000000000 -0500 @@ -1666,7 +1666,8 @@ mips_insn16_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -1692,7 +1693,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn16_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (mips_pc_is_mips16 (pc)) return &mips_insn16_frame_unwind; return NULL; @@ -1986,7 +1987,8 @@ mips_insn32_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -2012,7 +2014,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn32_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (! mips_pc_is_mips16 (pc)) return &mips_insn32_frame_unwind; return NULL; @@ -2107,7 +2109,7 @@ static const struct frame_unwind * mips_stub_frame_sniffer (struct frame_info *next_frame) { struct obj_section *s; - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (in_plt_section (pc, NULL)) return &mips_stub_frame_unwind; Index: src/gdb/mn10300-tdep.c =================================================================== --- src.orig/gdb/mn10300-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/mn10300-tdep.c 2007-02-19 14:44:23.000000000 -0500 @@ -850,9 +850,12 @@ mn10300_frame_unwind_cache (struct frame frame_id_build (trad_frame_get_this_base (cache), start)); else - trad_frame_set_id (cache, - frame_id_build (trad_frame_get_this_base (cache), - frame_func_unwind (next_frame))); + { + start = frame_func_unwind (next_frame, NORMAL_FRAME); + trad_frame_set_id (cache, + frame_id_build (trad_frame_get_this_base (cache), + start)); + } (*this_prologue_cache) = cache; return cache; Index: src/gdb/mt-tdep.c =================================================================== --- src.orig/gdb/mt-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/mt-tdep.c 2007-02-19 14:00:49.000000000 -0500 @@ -891,7 +891,7 @@ mt_frame_unwind_cache (struct frame_info frame_unwind_unsigned_register (next_frame, MT_SP_REGNUM, &sp); frame_unwind_unsigned_register (next_frame, MT_FP_REGNUM, &fp); - start_addr = frame_func_unwind (next_frame); + start_addr = frame_func_unwind (next_frame, NORMAL_FRAME); /* Return early if GDB couldn't find the function. */ if (start_addr == 0) @@ -1041,10 +1041,9 @@ mt_frame_this_id (struct frame_info *nex mt_frame_unwind_cache (next_frame, this_prologue_cache); if (!(info == NULL || info->prev_sp == 0)) - { - (*this_id) = frame_id_build (info->prev_sp, - frame_func_unwind (next_frame)); - } + (*this_id) = frame_id_build (info->prev_sp, + frame_func_unwind (next_frame, NORMAL_FRAME)); + return; } Index: src/gdb/rs6000-tdep.c =================================================================== --- src.orig/gdb/rs6000-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/rs6000-tdep.c 2007-02-19 14:00:20.000000000 -0500 @@ -2970,7 +2970,7 @@ rs6000_frame_cache (struct frame_info *n (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); pc = frame_pc_unwind (next_frame); skip_prologue (func, pc, &fdata); @@ -3122,7 +3122,8 @@ rs6000_frame_this_id (struct frame_info { struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: src/gdb/s390-tdep.c =================================================================== --- src.orig/gdb/s390-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/s390-tdep.c 2007-02-19 13:59:56.000000000 -0500 @@ -1232,7 +1232,7 @@ s390_prologue_frame_unwind_cache (struct bother searching for it -- with modern compilers this would be mostly pointless anyway. Trust that we'll either have valid DWARF-2 CFI data or else a valid backchain ... */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); if (!func) return 0; @@ -1556,14 +1556,15 @@ static const struct frame_unwind s390_st static const struct frame_unwind * s390_stub_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR addr_in_block; bfd_byte insn[S390_MAX_INSTR_SIZE]; /* If the current PC points to non-readable memory, we assume we have trapped due to an invalid function pointer call. We handle the non-existing current function like a PLT stub. */ - if (in_plt_section (pc, NULL) - || s390_readinstruction (insn, pc) < 0) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) + || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0) return &s390_stub_frame_unwind; return NULL; } Index: src/gdb/score-tdep.c =================================================================== --- src.orig/gdb/score-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/score-tdep.c 2007-02-19 14:00:34.000000000 -0500 @@ -801,7 +801,8 @@ score_prologue_this_id (struct frame_inf { struct score_frame_cache *info = score_make_prologue_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: src/gdb/sh-tdep.c =================================================================== --- src.orig/gdb/sh-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/sh-tdep.c 2007-02-19 13:59:47.000000000 -0500 @@ -2215,7 +2215,7 @@ sh_frame_cache (struct frame_info *next_ if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) sh_analyze_prologue (cache->pc, current_pc, cache); Index: src/gdb/sh64-tdep.c =================================================================== --- src.orig/gdb/sh64-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/sh64-tdep.c 2007-02-19 13:59:42.000000000 -0500 @@ -2254,7 +2254,7 @@ sh64_frame_cache (struct frame_info *nex if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) sh64_analyze_prologue (current_gdbarch, cache, cache->pc, current_pc); Index: src/gdb/sparc-tdep.c =================================================================== --- src.orig/gdb/sparc-tdep.c 2007-01-29 12:37:48.000000000 -0500 +++ src/gdb/sparc-tdep.c 2007-02-19 13:59:36.000000000 -0500 @@ -699,12 +699,9 @@ sparc_frame_cache (struct frame_info *ne cache = sparc_alloc_frame_cache (); *this_cache = cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - sparc_analyze_prologue (cache->pc, addr_in_block, cache); - } + sparc_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); if (cache->frameless_p) { @@ -1054,7 +1051,7 @@ sparc32_stabs_argument_has_addr (struct static int sparc32_dwarf2_struct_return_p (struct frame_info *next_frame) { - CORE_ADDR pc = frame_unwind_address_in_block (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct symbol *sym = find_pc_function (pc); if (sym) Index: src/gdb/sparc64obsd-tdep.c =================================================================== --- src.orig/gdb/sparc64obsd-tdep.c 2007-02-19 13:55:34.000000000 -0500 +++ src/gdb/sparc64obsd-tdep.c 2007-02-19 13:55:54.000000000 -0500 @@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru /* Kernel debugging support. */ static struct sparc_frame_cache * -sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) +sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; CORE_ADDR sp, trapframe_addr; @@ -267,15 +267,17 @@ static const struct frame_unwind sparc64 static const struct frame_unwind * sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) { + CORE_ADDR pc; ULONGEST pstate; char *name; /* Check whether we are in privileged mode, and bail out if we're not. */ - pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM); + pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); if ((pstate & SPARC64_PSTATE_PRIV) == 0) return NULL; - find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); + pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + find_pc_partial_function (pc, &name, NULL, NULL); if (name && strcmp (name, "Lslowtrap_reenter") == 0) return &sparc64obsd_trapframe_unwind; Index: src/gdb/spu-tdep.c =================================================================== --- src.orig/gdb/spu-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/spu-tdep.c 2007-02-19 13:58:13.000000000 -0500 @@ -587,7 +587,7 @@ spu_frame_unwind_cache (struct frame_inf info->local_base = 0; /* Find the start of the current function, and analyze its prologue. */ - info->func = frame_func_unwind (next_frame); + info->func = frame_func_unwind (next_frame, NORMAL_FRAME); if (info->func == 0) { /* Fall back to using the current PC as frame ID. */ Index: src/gdb/v850-tdep.c =================================================================== --- src.orig/gdb/v850-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/v850-tdep.c 2007-02-19 13:59:27.000000000 -0500 @@ -856,7 +856,7 @@ v850_frame_cache (struct frame_info *nex if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) v850_analyze_prologue (cache->pc, current_pc, cache); Index: src/gdb/vax-tdep.c =================================================================== --- src.orig/gdb/vax-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/vax-tdep.c 2007-02-19 13:59:20.000000000 -0500 @@ -384,7 +384,8 @@ vax_frame_this_id (struct frame_info *ne if (cache->base == 0) return; - (*this_id) = frame_id_build (cache->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (cache->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: src/gdb/xstormy16-tdep.c =================================================================== --- src.orig/gdb/xstormy16-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/xstormy16-tdep.c 2007-02-19 13:59:13.000000000 -0500 @@ -655,7 +655,7 @@ xstormy16_frame_cache (struct frame_info if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc) xstormy16_analyze_prologue (cache->pc, current_pc, cache, next_frame); Index: src/gdb/xtensa-tdep.c =================================================================== --- src.orig/gdb/xtensa-tdep.c 2007-02-19 13:57:28.000000000 -0500 +++ src/gdb/xtensa-tdep.c 2007-02-19 13:58:06.000000000 -0500 @@ -924,7 +924,7 @@ xtensa_frame_cache (struct frame_info *n cache->ws = ws & ~(1 << wb); } - cache->pc = ((frame_func_unwind (next_frame) & 0xc0000000) + cache->pc = ((frame_func_unwind (next_frame, NORMAL_FRAME) & 0xc0000000) | (ra & 0x3fffffff)); cache->ps = (ps & ~PS_CALLINC_MASK) | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT); ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-02-20 12:39 ` Daniel Jacobowitz @ 2007-02-20 15:31 ` Daniel Jacobowitz 2007-02-20 16:20 ` Daniel Jacobowitz 2007-02-22 21:28 ` Mark Kettenis 1 sibling, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-02-20 15:31 UTC (permalink / raw) To: gdb-patches; +Cc: Mark Kettenis On Tue, Feb 20, 2007 at 07:38:52AM -0500, Daniel Jacobowitz wrote: > Here we go. It's not too bad, all considered. Hmm, one small additional downside: it sends the *_FRAME constants out into dozens of new files. I was poking at adding a new one, which requires auditing all of the existing uses, which has now gotten much harder. That's not a fatal flaw in this patch, but it does make me wonder if there's a better way I'm not seeing... anyway, I'd rather have some acceptable fix than none. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-02-20 15:31 ` Daniel Jacobowitz @ 2007-02-20 16:20 ` Daniel Jacobowitz 0 siblings, 0 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-02-20 16:20 UTC (permalink / raw) To: gdb-patches; +Cc: Mark Kettenis On Tue, Feb 20, 2007 at 10:31:26AM -0500, Daniel Jacobowitz wrote: > Hmm, one small additional downside: it sends the *_FRAME constants out > into dozens of new files. I was poking at adding a new one, which > requires auditing all of the existing uses, which has now gotten much > harder. Bah, ignore this. For anyone else who wants to audit frame types: in most cases it suffices to inside frame.c search for ->type, and outside it search for get_frame_type. There are no interfaces which pass a frame type to a function, except for the two new ones in frame.c, so this finds everything interesting. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-02-20 12:39 ` Daniel Jacobowitz 2007-02-20 15:31 ` Daniel Jacobowitz @ 2007-02-22 21:28 ` Mark Kettenis 2007-02-22 21:32 ` Daniel Jacobowitz 1 sibling, 1 reply; 25+ messages in thread From: Mark Kettenis @ 2007-02-22 21:28 UTC (permalink / raw) To: drow; +Cc: gdb-patches > Date: Tue, 20 Feb 2007 07:38:52 -0500 > From: Daniel Jacobowitz <drow@false.org> > > On Wed, Jan 03, 2007 at 05:28:54PM -0500, Daniel Jacobowitz wrote: > > On Wed, Jan 03, 2007 at 11:23:08PM +0100, Mark Kettenis wrote: > > > Hmm, well, you need to commit that one first, because the > > > frame_func_unwind() change will depend on it. > > > > > > But perhaps we should give people a few days to comment... > > > > There's a call to frame_unwind_address_in_block in frame_func_unwind, > > so this is circular - got to break the loop one way or another. > > > > It will be simpler if I do both; once I've admitted it's got to be > > done, the mechanical change won't take but a few minutes. I'll > > take care of it (but not today). > > Here we go. It's not too bad, all considered. Mark, thanks again for > your help in finding a less hideous solution to this problem - I > really appreciate it. > > Does this look OK to commit? I've tested it on x86_64-linux (where, > with glibc HEAD, it fixes the remaining signal-related failures). And > I built everything listed in MAINTAINERS using gdb_mbuild.sh. Related > fixes in next message. Hi Daniel, Sorry that I didn't have the time to review this earlier. This still contains the check to catch recursion in frame_unwind_find_by_frame(), but that code really shouldn't be necessary now, so I'd prefer it if you removed it since it is quite ugly. > 2007-02-20 Daniel Jacobowitz <dan@codesourcery.com> > > * dwarf2-frame.c (dwarf2_frame_cache, dwarf2_frame_this_id) > (dwarf2_frame_sniffer): Update. > (dwarf2_signal_frame_this_id): New function. > (dwarf2_signal_frame_unwind): Use it. > (dwarf2_frame_base_sniffer): Use frame_unwind_address_in_block. > * frame-unwind.c (searching_for_unwind): New. > (clear_searching_flag): New. > (frame_unwind_find_by_frame): Assert that this function is not > entered recursively. > * frame.c (frame_func_unwind): Add this_type argument. > (get_frame_func): Update. > (frame_unwind_address_in_block): Add this_type argument and check it. > Fix a typo. > (get_frame_address_in_block): Update. > * frame.h (enum frame_type): Move higher in the file. > (frame_unwind_address_in_block, frame_func_unwind): Add enum frame_type > argument. > > * alpha-mdebug-tdep.c, alpha-tdep.c, amd64-tdep.c, amd64obsd-tdep.c, > arm-tdep.c, avr-tdep.c, cris-tdep.c, frv-tdep.c, h8300-tdep.c, > hppa-tdep.c, i386-tdep.c, i386obsd-tdep.c, ia64-tdep.c, > libunwind-frame.c, m32c-tdep.c, m32r-linux-tdep.c, m32r-tdep.c, > m68hc11-tdep.c, m68k-tdep.c, m88k-tdep.c, mips-mdebug-tdep.c, > mips-tdep.c, mn10300-tdep.c, mt-tdep.c, rs6000-tdep.c, s390-tdep.c, > score-tdep.c, sh-tdep.c, sh64-tdep.c, sparc-tdep.c, > sparc64obsd-tdep.c, spu-tdep.c, v850-tdep.c, vax-tdep.c, > xstormy16-tdep.c, xtensa-tdep.c: Update calls to > frame_func_unwind and frame_unwind_address_in_block to specify > the frame type. Use frame_unwind_address_in_block instead of > frame_pc_unwind in sniffers. > > --- > gdb/alpha-mdebug-tdep.c | 7 +++--- > gdb/alpha-tdep.c | 2 - > gdb/amd64-tdep.c | 2 - > gdb/amd64obsd-tdep.c | 4 ++- > gdb/arm-tdep.c | 6 +++-- > gdb/avr-tdep.c | 4 +-- > gdb/cris-tdep.c | 8 ++++--- > gdb/dwarf2-frame.c | 34 +++++++++++++++++++++++++------- > gdb/frame-unwind.c | 28 ++++++++++++++++++++++++-- > gdb/frame.c | 26 +++++++++++++++++------- > gdb/frame.h | 51 ++++++++++++++++++++++++++++++------------------ > gdb/frv-tdep.c | 5 ++-- > gdb/h8300-tdep.c | 2 - > gdb/hppa-tdep.c | 21 +++++++++++++------ > gdb/i386-tdep.c | 2 - > gdb/i386obsd-tdep.c | 4 ++- > gdb/ia64-tdep.c | 2 - > gdb/libunwind-frame.c | 5 +++- > gdb/m32c-tdep.c | 5 ++-- > gdb/m32r-linux-tdep.c | 2 - > gdb/m32r-tdep.c | 4 +-- > gdb/m68hc11-tdep.c | 4 +-- > gdb/m68k-tdep.c | 2 - > gdb/m88k-tdep.c | 7 +----- > gdb/mips-mdebug-tdep.c | 5 ++-- > gdb/mips-tdep.c | 12 ++++++----- > gdb/mn10300-tdep.c | 9 +++++--- > gdb/mt-tdep.c | 9 +++----- > gdb/rs6000-tdep.c | 5 ++-- > gdb/s390-tdep.c | 9 ++++---- > gdb/score-tdep.c | 3 +- > gdb/sh-tdep.c | 2 - > gdb/sh64-tdep.c | 2 - > gdb/sparc-tdep.c | 9 ++------ > gdb/sparc64obsd-tdep.c | 8 ++++--- > gdb/spu-tdep.c | 2 - > gdb/v850-tdep.c | 2 - > gdb/vax-tdep.c | 3 +- > gdb/xstormy16-tdep.c | 2 - > gdb/xtensa-tdep.c | 2 - > 40 files changed, 208 insertions(+), 113 deletions(-) > > Index: src/gdb/alpha-mdebug-tdep.c > =================================================================== > --- src.orig/gdb/alpha-mdebug-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/alpha-mdebug-tdep.c 2007-02-19 14:43:19.000000000 -0500 > @@ -246,7 +246,8 @@ alpha_mdebug_frame_this_id (struct frame > struct alpha_mdebug_unwind_cache *info > = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); > > - *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame)); > + *this_id = frame_id_build (info->vfp, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > /* Retrieve the value of REGNUM in FRAME. Don't give up! */ > @@ -311,7 +312,7 @@ static const struct frame_unwind alpha_m > const struct frame_unwind * > alpha_mdebug_frame_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > struct mdebug_extra_func_info *proc_desc; > > /* If this PC does not map to a PDR, then clearly this isn't an > @@ -368,7 +369,7 @@ static const struct frame_base alpha_mde > static const struct frame_base * > alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > struct mdebug_extra_func_info *proc_desc; > > /* If this PC does not map to a PDR, then clearly this isn't an > Index: src/gdb/alpha-tdep.c > =================================================================== > --- src.orig/gdb/alpha-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/alpha-tdep.c 2007-02-19 14:43:05.000000000 -0500 > @@ -820,7 +820,7 @@ alpha_sigtramp_frame_this_id (struct fra > code_addr = 0; > } > else > - code_addr = frame_func_unwind (next_frame); > + code_addr = frame_func_unwind (next_frame, SIGTRAMP_FRAME); > > /* The stack address is trivially read from the sigcontext. */ > stack_addr = alpha_sigtramp_register_address (info->sigcontext_addr, > Index: src/gdb/amd64-tdep.c > =================================================================== > --- src.orig/gdb/amd64-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/amd64-tdep.c 2007-02-19 14:42:58.000000000 -0500 > @@ -833,7 +833,7 @@ amd64_frame_cache (struct frame_info *ne > cache = amd64_alloc_frame_cache (); > *this_cache = cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > amd64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); > > Index: src/gdb/amd64obsd-tdep.c > =================================================================== > --- src.orig/gdb/amd64obsd-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/amd64obsd-tdep.c 2007-02-19 14:42:47.000000000 -0500 > @@ -356,7 +356,9 @@ amd64obsd_trapframe_cache(struct frame_i > cache = trad_frame_cache_zalloc (next_frame); > *this_cache = cache; > > - func = frame_func_unwind (next_frame); > + /* NORMAL_FRAME matches the type in amd64obsd_trapframe_unwind, but > + SIGTRAMP_FRAME might be more appropriate. */ > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM); > > find_pc_partial_function (func, &name, NULL, NULL); > Index: src/gdb/arm-tdep.c > =================================================================== > --- src.orig/gdb/arm-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/arm-tdep.c 2007-02-19 14:41:27.000000000 -0500 > @@ -929,7 +929,7 @@ arm_prologue_this_id (struct frame_info > *this_cache = arm_make_prologue_cache (next_frame); > cache = *this_cache; > > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* This is meant to halt the backtrace at "_start". Make sure we > don't halt it at a generic dummy frame. */ > @@ -1034,9 +1034,11 @@ struct frame_unwind arm_stub_unwind = { > static const struct frame_unwind * > arm_stub_unwind_sniffer (struct frame_info *next_frame) > { > + CORE_ADDR addr_in_block; > char dummy[4]; > > - if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL) > + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > + if (in_plt_section (addr_in_block, NULL) > || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0) > return &arm_stub_unwind; > > Index: src/gdb/avr-tdep.c > =================================================================== > --- src.orig/gdb/avr-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/avr-tdep.c 2007-02-19 14:41:19.000000000 -0500 > @@ -875,7 +875,7 @@ avr_frame_unwind_cache (struct frame_inf > info->size = 0; > info->prologue_type = AVR_PROLOGUE_NONE; > > - pc = frame_func_unwind (next_frame); > + pc = frame_func_unwind (next_frame, NORMAL_FRAME); > > if ((pc > 0) && (pc < frame_pc_unwind (next_frame))) > avr_scan_prologue (pc, info); > @@ -958,7 +958,7 @@ avr_frame_this_id (struct frame_info *ne > struct frame_id id; > > /* The FUNC is easy. */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Hopefully the prologue analysis either correctly determined the > frame's base (which is the SP from the previous frame), or set > Index: src/gdb/cris-tdep.c > =================================================================== > --- src.orig/gdb/cris-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/cris-tdep.c 2007-02-19 14:41:08.000000000 -0500 > @@ -792,9 +792,11 @@ cris_frame_unwind_cache (struct frame_in > > /* Prologue analysis does the rest... */ > if (cris_version () == 32) > - crisv32_scan_prologue (frame_func_unwind (next_frame), next_frame, info); > + crisv32_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), > + next_frame, info); > else > - cris_scan_prologue (frame_func_unwind (next_frame), next_frame, info); > + cris_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), > + next_frame, info); > > return info; > } > @@ -814,7 +816,7 @@ cris_frame_this_id (struct frame_info *n > struct frame_id id; > > /* The FUNC is easy. */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Hopefully the prologue analysis either correctly determined the > frame's base (which is the SP from the previous frame), or set > Index: src/gdb/dwarf2-frame.c > =================================================================== > --- src.orig/gdb/dwarf2-frame.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/dwarf2-frame.c 2007-02-19 14:40:11.000000000 -0500 > @@ -848,7 +848,7 @@ dwarf2_frame_cache (struct frame_info *n > frame_unwind_address_in_block does just this. It's not clear how > reliable the method is though; there is the potential for the > register state pre-call being different to that on return. */ > - fs->pc = frame_unwind_address_in_block (next_frame); > + fs->pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > > /* Find the correct FDE. */ > fde = dwarf2_frame_find_fde (&fs->pc); > @@ -1011,7 +1011,22 @@ dwarf2_frame_this_id (struct frame_info > if (cache->undefined_retaddr) > return; > > - (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (cache->cfa, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > +} > + > +static void > +dwarf2_signal_frame_this_id (struct frame_info *next_frame, void **this_cache, > + struct frame_id *this_id) > +{ > + struct dwarf2_frame_cache *cache = > + dwarf2_frame_cache (next_frame, this_cache); > + > + if (cache->undefined_retaddr) > + return; > + > + (*this_id) = frame_id_build (cache->cfa, > + frame_func_unwind (next_frame, SIGTRAMP_FRAME)); > } > > static void > @@ -1179,7 +1194,7 @@ static const struct frame_unwind dwarf2_ > static const struct frame_unwind dwarf2_signal_frame_unwind = > { > SIGTRAMP_FRAME, > - dwarf2_frame_this_id, > + dwarf2_signal_frame_this_id, > dwarf2_frame_prev_register > }; > > @@ -1188,8 +1203,12 @@ dwarf2_frame_sniffer (struct frame_info > { > /* Grab an address that is guarenteed to reside somewhere within the > function. frame_pc_unwind(), for a no-return next function, can > - end up returning something past the end of this function's body. */ > - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); > + end up returning something past the end of this function's body. > + If the frame we're sniffing for is a signal frame whose start > + address is placed on the stack by the OS, its FDE must > + extend one byte before its start address or we will miss it. */ > + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, > + NORMAL_FRAME); > struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); > if (!fde) > return NULL; > @@ -1233,8 +1252,9 @@ static const struct frame_base dwarf2_fr > const struct frame_base * > dwarf2_frame_base_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > - if (dwarf2_frame_find_fde (&pc)) > + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, > + NORMAL_FRAME); > + if (dwarf2_frame_find_fde (&block_addr)) > return &dwarf2_frame_base; > > return NULL; > Index: src/gdb/frame-unwind.c > =================================================================== > --- src.orig/gdb/frame-unwind.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/frame-unwind.c 2007-02-19 14:36:33.000000000 -0500 > @@ -28,6 +28,8 @@ > > static struct gdbarch_data *frame_unwind_data; > > +static int searching_for_unwind; > + > struct frame_unwind_table_entry > { > frame_unwind_sniffer_ftype *sniffer; > @@ -83,6 +85,12 @@ frame_unwind_prepend_unwinder (struct gd > (*table->osabi_head) = entry; > } > > +static void > +clear_searching_flag (void *arg) > +{ > + searching_for_unwind = 0; > +} > + > const struct frame_unwind * > frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache) > { > @@ -90,6 +98,15 @@ frame_unwind_find_by_frame (struct frame > struct gdbarch *gdbarch = get_frame_arch (next_frame); > struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); > struct frame_unwind_table_entry *entry; > + struct cleanup *back_to; > + > + /* Check if we were re-entered, and assert instead of running out > + of stack. This happens if the sniffer calls anything which > + requires NEXT_FRAME's unwinder. */ > + gdb_assert (!searching_for_unwind); > + searching_for_unwind = 1; > + back_to = make_cleanup (clear_searching_flag, NULL); > + > for (entry = table->list; entry != NULL; entry = entry->next) > { > if (entry->sniffer != NULL) > @@ -97,15 +114,22 @@ frame_unwind_find_by_frame (struct frame > const struct frame_unwind *desc = NULL; > desc = entry->sniffer (next_frame); > if (desc != NULL) > - return desc; > + { > + do_cleanups (back_to); > + return desc; > + } > } > if (entry->unwinder != NULL) > { > if (entry->unwinder->sniffer (entry->unwinder, next_frame, > this_cache)) > - return entry->unwinder; > + { > + do_cleanups (back_to); > + return entry->unwinder; > + } > } > } > + do_cleanups (back_to); > internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed")); > } > > Index: src/gdb/frame.c > =================================================================== > --- src.orig/gdb/frame.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/frame.c 2007-02-19 14:36:01.000000000 -0500 > @@ -471,13 +471,13 @@ frame_pc_unwind (struct frame_info *this > } > > CORE_ADDR > -frame_func_unwind (struct frame_info *fi) > +frame_func_unwind (struct frame_info *fi, enum frame_type this_type) > { > if (!fi->prev_func.p) > { > /* Make certain that this, and not the adjacent, function is > found. */ > - CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi); > + CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi, this_type); > fi->prev_func.p = 1; > fi->prev_func.addr = get_pc_function_start (addr_in_block); > if (frame_debug) > @@ -491,7 +491,7 @@ frame_func_unwind (struct frame_info *fi > CORE_ADDR > get_frame_func (struct frame_info *fi) > { > - return frame_func_unwind (fi->next); > + return frame_func_unwind (fi->next, get_frame_type (fi)); > } > > static int > @@ -1496,20 +1496,31 @@ get_frame_pc (struct frame_info *frame) > return frame_pc_unwind (frame->next); > } > > -/* Return an address of that falls within the frame's code block. */ > +/* Return an address that falls within NEXT_FRAME's caller's code > + block, assuming that the caller is a THIS_TYPE frame. */ > > CORE_ADDR > -frame_unwind_address_in_block (struct frame_info *next_frame) > +frame_unwind_address_in_block (struct frame_info *next_frame, > + enum frame_type this_type) > { > /* A draft address. */ > CORE_ADDR pc = frame_pc_unwind (next_frame); > > + /* If NEXT_FRAME was called by a signal frame or dummy frame, then > + we shold not adjust the unwound PC. These frames may not call > + their next frame in the normal way; the operating system or GDB > + may have pushed their resume address manually onto the stack, so > + it may be the very first instruction. Even if the resume address > + was not manually pushed, they expect to be returned to. */ > + if (this_type != NORMAL_FRAME) > + return pc; > + > /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel), > and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS > frame's PC ends up pointing at the instruction fallowing the > "call". Adjust that PC value so that it falls on the call > instruction (which, hopefully, falls within THIS frame's code > - block. So far it's proved to be a very good approximation. See > + block). So far it's proved to be a very good approximation. See > get_frame_type() for why ->type can't be used. */ > if (next_frame->level >= 0 > && get_frame_type (next_frame) == NORMAL_FRAME) > @@ -1520,7 +1531,8 @@ frame_unwind_address_in_block (struct fr > CORE_ADDR > get_frame_address_in_block (struct frame_info *this_frame) > { > - return frame_unwind_address_in_block (this_frame->next); > + return frame_unwind_address_in_block (this_frame->next, > + get_frame_type (this_frame)); > } > > static int > Index: src/gdb/frame.h > =================================================================== > --- src.orig/gdb/frame.h 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/frame.h 2007-02-19 14:34:33.000000000 -0500 > @@ -184,6 +184,25 @@ extern int frame_id_inner (struct frame_ > extern void fprint_frame_id (struct ui_file *file, struct frame_id id); > > > +/* Frame types. Some are real, some are signal trampolines, and some > + are completely artificial (dummy). */ > + > +enum frame_type > +{ > + /* A true stack frame, created by the target program during normal > + execution. */ > + NORMAL_FRAME, > + /* A fake frame, created by GDB when performing an inferior function > + call. */ > + DUMMY_FRAME, > + /* In a signal handler, various OSs handle this in various ways. > + The main thing is that the frame may be far from normal. */ > + SIGTRAMP_FRAME, > + /* Sentinel or registers frame. This frame obtains register values > + direct from the inferior's registers. */ > + SENTINEL_FRAME > +}; > + > /* For every stopped thread, GDB tracks two frames: current and > selected. Current frame is the inner most frame of the selected > thread. Selected frame is the one being examined by the the GDB > @@ -265,7 +284,13 @@ extern CORE_ADDR get_frame_pc (struct fr > the frame's block. */ > > extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); > -extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); > + > +/* Similar to get_frame_address_in_block, find an address in the > + block which logically called NEXT_FRAME, assuming it is a THIS_TYPE > + frame. */ > + > +extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, > + enum frame_type this_type); > > /* The frame's inner-most bound. AKA the stack-pointer. Confusingly > known as top-of-stack. */ > @@ -277,9 +302,13 @@ extern CORE_ADDR frame_sp_unwind (struct > /* Following on from the `resume' address. Return the entry point > address of the function containing that resume address, or zero if > that function isn't known. */ > -extern CORE_ADDR frame_func_unwind (struct frame_info *fi); > extern CORE_ADDR get_frame_func (struct frame_info *fi); > > +/* Similar to get_frame_func, find the start of the function which > + logically called NEXT_FRAME, assuming it is a THIS_TYPE frame. */ > +extern CORE_ADDR frame_func_unwind (struct frame_info *next_frame, > + enum frame_type this_type); > + > /* Closely related to the resume address, various symbol table > attributes that are determined by the PC. Note that for a normal > frame, the PC refers to the resume address after the return, and > @@ -375,24 +404,8 @@ extern CORE_ADDR get_frame_args_address > for an invalid frame). */ > extern int frame_relative_level (struct frame_info *fi); > > -/* Return the frame's type. Some are real, some are signal > - trampolines, and some are completely artificial (dummy). */ > +/* Return the frame's type. */ > > -enum frame_type > -{ > - /* A true stack frame, created by the target program during normal > - execution. */ > - NORMAL_FRAME, > - /* A fake frame, created by GDB when performing an inferior function > - call. */ > - DUMMY_FRAME, > - /* In a signal handler, various OSs handle this in various ways. > - The main thing is that the frame may be far from normal. */ > - SIGTRAMP_FRAME, > - /* Sentinel or registers frame. This frame obtains register values > - direct from the inferior's registers. */ > - SENTINEL_FRAME > -}; > extern enum frame_type get_frame_type (struct frame_info *); > > /* For frames where we can not unwind further, describe why. */ > Index: src/gdb/frv-tdep.c > =================================================================== > --- src.orig/gdb/frv-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/frv-tdep.c 2007-02-19 16:39:55.000000000 -0500 > @@ -1016,7 +1016,8 @@ frv_frame_unwind_cache (struct frame_inf > info->saved_regs = trad_frame_alloc_saved_regs (next_frame); > > /* Prologue analysis does the rest... */ > - frv_analyze_prologue (frame_func_unwind (next_frame), next_frame, info); > + frv_analyze_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), > + next_frame, info); > > return info; > } > @@ -1346,7 +1347,7 @@ frv_frame_this_id (struct frame_info *ne > struct frame_id id; > > /* The FUNC is easy. */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Check if the stack is empty. */ > msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); > Index: src/gdb/h8300-tdep.c > =================================================================== > --- src.orig/gdb/h8300-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/h8300-tdep.c 2007-02-19 14:29:32.000000000 -0500 > @@ -447,7 +447,7 @@ h8300_frame_cache (struct frame_info *ne > > cache->saved_regs[E_PC_REGNUM] = -BINWORD; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > current_pc = frame_pc_unwind (next_frame); > if (cache->pc != 0) > h8300_analyze_prologue (cache->pc, current_pc, cache); > Index: src/gdb/hppa-tdep.c > =================================================================== > --- src.orig/gdb/hppa-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/hppa-tdep.c 2007-02-19 14:29:26.000000000 -0500 > @@ -1787,9 +1787,14 @@ hppa_skip_prologue (CORE_ADDR pc) > static struct unwind_table_entry * > hppa_find_unwind_entry_in_block (struct frame_info *f) > { > - CORE_ADDR pc; > + CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME); > > - pc = frame_unwind_address_in_block (f); > + /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the > + result of frame_unwind_address_in_block implies a problem. > + The bits should have been removed earlier, before the return > + value of frame_pc_unwind. That might be happening already; > + if it isn't, it should be fixed. Then this call can be > + removed. */ > pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc); > return find_unwind_entry (pc); > } > @@ -1899,7 +1904,7 @@ hppa_frame_cache (struct frame_info *nex > if ((u->Region_description & 0x2) == 0) > start_pc = u->region_start; > else > - start_pc = frame_func_unwind (next_frame); > + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); > > prologue_end = skip_prologue_hard_way (start_pc, 0); > end_pc = frame_pc_unwind (next_frame); > @@ -2267,7 +2272,7 @@ hppa_fallback_frame_cache (struct frame_ > (*this_cache) = cache; > cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); > > - start_pc = frame_func_unwind (next_frame); > + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (start_pc) > { > CORE_ADDR cur_pc = frame_pc_unwind (next_frame); > @@ -2326,7 +2331,8 @@ hppa_fallback_frame_this_id (struct fram > { > struct hppa_frame_cache *info = > hppa_fallback_frame_cache (next_frame, this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > @@ -2409,7 +2415,8 @@ hppa_stub_frame_this_id (struct frame_in > = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache); > > if (info) > - *this_id = frame_id_build (info->base, frame_func_unwind (next_frame)); > + *this_id = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > else > *this_id = null_frame_id; > } > @@ -2441,7 +2448,7 @@ static const struct frame_unwind hppa_st > static const struct frame_unwind * > hppa_stub_unwind_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > struct gdbarch *gdbarch = get_frame_arch (next_frame); > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > > Index: src/gdb/i386-tdep.c > =================================================================== > --- src.orig/gdb/i386-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/i386-tdep.c 2007-02-19 14:28:52.000000000 -0500 > @@ -949,7 +949,7 @@ i386_frame_cache (struct frame_info *nex > /* For normal frames, %eip is stored at 4(%ebp). */ > cache->saved_regs[I386_EIP_REGNUM] = 4; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); > > Index: src/gdb/i386obsd-tdep.c > =================================================================== > --- src.orig/gdb/i386obsd-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/i386obsd-tdep.c 2007-02-19 14:28:41.000000000 -0500 > @@ -353,7 +353,9 @@ i386obsd_trapframe_cache(struct frame_in > cache = trad_frame_cache_zalloc (next_frame); > *this_cache = cache; > > - func = frame_func_unwind (next_frame); > + /* NORMAL_FRAME matches the type in i386obsd_trapframe_unwind, but > + SIGTRAMP_FRAME might be more appropriate. */ > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM); > > find_pc_partial_function (func, &name, NULL, NULL); > Index: src/gdb/ia64-tdep.c > =================================================================== > --- src.orig/gdb/ia64-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/ia64-tdep.c 2007-02-19 14:27:10.000000000 -0500 > @@ -1555,7 +1555,7 @@ ia64_frame_cache (struct frame_info *nex > > cache->cfm = cfm; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > > if (cache->pc != 0) > examine_prologue (cache->pc, frame_pc_unwind (next_frame), next_frame, cache); > Index: src/gdb/libunwind-frame.c > =================================================================== > --- src.orig/gdb/libunwind-frame.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/libunwind-frame.c 2007-02-19 14:26:49.000000000 -0500 > @@ -141,7 +141,10 @@ libunwind_frame_cache (struct frame_info > /* Allocate a new cache. */ > cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); > > - cache->func_addr = frame_func_unwind (next_frame); > + /* We can assume we are unwinding a normal frame. Even if this is > + for a signal trampoline, ia64 signal "trampolines" use a normal > + subroutine call to start the signal handler. */ > + cache->func_addr = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->func_addr == 0 > && frame_relative_level (next_frame) > 0 > && get_frame_type (next_frame) != SIGTRAMP_FRAME) > Index: src/gdb/m32c-tdep.c > =================================================================== > --- src.orig/gdb/m32c-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/m32c-tdep.c 2007-02-19 13:59:05.000000000 -0500 > @@ -1836,7 +1836,7 @@ m32c_analyze_frame_prologue (struct fram > { > if (! *this_prologue_cache) > { > - CORE_ADDR func_start = frame_func_unwind (next_frame); > + CORE_ADDR func_start = frame_func_unwind (next_frame, NORMAL_FRAME); > CORE_ADDR stop_addr = frame_pc_unwind (next_frame); > > /* If we couldn't find any function containing the PC, then > @@ -1900,7 +1900,8 @@ m32c_this_id (struct frame_info *next_fr > CORE_ADDR base = m32c_frame_base (next_frame, this_prologue_cache); > > if (base) > - *this_id = frame_id_build (base, frame_func_unwind (next_frame)); > + *this_id = frame_id_build (base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > /* Otherwise, leave it unset, and that will terminate the backtrace. */ > } > > Index: src/gdb/m32r-linux-tdep.c > =================================================================== > --- src.orig/gdb/m32r-linux-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/m32r-linux-tdep.c 2007-02-19 14:03:30.000000000 -0500 > @@ -250,7 +250,7 @@ m32r_linux_sigtramp_frame_cache (struct > if (addr) > sigcontext_addr += 128; > else > - addr = frame_func_unwind (next_frame); > + addr = frame_func_unwind (next_frame, NORMAL_FRAME); > } > cache->pc = addr; > > Index: src/gdb/m32r-tdep.c > =================================================================== > --- src.orig/gdb/m32r-tdep.c 2007-02-19 13:57:27.000000000 -0500 > +++ src/gdb/m32r-tdep.c 2007-02-19 14:03:17.000000000 -0500 > @@ -536,7 +536,7 @@ m32r_frame_unwind_cache (struct frame_in > info->uses_frame = 0; > > scan_limit = frame_pc_unwind (next_frame); > - for (pc = frame_func_unwind (next_frame); > + for (pc = frame_func_unwind (next_frame, NORMAL_FRAME); > pc > 0 && pc < scan_limit; pc += 2) > { > if ((pc & 2) == 0) > @@ -835,7 +835,7 @@ m32r_frame_this_id (struct frame_info *n > struct frame_id id; > > /* The FUNC is easy. */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Check if the stack is empty. */ > msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); > Index: src/gdb/m68hc11-tdep.c > =================================================================== > --- src.orig/gdb/m68hc11-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/m68hc11-tdep.c 2007-02-19 14:03:01.000000000 -0500 > @@ -798,7 +798,7 @@ m68hc11_frame_unwind_cache (struct frame > (*this_prologue_cache) = info; > info->saved_regs = trad_frame_alloc_saved_regs (next_frame); > > - info->pc = frame_func_unwind (next_frame); > + info->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > > info->size = 0; > info->return_kind = m68hc11_get_return_insn (info->pc); > @@ -889,7 +889,7 @@ m68hc11_frame_this_id (struct frame_info > struct frame_id id; > > /* The FUNC is easy. */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Hopefully the prologue analysis either correctly determined the > frame's base (which is the SP from the previous frame), or set > Index: src/gdb/m68k-tdep.c > =================================================================== > --- src.orig/gdb/m68k-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/m68k-tdep.c 2007-02-19 14:02:53.000000000 -0500 > @@ -819,7 +819,7 @@ m68k_frame_cache (struct frame_info *nex > /* For normal frames, %pc is stored at 4(%fp). */ > cache->saved_regs[M68K_PC_REGNUM] = 4; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > m68k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); > > Index: src/gdb/m88k-tdep.c > =================================================================== > --- src.orig/gdb/m88k-tdep.c 2007-01-29 12:37:47.000000000 -0500 > +++ src/gdb/m88k-tdep.c 2007-02-19 14:02:45.000000000 -0500 > @@ -659,12 +659,9 @@ m88k_frame_cache (struct frame_info *nex > cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); > cache->fp_offset = -1; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > - { > - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); > - m88k_analyze_prologue (cache->pc, addr_in_block, cache); > - } > + m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); > > /* Calculate the stack pointer used in the prologue. */ > if (cache->fp_offset != -1) > Index: src/gdb/mips-mdebug-tdep.c > =================================================================== > --- src.orig/gdb/mips-mdebug-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/mips-mdebug-tdep.c 2007-02-19 14:02:39.000000000 -0500 > @@ -386,7 +386,8 @@ mips_mdebug_frame_this_id (struct frame_ > { > struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, > this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > @@ -412,7 +413,7 @@ static const struct frame_unwind mips_md > static const struct frame_unwind * > mips_mdebug_frame_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > CORE_ADDR startaddr = 0; > struct mdebug_extra_func_info *proc_desc; > int kernel_trap; > Index: src/gdb/mips-tdep.c > =================================================================== > --- src.orig/gdb/mips-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/mips-tdep.c 2007-02-19 16:44:38.000000000 -0500 > @@ -1666,7 +1666,8 @@ mips_insn16_frame_this_id (struct frame_ > { > struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame, > this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > @@ -1692,7 +1693,7 @@ static const struct frame_unwind mips_in > static const struct frame_unwind * > mips_insn16_frame_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > if (mips_pc_is_mips16 (pc)) > return &mips_insn16_frame_unwind; > return NULL; > @@ -1986,7 +1987,8 @@ mips_insn32_frame_this_id (struct frame_ > { > struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame, > this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > @@ -2012,7 +2014,7 @@ static const struct frame_unwind mips_in > static const struct frame_unwind * > mips_insn32_frame_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > if (! mips_pc_is_mips16 (pc)) > return &mips_insn32_frame_unwind; > return NULL; > @@ -2107,7 +2109,7 @@ static const struct frame_unwind * > mips_stub_frame_sniffer (struct frame_info *next_frame) > { > struct obj_section *s; > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > > if (in_plt_section (pc, NULL)) > return &mips_stub_frame_unwind; > Index: src/gdb/mn10300-tdep.c > =================================================================== > --- src.orig/gdb/mn10300-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/mn10300-tdep.c 2007-02-19 14:44:23.000000000 -0500 > @@ -850,9 +850,12 @@ mn10300_frame_unwind_cache (struct frame > frame_id_build (trad_frame_get_this_base (cache), > start)); > else > - trad_frame_set_id (cache, > - frame_id_build (trad_frame_get_this_base (cache), > - frame_func_unwind (next_frame))); > + { > + start = frame_func_unwind (next_frame, NORMAL_FRAME); > + trad_frame_set_id (cache, > + frame_id_build (trad_frame_get_this_base (cache), > + start)); > + } > > (*this_prologue_cache) = cache; > return cache; > Index: src/gdb/mt-tdep.c > =================================================================== > --- src.orig/gdb/mt-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/mt-tdep.c 2007-02-19 14:00:49.000000000 -0500 > @@ -891,7 +891,7 @@ mt_frame_unwind_cache (struct frame_info > frame_unwind_unsigned_register (next_frame, MT_SP_REGNUM, &sp); > frame_unwind_unsigned_register (next_frame, MT_FP_REGNUM, &fp); > > - start_addr = frame_func_unwind (next_frame); > + start_addr = frame_func_unwind (next_frame, NORMAL_FRAME); > > /* Return early if GDB couldn't find the function. */ > if (start_addr == 0) > @@ -1041,10 +1041,9 @@ mt_frame_this_id (struct frame_info *nex > mt_frame_unwind_cache (next_frame, this_prologue_cache); > > if (!(info == NULL || info->prev_sp == 0)) > - { > - (*this_id) = frame_id_build (info->prev_sp, > - frame_func_unwind (next_frame)); > - } > + (*this_id) = frame_id_build (info->prev_sp, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > + > return; > } > > Index: src/gdb/rs6000-tdep.c > =================================================================== > --- src.orig/gdb/rs6000-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/rs6000-tdep.c 2007-02-19 14:00:20.000000000 -0500 > @@ -2970,7 +2970,7 @@ rs6000_frame_cache (struct frame_info *n > (*this_cache) = cache; > cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); > > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > pc = frame_pc_unwind (next_frame); > skip_prologue (func, pc, &fdata); > > @@ -3122,7 +3122,8 @@ rs6000_frame_this_id (struct frame_info > { > struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame, > this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > Index: src/gdb/s390-tdep.c > =================================================================== > --- src.orig/gdb/s390-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/s390-tdep.c 2007-02-19 13:59:56.000000000 -0500 > @@ -1232,7 +1232,7 @@ s390_prologue_frame_unwind_cache (struct > bother searching for it -- with modern compilers this would be mostly > pointless anyway. Trust that we'll either have valid DWARF-2 CFI data > or else a valid backchain ... */ > - func = frame_func_unwind (next_frame); > + func = frame_func_unwind (next_frame, NORMAL_FRAME); > if (!func) > return 0; > > @@ -1556,14 +1556,15 @@ static const struct frame_unwind s390_st > static const struct frame_unwind * > s390_stub_frame_sniffer (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_pc_unwind (next_frame); > + CORE_ADDR addr_in_block; > bfd_byte insn[S390_MAX_INSTR_SIZE]; > > /* If the current PC points to non-readable memory, we assume we > have trapped due to an invalid function pointer call. We handle > the non-existing current function like a PLT stub. */ > - if (in_plt_section (pc, NULL) > - || s390_readinstruction (insn, pc) < 0) > + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > + if (in_plt_section (addr_in_block, NULL) > + || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0) > return &s390_stub_frame_unwind; > return NULL; > } > Index: src/gdb/score-tdep.c > =================================================================== > --- src.orig/gdb/score-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/score-tdep.c 2007-02-19 14:00:34.000000000 -0500 > @@ -801,7 +801,8 @@ score_prologue_this_id (struct frame_inf > { > struct score_frame_cache *info = score_make_prologue_cache (next_frame, > this_cache); > - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (info->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > Index: src/gdb/sh-tdep.c > =================================================================== > --- src.orig/gdb/sh-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/sh-tdep.c 2007-02-19 13:59:47.000000000 -0500 > @@ -2215,7 +2215,7 @@ sh_frame_cache (struct frame_info *next_ > if (cache->base == 0) > return cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > current_pc = frame_pc_unwind (next_frame); > if (cache->pc != 0) > sh_analyze_prologue (cache->pc, current_pc, cache); > Index: src/gdb/sh64-tdep.c > =================================================================== > --- src.orig/gdb/sh64-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/sh64-tdep.c 2007-02-19 13:59:42.000000000 -0500 > @@ -2254,7 +2254,7 @@ sh64_frame_cache (struct frame_info *nex > if (cache->base == 0) > return cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > sh64_analyze_prologue (current_gdbarch, cache, cache->pc, current_pc); > > Index: src/gdb/sparc-tdep.c > =================================================================== > --- src.orig/gdb/sparc-tdep.c 2007-01-29 12:37:48.000000000 -0500 > +++ src/gdb/sparc-tdep.c 2007-02-19 13:59:36.000000000 -0500 > @@ -699,12 +699,9 @@ sparc_frame_cache (struct frame_info *ne > cache = sparc_alloc_frame_cache (); > *this_cache = cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > if (cache->pc != 0) > - { > - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); > - sparc_analyze_prologue (cache->pc, addr_in_block, cache); > - } > + sparc_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); > > if (cache->frameless_p) > { > @@ -1054,7 +1051,7 @@ sparc32_stabs_argument_has_addr (struct > static int > sparc32_dwarf2_struct_return_p (struct frame_info *next_frame) > { > - CORE_ADDR pc = frame_unwind_address_in_block (next_frame); > + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > struct symbol *sym = find_pc_function (pc); > > if (sym) > Index: src/gdb/sparc64obsd-tdep.c > =================================================================== > --- src.orig/gdb/sparc64obsd-tdep.c 2007-02-19 13:55:34.000000000 -0500 > +++ src/gdb/sparc64obsd-tdep.c 2007-02-19 13:55:54.000000000 -0500 > @@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru > /* Kernel debugging support. */ > > static struct sparc_frame_cache * > -sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) > +sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache) > { > struct sparc_frame_cache *cache; > CORE_ADDR sp, trapframe_addr; > @@ -267,15 +267,17 @@ static const struct frame_unwind sparc64 > static const struct frame_unwind * > sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) > { > + CORE_ADDR pc; > ULONGEST pstate; > char *name; > > /* Check whether we are in privileged mode, and bail out if we're not. */ > - pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM); > + pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); > if ((pstate & SPARC64_PSTATE_PRIV) == 0) > return NULL; > > - find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); > + pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); > + find_pc_partial_function (pc, &name, NULL, NULL); > if (name && strcmp (name, "Lslowtrap_reenter") == 0) > return &sparc64obsd_trapframe_unwind; > > Index: src/gdb/spu-tdep.c > =================================================================== > --- src.orig/gdb/spu-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/spu-tdep.c 2007-02-19 13:58:13.000000000 -0500 > @@ -587,7 +587,7 @@ spu_frame_unwind_cache (struct frame_inf > info->local_base = 0; > > /* Find the start of the current function, and analyze its prologue. */ > - info->func = frame_func_unwind (next_frame); > + info->func = frame_func_unwind (next_frame, NORMAL_FRAME); > if (info->func == 0) > { > /* Fall back to using the current PC as frame ID. */ > Index: src/gdb/v850-tdep.c > =================================================================== > --- src.orig/gdb/v850-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/v850-tdep.c 2007-02-19 13:59:27.000000000 -0500 > @@ -856,7 +856,7 @@ v850_frame_cache (struct frame_info *nex > if (cache->base == 0) > return cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > current_pc = frame_pc_unwind (next_frame); > if (cache->pc != 0) > v850_analyze_prologue (cache->pc, current_pc, cache); > Index: src/gdb/vax-tdep.c > =================================================================== > --- src.orig/gdb/vax-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/vax-tdep.c 2007-02-19 13:59:20.000000000 -0500 > @@ -384,7 +384,8 @@ vax_frame_this_id (struct frame_info *ne > if (cache->base == 0) > return; > > - (*this_id) = frame_id_build (cache->base, frame_func_unwind (next_frame)); > + (*this_id) = frame_id_build (cache->base, > + frame_func_unwind (next_frame, NORMAL_FRAME)); > } > > static void > Index: src/gdb/xstormy16-tdep.c > =================================================================== > --- src.orig/gdb/xstormy16-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/xstormy16-tdep.c 2007-02-19 13:59:13.000000000 -0500 > @@ -655,7 +655,7 @@ xstormy16_frame_cache (struct frame_info > if (cache->base == 0) > return cache; > > - cache->pc = frame_func_unwind (next_frame); > + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); > current_pc = frame_pc_unwind (next_frame); > if (cache->pc) > xstormy16_analyze_prologue (cache->pc, current_pc, cache, next_frame); > Index: src/gdb/xtensa-tdep.c > =================================================================== > --- src.orig/gdb/xtensa-tdep.c 2007-02-19 13:57:28.000000000 -0500 > +++ src/gdb/xtensa-tdep.c 2007-02-19 13:58:06.000000000 -0500 > @@ -924,7 +924,7 @@ xtensa_frame_cache (struct frame_info *n > cache->ws = ws & ~(1 << wb); > } > > - cache->pc = ((frame_func_unwind (next_frame) & 0xc0000000) > + cache->pc = ((frame_func_unwind (next_frame, NORMAL_FRAME) & 0xc0000000) > | (ra & 0x3fffffff)); > cache->ps = (ps & ~PS_CALLINC_MASK) | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT); > > ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-02-22 21:28 ` Mark Kettenis @ 2007-02-22 21:32 ` Daniel Jacobowitz 2007-02-27 20:18 ` Daniel Jacobowitz 0 siblings, 1 reply; 25+ messages in thread From: Daniel Jacobowitz @ 2007-02-22 21:32 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Thu, Feb 22, 2007 at 10:27:51PM +0100, Mark Kettenis wrote: > Hi Daniel, > > Sorry that I didn't have the time to review this earlier. This still > contains the check to catch recursion in frame_unwind_find_by_frame(), > but that code really shouldn't be necessary now, so I'd prefer it if > you removed it since it is quite ugly. Fine by me - I'll just discard the frame-unwind.c part when I commit it then. It was only useful during testing but I don't imagine it will catch much afterwards. Thanks. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [patch RFC] Re: Notes on a frame_unwind_address_in_block problem 2007-02-22 21:32 ` Daniel Jacobowitz @ 2007-02-27 20:18 ` Daniel Jacobowitz 0 siblings, 0 replies; 25+ messages in thread From: Daniel Jacobowitz @ 2007-02-27 20:18 UTC (permalink / raw) To: gdb-patches On Thu, Feb 22, 2007 at 04:32:43PM -0500, Daniel Jacobowitz wrote: > On Thu, Feb 22, 2007 at 10:27:51PM +0100, Mark Kettenis wrote: > > Hi Daniel, > > > > Sorry that I didn't have the time to review this earlier. This still > > contains the check to catch recursion in frame_unwind_find_by_frame(), > > but that code really shouldn't be necessary now, so I'd prefer it if > > you removed it since it is quite ugly. > > Fine by me - I'll just discard the frame-unwind.c part when I commit > it then. It was only useful during testing but I don't imagine it > will catch much afterwards. Thanks. Here is the final version, which I have checked in. Testsuite results on Debian/unstable x86_64-pc-linux-gnu plus a relatively current glibc snapshot are improving: FAIL: gdb.ada/arrayidx.exp: print e_one_two_three, indexes off FAIL: gdb.ada/arrayidx.exp: print r_two_three, indexes off FAIL: gdb.ada/arrayidx.exp: print u_one_two_three, indexes off FAIL: gdb.ada/arrayidx.exp: print p_one_two_three, indexes off FAIL: gdb.ada/arrayidx.exp: print e_one_two_three FAIL: gdb.ada/arrayidx.exp: print r_two_three FAIL: gdb.ada/arrayidx.exp: print u_one_two_three FAIL: gdb.ada/arrayidx.exp: print p_one_two_three FAIL: gdb.ada/packed_array.exp: print var FAIL: gdb.base/corefile.exp: accessing mmapped data in core file (mapping address not found in core file) FAIL: gdb.cp/annota3.exp: annotate-quit (pattern 1) FAIL: gdb.cp/inherit.exp: ptype tagless struct FAIL: gdb.cp/inherit.exp: print type of anonymous union // unrecognized line type 1: class_with_anon_union::._0; XPASS: gdb.mi/mi-var-display.exp: eval variable anone XPASS: gdb.mi/mi2-var-display.exp: eval variable anone FAIL: gdb.threads/staticthreads.exp: running to main in runto FAIL: gdb.threads/staticthreads.exp: Continue to main's call of sem_post FAIL: gdb.threads/staticthreads.exp: handle SIG32 helps FAIL: gdb.threads/watchthreads.exp: threaded watch loop FAIL: gdb.threads/watchthreads.exp: first watchpoint on args[1] hit FAIL: gdb.threads/watchthreads.exp: watchpoint on args[0] hit in thread FAIL: gdb.threads/watchthreads.exp: watchpoint on args[1] hit in thread FAIL: gdb.threads/watchthreads.exp: combination of threaded watchpoints = 30 I'm going to keep working on this. -- Daniel Jacobowitz CodeSourcery 2007-02-27 Daniel Jacobowitz <dan@codesourcery.com> * dwarf2-frame.c (dwarf2_frame_cache, dwarf2_frame_this_id) (dwarf2_frame_sniffer): Update. (dwarf2_signal_frame_this_id): New function. (dwarf2_signal_frame_unwind): Use it. (dwarf2_frame_base_sniffer): Use frame_unwind_address_in_block. * frame.c (frame_func_unwind): Add this_type argument. (get_frame_func): Update. (frame_unwind_address_in_block): Add this_type argument and check it. Fix a typo. (get_frame_address_in_block): Update. * frame.h (enum frame_type): Move higher in the file. (frame_unwind_address_in_block, frame_func_unwind): Add enum frame_type argument. * alpha-mdebug-tdep.c, alpha-tdep.c, amd64-tdep.c, amd64obsd-tdep.c, arm-tdep.c, avr-tdep.c, cris-tdep.c, frv-tdep.c, h8300-tdep.c, hppa-tdep.c, i386-tdep.c, i386obsd-tdep.c, ia64-tdep.c, libunwind-frame.c, m32c-tdep.c, m32r-linux-tdep.c, m32r-tdep.c, m68hc11-tdep.c, m68k-tdep.c, m88k-tdep.c, mips-mdebug-tdep.c, mips-tdep.c, mn10300-tdep.c, mt-tdep.c, rs6000-tdep.c, s390-tdep.c, score-tdep.c, sh-tdep.c, sh64-tdep.c, sparc-tdep.c, sparc64obsd-tdep.c, spu-tdep.c, v850-tdep.c, vax-tdep.c, xstormy16-tdep.c, xtensa-tdep.c: Update calls to frame_func_unwind and frame_unwind_address_in_block to specify the frame type. Use frame_unwind_address_in_block instead of frame_pc_unwind in sniffers. 2007-02-27 Daniel Jacobowitz <dan@codesourcery.com> * gdb.arch/i386-signal.c, gdb.arch/i386-signal.exp: New files. Index: alpha-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-mdebug-tdep.c,v retrieving revision 1.13 diff -u -p -r1.13 alpha-mdebug-tdep.c --- alpha-mdebug-tdep.c 9 Jan 2007 20:19:15 -0000 1.13 +++ alpha-mdebug-tdep.c 27 Feb 2007 20:14:39 -0000 @@ -246,7 +246,8 @@ alpha_mdebug_frame_this_id (struct frame struct alpha_mdebug_unwind_cache *info = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); - *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame)); + *this_id = frame_id_build (info->vfp, + frame_func_unwind (next_frame, NORMAL_FRAME)); } /* Retrieve the value of REGNUM in FRAME. Don't give up! */ @@ -311,7 +312,7 @@ static const struct frame_unwind alpha_m const struct frame_unwind * alpha_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an @@ -368,7 +369,7 @@ static const struct frame_base alpha_mde static const struct frame_base * alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct mdebug_extra_func_info *proc_desc; /* If this PC does not map to a PDR, then clearly this isn't an Index: alpha-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-tdep.c,v retrieving revision 1.161 diff -u -p -r1.161 alpha-tdep.c --- alpha-tdep.c 29 Jan 2007 17:31:05 -0000 1.161 +++ alpha-tdep.c 27 Feb 2007 20:14:39 -0000 @@ -820,7 +820,7 @@ alpha_sigtramp_frame_this_id (struct fra code_addr = 0; } else - code_addr = frame_func_unwind (next_frame); + code_addr = frame_func_unwind (next_frame, SIGTRAMP_FRAME); /* The stack address is trivially read from the sigcontext. */ stack_addr = alpha_sigtramp_register_address (info->sigcontext_addr, Index: amd64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/amd64-tdep.c,v retrieving revision 1.33 diff -u -p -r1.33 amd64-tdep.c --- amd64-tdep.c 9 Jan 2007 17:58:49 -0000 1.33 +++ amd64-tdep.c 27 Feb 2007 20:14:39 -0000 @@ -833,7 +833,7 @@ amd64_frame_cache (struct frame_info *ne cache = amd64_alloc_frame_cache (); *this_cache = cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) amd64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: amd64obsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/amd64obsd-tdep.c,v retrieving revision 1.23 diff -u -p -r1.23 amd64obsd-tdep.c --- amd64obsd-tdep.c 9 Jan 2007 17:58:49 -0000 1.23 +++ amd64obsd-tdep.c 27 Feb 2007 20:14:39 -0000 @@ -356,7 +356,9 @@ amd64obsd_trapframe_cache(struct frame_i cache = trad_frame_cache_zalloc (next_frame); *this_cache = cache; - func = frame_func_unwind (next_frame); + /* NORMAL_FRAME matches the type in amd64obsd_trapframe_unwind, but + SIGTRAMP_FRAME might be more appropriate. */ + func = frame_func_unwind (next_frame, NORMAL_FRAME); sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.223 diff -u -p -r1.223 arm-tdep.c --- arm-tdep.c 26 Feb 2007 19:18:52 -0000 1.223 +++ arm-tdep.c 27 Feb 2007 20:14:40 -0000 @@ -931,7 +931,7 @@ arm_prologue_this_id (struct frame_info *this_cache = arm_make_prologue_cache (next_frame); cache = *this_cache; - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* This is meant to halt the backtrace at "_start". Make sure we don't halt it at a generic dummy frame. */ @@ -1036,9 +1036,11 @@ struct frame_unwind arm_stub_unwind = { static const struct frame_unwind * arm_stub_unwind_sniffer (struct frame_info *next_frame) { + CORE_ADDR addr_in_block; char dummy[4]; - if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0) return &arm_stub_unwind; Index: avr-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/avr-tdep.c,v retrieving revision 1.93 diff -u -p -r1.93 avr-tdep.c --- avr-tdep.c 16 Feb 2007 21:49:59 -0000 1.93 +++ avr-tdep.c 27 Feb 2007 20:14:40 -0000 @@ -875,7 +875,7 @@ avr_frame_unwind_cache (struct frame_inf info->size = 0; info->prologue_type = AVR_PROLOGUE_NONE; - pc = frame_func_unwind (next_frame); + pc = frame_func_unwind (next_frame, NORMAL_FRAME); if ((pc > 0) && (pc < frame_pc_unwind (next_frame))) avr_scan_prologue (pc, info); @@ -958,7 +958,7 @@ avr_frame_this_id (struct frame_info *ne struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: cris-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/cris-tdep.c,v retrieving revision 1.137 diff -u -p -r1.137 cris-tdep.c --- cris-tdep.c 9 Jan 2007 17:58:50 -0000 1.137 +++ cris-tdep.c 27 Feb 2007 20:14:40 -0000 @@ -792,9 +792,11 @@ cris_frame_unwind_cache (struct frame_in /* Prologue analysis does the rest... */ if (cris_version () == 32) - crisv32_scan_prologue (frame_func_unwind (next_frame), next_frame, info); + crisv32_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); else - cris_scan_prologue (frame_func_unwind (next_frame), next_frame, info); + cris_scan_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); return info; } @@ -814,7 +816,7 @@ cris_frame_this_id (struct frame_info *n struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.67 diff -u -p -r1.67 dwarf2-frame.c --- dwarf2-frame.c 21 Jan 2007 22:42:09 -0000 1.67 +++ dwarf2-frame.c 27 Feb 2007 20:14:40 -0000 @@ -848,7 +848,7 @@ dwarf2_frame_cache (struct frame_info *n frame_unwind_address_in_block does just this. It's not clear how reliable the method is though; there is the potential for the register state pre-call being different to that on return. */ - fs->pc = frame_unwind_address_in_block (next_frame); + fs->pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); /* Find the correct FDE. */ fde = dwarf2_frame_find_fde (&fs->pc); @@ -1011,7 +1011,22 @@ dwarf2_frame_this_id (struct frame_info if (cache->undefined_retaddr) return; - (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (cache->cfa, + frame_func_unwind (next_frame, NORMAL_FRAME)); +} + +static void +dwarf2_signal_frame_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct dwarf2_frame_cache *cache = + dwarf2_frame_cache (next_frame, this_cache); + + if (cache->undefined_retaddr) + return; + + (*this_id) = frame_id_build (cache->cfa, + frame_func_unwind (next_frame, SIGTRAMP_FRAME)); } static void @@ -1179,7 +1194,7 @@ static const struct frame_unwind dwarf2_ static const struct frame_unwind dwarf2_signal_frame_unwind = { SIGTRAMP_FRAME, - dwarf2_frame_this_id, + dwarf2_signal_frame_this_id, dwarf2_frame_prev_register }; @@ -1188,8 +1203,12 @@ dwarf2_frame_sniffer (struct frame_info { /* Grab an address that is guarenteed to reside somewhere within the function. frame_pc_unwind(), for a no-return next function, can - end up returning something past the end of this function's body. */ - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); + end up returning something past the end of this function's body. + If the frame we're sniffing for is a signal frame whose start + address is placed on the stack by the OS, its FDE must + extend one byte before its start address or we will miss it. */ + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); if (!fde) return NULL; @@ -1233,8 +1252,9 @@ static const struct frame_base dwarf2_fr const struct frame_base * dwarf2_frame_base_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - if (dwarf2_frame_find_fde (&pc)) + CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame, + NORMAL_FRAME); + if (dwarf2_frame_find_fde (&block_addr)) return &dwarf2_frame_base; return NULL; Index: frame.c =================================================================== RCS file: /cvs/src/src/gdb/frame.c,v retrieving revision 1.221 diff -u -p -r1.221 frame.c --- frame.c 27 Feb 2007 19:46:04 -0000 1.221 +++ frame.c 27 Feb 2007 20:14:41 -0000 @@ -471,13 +471,13 @@ frame_pc_unwind (struct frame_info *this } CORE_ADDR -frame_func_unwind (struct frame_info *fi) +frame_func_unwind (struct frame_info *fi, enum frame_type this_type) { if (!fi->prev_func.p) { /* Make certain that this, and not the adjacent, function is found. */ - CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi); + CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi, this_type); fi->prev_func.p = 1; fi->prev_func.addr = get_pc_function_start (addr_in_block); if (frame_debug) @@ -491,7 +491,7 @@ frame_func_unwind (struct frame_info *fi CORE_ADDR get_frame_func (struct frame_info *fi) { - return frame_func_unwind (fi->next); + return frame_func_unwind (fi->next, get_frame_type (fi)); } static int @@ -1496,20 +1496,31 @@ get_frame_pc (struct frame_info *frame) return frame_pc_unwind (frame->next); } -/* Return an address of that falls within the frame's code block. */ +/* Return an address that falls within NEXT_FRAME's caller's code + block, assuming that the caller is a THIS_TYPE frame. */ CORE_ADDR -frame_unwind_address_in_block (struct frame_info *next_frame) +frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type) { /* A draft address. */ CORE_ADDR pc = frame_pc_unwind (next_frame); + /* If NEXT_FRAME was called by a signal frame or dummy frame, then + we shold not adjust the unwound PC. These frames may not call + their next frame in the normal way; the operating system or GDB + may have pushed their resume address manually onto the stack, so + it may be the very first instruction. Even if the resume address + was not manually pushed, they expect to be returned to. */ + if (this_type != NORMAL_FRAME) + return pc; + /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel), and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS frame's PC ends up pointing at the instruction fallowing the "call". Adjust that PC value so that it falls on the call instruction (which, hopefully, falls within THIS frame's code - block. So far it's proved to be a very good approximation. See + block). So far it's proved to be a very good approximation. See get_frame_type() for why ->type can't be used. */ if (next_frame->level >= 0 && get_frame_type (next_frame) == NORMAL_FRAME) @@ -1520,7 +1531,8 @@ frame_unwind_address_in_block (struct fr CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame) { - return frame_unwind_address_in_block (this_frame->next); + return frame_unwind_address_in_block (this_frame->next, + get_frame_type (this_frame)); } static int Index: frame.h =================================================================== RCS file: /cvs/src/src/gdb/frame.h,v retrieving revision 1.153 diff -u -p -r1.153 frame.h --- frame.h 27 Feb 2007 19:46:04 -0000 1.153 +++ frame.h 27 Feb 2007 20:14:41 -0000 @@ -184,6 +184,25 @@ extern int frame_id_inner (struct frame_ extern void fprint_frame_id (struct ui_file *file, struct frame_id id); +/* Frame types. Some are real, some are signal trampolines, and some + are completely artificial (dummy). */ + +enum frame_type +{ + /* A true stack frame, created by the target program during normal + execution. */ + NORMAL_FRAME, + /* A fake frame, created by GDB when performing an inferior function + call. */ + DUMMY_FRAME, + /* In a signal handler, various OSs handle this in various ways. + The main thing is that the frame may be far from normal. */ + SIGTRAMP_FRAME, + /* Sentinel or registers frame. This frame obtains register values + direct from the inferior's registers. */ + SENTINEL_FRAME +}; + /* For every stopped thread, GDB tracks two frames: current and selected. Current frame is the inner most frame of the selected thread. Selected frame is the one being examined by the the GDB @@ -265,7 +284,13 @@ extern CORE_ADDR get_frame_pc (struct fr the frame's block. */ extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); -extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame); + +/* Similar to get_frame_address_in_block, find an address in the + block which logically called NEXT_FRAME, assuming it is a THIS_TYPE + frame. */ + +extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, + enum frame_type this_type); /* The frame's inner-most bound. AKA the stack-pointer. Confusingly known as top-of-stack. */ @@ -277,9 +302,13 @@ extern CORE_ADDR frame_sp_unwind (struct /* Following on from the `resume' address. Return the entry point address of the function containing that resume address, or zero if that function isn't known. */ -extern CORE_ADDR frame_func_unwind (struct frame_info *fi); extern CORE_ADDR get_frame_func (struct frame_info *fi); +/* Similar to get_frame_func, find the start of the function which + logically called NEXT_FRAME, assuming it is a THIS_TYPE frame. */ +extern CORE_ADDR frame_func_unwind (struct frame_info *next_frame, + enum frame_type this_type); + /* Closely related to the resume address, various symbol table attributes that are determined by the PC. Note that for a normal frame, the PC refers to the resume address after the return, and @@ -375,24 +404,8 @@ extern CORE_ADDR get_frame_args_address for an invalid frame). */ extern int frame_relative_level (struct frame_info *fi); -/* Return the frame's type. Some are real, some are signal - trampolines, and some are completely artificial (dummy). */ +/* Return the frame's type. */ -enum frame_type -{ - /* A true stack frame, created by the target program during normal - execution. */ - NORMAL_FRAME, - /* A fake frame, created by GDB when performing an inferior function - call. */ - DUMMY_FRAME, - /* In a signal handler, various OSs handle this in various ways. - The main thing is that the frame may be far from normal. */ - SIGTRAMP_FRAME, - /* Sentinel or registers frame. This frame obtains register values - direct from the inferior's registers. */ - SENTINEL_FRAME -}; extern enum frame_type get_frame_type (struct frame_info *); /* For frames where we can not unwind further, describe why. */ Index: frv-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/frv-tdep.c,v retrieving revision 1.100 diff -u -p -r1.100 frv-tdep.c --- frv-tdep.c 14 Jan 2007 14:35:52 -0000 1.100 +++ frv-tdep.c 27 Feb 2007 20:14:41 -0000 @@ -1016,7 +1016,8 @@ frv_frame_unwind_cache (struct frame_inf info->saved_regs = trad_frame_alloc_saved_regs (next_frame); /* Prologue analysis does the rest... */ - frv_analyze_prologue (frame_func_unwind (next_frame), next_frame, info); + frv_analyze_prologue (frame_func_unwind (next_frame, NORMAL_FRAME), + next_frame, info); return info; } @@ -1346,7 +1347,7 @@ frv_frame_this_id (struct frame_info *ne struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); Index: h8300-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/h8300-tdep.c,v retrieving revision 1.105 diff -u -p -r1.105 h8300-tdep.c --- h8300-tdep.c 9 Jan 2007 20:19:15 -0000 1.105 +++ h8300-tdep.c 27 Feb 2007 20:14:41 -0000 @@ -447,7 +447,7 @@ h8300_frame_cache (struct frame_info *ne cache->saved_regs[E_PC_REGNUM] = -BINWORD; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) h8300_analyze_prologue (cache->pc, current_pc, cache); Index: hppa-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/hppa-tdep.c,v retrieving revision 1.226 diff -u -p -r1.226 hppa-tdep.c --- hppa-tdep.c 16 Feb 2007 21:49:59 -0000 1.226 +++ hppa-tdep.c 27 Feb 2007 20:14:41 -0000 @@ -1787,9 +1787,14 @@ hppa_skip_prologue (CORE_ADDR pc) static struct unwind_table_entry * hppa_find_unwind_entry_in_block (struct frame_info *f) { - CORE_ADDR pc; + CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME); - pc = frame_unwind_address_in_block (f); + /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the + result of frame_unwind_address_in_block implies a problem. + The bits should have been removed earlier, before the return + value of frame_pc_unwind. That might be happening already; + if it isn't, it should be fixed. Then this call can be + removed. */ pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc); return find_unwind_entry (pc); } @@ -1899,7 +1904,7 @@ hppa_frame_cache (struct frame_info *nex if ((u->Region_description & 0x2) == 0) start_pc = u->region_start; else - start_pc = frame_func_unwind (next_frame); + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); prologue_end = skip_prologue_hard_way (start_pc, 0); end_pc = frame_pc_unwind (next_frame); @@ -2267,7 +2272,7 @@ hppa_fallback_frame_cache (struct frame_ (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - start_pc = frame_func_unwind (next_frame); + start_pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (start_pc) { CORE_ADDR cur_pc = frame_pc_unwind (next_frame); @@ -2326,7 +2331,8 @@ hppa_fallback_frame_this_id (struct fram { struct hppa_frame_cache *info = hppa_fallback_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -2409,7 +2415,8 @@ hppa_stub_frame_this_id (struct frame_in = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache); if (info) - *this_id = frame_id_build (info->base, frame_func_unwind (next_frame)); + *this_id = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); else *this_id = null_frame_id; } @@ -2441,7 +2448,7 @@ static const struct frame_unwind hppa_st static const struct frame_unwind * hppa_stub_unwind_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct gdbarch *gdbarch = get_frame_arch (next_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.231 diff -u -p -r1.231 i386-tdep.c --- i386-tdep.c 16 Feb 2007 21:49:59 -0000 1.231 +++ i386-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -949,7 +949,7 @@ i386_frame_cache (struct frame_info *nex /* For normal frames, %eip is stored at 4(%ebp). */ cache->saved_regs[I386_EIP_REGNUM] = 4; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: i386obsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386obsd-tdep.c,v retrieving revision 1.31 diff -u -p -r1.31 i386obsd-tdep.c --- i386obsd-tdep.c 9 Jan 2007 17:58:51 -0000 1.31 +++ i386obsd-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -353,7 +353,9 @@ i386obsd_trapframe_cache(struct frame_in cache = trad_frame_cache_zalloc (next_frame); *this_cache = cache; - func = frame_func_unwind (next_frame); + /* NORMAL_FRAME matches the type in i386obsd_trapframe_unwind, but + SIGTRAMP_FRAME might be more appropriate. */ + func = frame_func_unwind (next_frame, NORMAL_FRAME); sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); Index: ia64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ia64-tdep.c,v retrieving revision 1.146 diff -u -p -r1.146 ia64-tdep.c --- ia64-tdep.c 16 Feb 2007 21:49:59 -0000 1.146 +++ ia64-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -1555,7 +1555,7 @@ ia64_frame_cache (struct frame_info *nex cache->cfm = cfm; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) examine_prologue (cache->pc, frame_pc_unwind (next_frame), next_frame, cache); Index: libunwind-frame.c =================================================================== RCS file: /cvs/src/src/gdb/libunwind-frame.c,v retrieving revision 1.10 diff -u -p -r1.10 libunwind-frame.c --- libunwind-frame.c 9 Jan 2007 17:58:51 -0000 1.10 +++ libunwind-frame.c 27 Feb 2007 20:14:42 -0000 @@ -141,7 +141,10 @@ libunwind_frame_cache (struct frame_info /* Allocate a new cache. */ cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); - cache->func_addr = frame_func_unwind (next_frame); + /* We can assume we are unwinding a normal frame. Even if this is + for a signal trampoline, ia64 signal "trampolines" use a normal + subroutine call to start the signal handler. */ + cache->func_addr = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->func_addr == 0 && frame_relative_level (next_frame) > 0 && get_frame_type (next_frame) != SIGTRAMP_FRAME) Index: m32c-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m32c-tdep.c,v retrieving revision 1.7 diff -u -p -r1.7 m32c-tdep.c --- m32c-tdep.c 23 Jan 2007 13:06:32 -0000 1.7 +++ m32c-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -1836,7 +1836,7 @@ m32c_analyze_frame_prologue (struct fram { if (! *this_prologue_cache) { - CORE_ADDR func_start = frame_func_unwind (next_frame); + CORE_ADDR func_start = frame_func_unwind (next_frame, NORMAL_FRAME); CORE_ADDR stop_addr = frame_pc_unwind (next_frame); /* If we couldn't find any function containing the PC, then @@ -1900,7 +1900,8 @@ m32c_this_id (struct frame_info *next_fr CORE_ADDR base = m32c_frame_base (next_frame, this_prologue_cache); if (base) - *this_id = frame_id_build (base, frame_func_unwind (next_frame)); + *this_id = frame_id_build (base, + frame_func_unwind (next_frame, NORMAL_FRAME)); /* Otherwise, leave it unset, and that will terminate the backtrace. */ } Index: m32r-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m32r-linux-tdep.c,v retrieving revision 1.7 diff -u -p -r1.7 m32r-linux-tdep.c --- m32r-linux-tdep.c 9 Jan 2007 17:58:51 -0000 1.7 +++ m32r-linux-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -250,7 +250,7 @@ m32r_linux_sigtramp_frame_cache (struct if (addr) sigcontext_addr += 128; else - addr = frame_func_unwind (next_frame); + addr = frame_func_unwind (next_frame, NORMAL_FRAME); } cache->pc = addr; Index: m32r-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m32r-tdep.c,v retrieving revision 1.42 diff -u -p -r1.42 m32r-tdep.c --- m32r-tdep.c 9 Jan 2007 17:58:52 -0000 1.42 +++ m32r-tdep.c 27 Feb 2007 20:14:42 -0000 @@ -536,7 +536,7 @@ m32r_frame_unwind_cache (struct frame_in info->uses_frame = 0; scan_limit = frame_pc_unwind (next_frame); - for (pc = frame_func_unwind (next_frame); + for (pc = frame_func_unwind (next_frame, NORMAL_FRAME); pc > 0 && pc < scan_limit; pc += 2) { if ((pc & 2) == 0) @@ -835,7 +835,7 @@ m32r_frame_this_id (struct frame_info *n struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Check if the stack is empty. */ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL); Index: m68hc11-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m68hc11-tdep.c,v retrieving revision 1.111 diff -u -p -r1.111 m68hc11-tdep.c --- m68hc11-tdep.c 9 Jan 2007 17:58:52 -0000 1.111 +++ m68hc11-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -798,7 +798,7 @@ m68hc11_frame_unwind_cache (struct frame (*this_prologue_cache) = info; info->saved_regs = trad_frame_alloc_saved_regs (next_frame); - info->pc = frame_func_unwind (next_frame); + info->pc = frame_func_unwind (next_frame, NORMAL_FRAME); info->size = 0; info->return_kind = m68hc11_get_return_insn (info->pc); @@ -889,7 +889,7 @@ m68hc11_frame_this_id (struct frame_info struct frame_id id; /* The FUNC is easy. */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set Index: m68k-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m68k-tdep.c,v retrieving revision 1.111 diff -u -p -r1.111 m68k-tdep.c --- m68k-tdep.c 16 Feb 2007 21:49:59 -0000 1.111 +++ m68k-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -819,7 +819,7 @@ m68k_frame_cache (struct frame_info *nex /* For normal frames, %pc is stored at 4(%fp). */ cache->saved_regs[M68K_PC_REGNUM] = 4; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) m68k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); Index: m88k-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m88k-tdep.c,v retrieving revision 1.21 diff -u -p -r1.21 m88k-tdep.c --- m88k-tdep.c 29 Jan 2007 17:31:06 -0000 1.21 +++ m88k-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -659,12 +659,9 @@ m88k_frame_cache (struct frame_info *nex cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); cache->fp_offset = -1; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - m88k_analyze_prologue (cache->pc, addr_in_block, cache); - } + m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); /* Calculate the stack pointer used in the prologue. */ if (cache->fp_offset != -1) Index: mips-mdebug-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-mdebug-tdep.c,v retrieving revision 1.8 diff -u -p -r1.8 mips-mdebug-tdep.c --- mips-mdebug-tdep.c 9 Jan 2007 17:58:52 -0000 1.8 +++ mips-mdebug-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -386,7 +386,8 @@ mips_mdebug_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -412,7 +413,7 @@ static const struct frame_unwind mips_md static const struct frame_unwind * mips_mdebug_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); CORE_ADDR startaddr = 0; struct mdebug_extra_func_info *proc_desc; int kernel_trap; Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.403 diff -u -p -r1.403 mips-tdep.c --- mips-tdep.c 29 Jan 2007 17:31:06 -0000 1.403 +++ mips-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -1666,7 +1666,8 @@ mips_insn16_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -1692,7 +1693,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn16_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (mips_pc_is_mips16 (pc)) return &mips_insn16_frame_unwind; return NULL; @@ -1986,7 +1987,8 @@ mips_insn32_frame_this_id (struct frame_ { struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void @@ -2012,7 +2014,7 @@ static const struct frame_unwind mips_in static const struct frame_unwind * mips_insn32_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (! mips_pc_is_mips16 (pc)) return &mips_insn32_frame_unwind; return NULL; @@ -2107,7 +2109,7 @@ static const struct frame_unwind * mips_stub_frame_sniffer (struct frame_info *next_frame) { struct obj_section *s; - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (in_plt_section (pc, NULL)) return &mips_stub_frame_unwind; Index: mn10300-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mn10300-tdep.c,v retrieving revision 1.138 diff -u -p -r1.138 mn10300-tdep.c --- mn10300-tdep.c 9 Jan 2007 17:58:52 -0000 1.138 +++ mn10300-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -850,9 +850,12 @@ mn10300_frame_unwind_cache (struct frame frame_id_build (trad_frame_get_this_base (cache), start)); else - trad_frame_set_id (cache, - frame_id_build (trad_frame_get_this_base (cache), - frame_func_unwind (next_frame))); + { + start = frame_func_unwind (next_frame, NORMAL_FRAME); + trad_frame_set_id (cache, + frame_id_build (trad_frame_get_this_base (cache), + start)); + } (*this_prologue_cache) = cache; return cache; Index: mt-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mt-tdep.c,v retrieving revision 1.8 diff -u -p -r1.8 mt-tdep.c --- mt-tdep.c 20 Feb 2007 12:45:06 -0000 1.8 +++ mt-tdep.c 27 Feb 2007 20:14:43 -0000 @@ -891,7 +891,7 @@ mt_frame_unwind_cache (struct frame_info frame_unwind_unsigned_register (next_frame, MT_SP_REGNUM, &sp); frame_unwind_unsigned_register (next_frame, MT_FP_REGNUM, &fp); - start_addr = frame_func_unwind (next_frame); + start_addr = frame_func_unwind (next_frame, NORMAL_FRAME); /* Return early if GDB couldn't find the function. */ if (start_addr == 0) @@ -1041,10 +1041,9 @@ mt_frame_this_id (struct frame_info *nex mt_frame_unwind_cache (next_frame, this_prologue_cache); if (!(info == NULL || info->prev_sp == 0)) - { - (*this_id) = frame_id_build (info->prev_sp, - frame_func_unwind (next_frame)); - } + (*this_id) = frame_id_build (info->prev_sp, + frame_func_unwind (next_frame, NORMAL_FRAME)); + return; } Index: rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.262 diff -u -p -r1.262 rs6000-tdep.c --- rs6000-tdep.c 8 Feb 2007 18:05:23 -0000 1.262 +++ rs6000-tdep.c 27 Feb 2007 20:14:44 -0000 @@ -2970,7 +2970,7 @@ rs6000_frame_cache (struct frame_info *n (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); pc = frame_pc_unwind (next_frame); skip_prologue (func, pc, &fdata); @@ -3122,7 +3122,8 @@ rs6000_frame_this_id (struct frame_info { struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: s390-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/s390-tdep.c,v retrieving revision 1.158 diff -u -p -r1.158 s390-tdep.c --- s390-tdep.c 9 Jan 2007 17:58:58 -0000 1.158 +++ s390-tdep.c 27 Feb 2007 20:14:44 -0000 @@ -1232,7 +1232,7 @@ s390_prologue_frame_unwind_cache (struct bother searching for it -- with modern compilers this would be mostly pointless anyway. Trust that we'll either have valid DWARF-2 CFI data or else a valid backchain ... */ - func = frame_func_unwind (next_frame); + func = frame_func_unwind (next_frame, NORMAL_FRAME); if (!func) return 0; @@ -1556,14 +1556,15 @@ static const struct frame_unwind s390_st static const struct frame_unwind * s390_stub_frame_sniffer (struct frame_info *next_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + CORE_ADDR addr_in_block; bfd_byte insn[S390_MAX_INSTR_SIZE]; /* If the current PC points to non-readable memory, we assume we have trapped due to an invalid function pointer call. We handle the non-existing current function like a PLT stub. */ - if (in_plt_section (pc, NULL) - || s390_readinstruction (insn, pc) < 0) + addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + if (in_plt_section (addr_in_block, NULL) + || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0) return &s390_stub_frame_unwind; return NULL; } Index: score-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/score-tdep.c,v retrieving revision 1.3 diff -u -p -r1.3 score-tdep.c --- score-tdep.c 9 Jan 2007 21:25:03 -0000 1.3 +++ score-tdep.c 27 Feb 2007 20:14:44 -0000 @@ -801,7 +801,8 @@ score_prologue_this_id (struct frame_inf { struct score_frame_cache *info = score_make_prologue_cache (next_frame, this_cache); - (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (info->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: sh-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sh-tdep.c,v retrieving revision 1.197 diff -u -p -r1.197 sh-tdep.c --- sh-tdep.c 21 Jan 2007 17:37:51 -0000 1.197 +++ sh-tdep.c 27 Feb 2007 20:14:44 -0000 @@ -2215,7 +2215,7 @@ sh_frame_cache (struct frame_info *next_ if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) sh_analyze_prologue (cache->pc, current_pc, cache); Index: sh64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sh64-tdep.c,v retrieving revision 1.43 diff -u -p -r1.43 sh64-tdep.c --- sh64-tdep.c 27 Feb 2007 19:46:04 -0000 1.43 +++ sh64-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -2253,7 +2253,7 @@ sh64_frame_cache (struct frame_info *nex if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) sh64_analyze_prologue (current_gdbarch, cache, cache->pc, current_pc); Index: sparc-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.c,v retrieving revision 1.177 diff -u -p -r1.177 sparc-tdep.c --- sparc-tdep.c 29 Jan 2007 17:31:06 -0000 1.177 +++ sparc-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -699,12 +699,9 @@ sparc_frame_cache (struct frame_info *ne cache = sparc_alloc_frame_cache (); *this_cache = cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); if (cache->pc != 0) - { - CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); - sparc_analyze_prologue (cache->pc, addr_in_block, cache); - } + sparc_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); if (cache->frameless_p) { @@ -1054,7 +1051,7 @@ sparc32_stabs_argument_has_addr (struct static int sparc32_dwarf2_struct_return_p (struct frame_info *next_frame) { - CORE_ADDR pc = frame_unwind_address_in_block (next_frame); + CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); struct symbol *sym = find_pc_function (pc); if (sym) Index: sparc64obsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc64obsd-tdep.c,v retrieving revision 1.21 diff -u -p -r1.21 sparc64obsd-tdep.c --- sparc64obsd-tdep.c 9 Jan 2007 17:58:58 -0000 1.21 +++ sparc64obsd-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru /* Kernel debugging support. */ static struct sparc_frame_cache * -sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) +sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; CORE_ADDR sp, trapframe_addr; @@ -267,15 +267,17 @@ static const struct frame_unwind sparc64 static const struct frame_unwind * sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) { + CORE_ADDR pc; ULONGEST pstate; char *name; /* Check whether we are in privileged mode, and bail out if we're not. */ - pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM); + pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); if ((pstate & SPARC64_PSTATE_PRIV) == 0) return NULL; - find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); + pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); + find_pc_partial_function (pc, &name, NULL, NULL); if (name && strcmp (name, "Lslowtrap_reenter") == 0) return &sparc64obsd_trapframe_unwind; Index: spu-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/spu-tdep.c,v retrieving revision 1.6 diff -u -p -r1.6 spu-tdep.c --- spu-tdep.c 29 Jan 2007 17:31:06 -0000 1.6 +++ spu-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -587,7 +587,7 @@ spu_frame_unwind_cache (struct frame_inf info->local_base = 0; /* Find the start of the current function, and analyze its prologue. */ - info->func = frame_func_unwind (next_frame); + info->func = frame_func_unwind (next_frame, NORMAL_FRAME); if (info->func == 0) { /* Fall back to using the current PC as frame ID. */ Index: v850-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/v850-tdep.c,v retrieving revision 1.97 diff -u -p -r1.97 v850-tdep.c --- v850-tdep.c 9 Jan 2007 17:58:59 -0000 1.97 +++ v850-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -856,7 +856,7 @@ v850_frame_cache (struct frame_info *nex if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc != 0) v850_analyze_prologue (cache->pc, current_pc, cache); Index: vax-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/vax-tdep.c,v retrieving revision 1.94 diff -u -p -r1.94 vax-tdep.c --- vax-tdep.c 29 Jan 2007 17:31:06 -0000 1.94 +++ vax-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -384,7 +384,8 @@ vax_frame_this_id (struct frame_info *ne if (cache->base == 0) return; - (*this_id) = frame_id_build (cache->base, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (cache->base, + frame_func_unwind (next_frame, NORMAL_FRAME)); } static void Index: xstormy16-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/xstormy16-tdep.c,v retrieving revision 1.92 diff -u -p -r1.92 xstormy16-tdep.c --- xstormy16-tdep.c 22 Jan 2007 10:08:33 -0000 1.92 +++ xstormy16-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -655,7 +655,7 @@ xstormy16_frame_cache (struct frame_info if (cache->base == 0) return cache; - cache->pc = frame_func_unwind (next_frame); + cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME); current_pc = frame_pc_unwind (next_frame); if (cache->pc) xstormy16_analyze_prologue (cache->pc, current_pc, cache, next_frame); Index: xtensa-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/xtensa-tdep.c,v retrieving revision 1.4 diff -u -p -r1.4 xtensa-tdep.c --- xtensa-tdep.c 20 Feb 2007 12:45:06 -0000 1.4 +++ xtensa-tdep.c 27 Feb 2007 20:14:45 -0000 @@ -924,7 +924,7 @@ xtensa_frame_cache (struct frame_info *n cache->ws = ws & ~(1 << wb); } - cache->pc = ((frame_func_unwind (next_frame) & 0xc0000000) + cache->pc = ((frame_func_unwind (next_frame, NORMAL_FRAME) & 0xc0000000) | (ra & 0x3fffffff)); cache->ps = (ps & ~PS_CALLINC_MASK) | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT); Index: testsuite/gdb.arch/i386-signal.c =================================================================== RCS file: testsuite/gdb.arch/i386-signal.c diff -N testsuite/gdb.arch/i386-signal.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.arch/i386-signal.c 27 Feb 2007 20:14:45 -0000 @@ -0,0 +1,55 @@ +/* Unwinder test program for signal frames. + + Copyright 2007 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +void sigframe (void); +void setup (void); + +void +func (void) +{ +} + +int +main (void) +{ + setup (); +} + +/* Create an imitation signal frame. This will work on any x86 or + x86-64 target which uses a version of GAS recent enough for + .cfi_signal_frame (added 2006-02-27 and included in binutils 2.17). + The default CIE created by gas suffices to unwind from an empty + function. */ + +asm(".text\n" + " .align 8\n" + " .globl setup\n" + "setup:\n" + " push $sigframe\n" + " jmp func\n" + "\n" + " .cfi_startproc\n" + " .cfi_signal_frame\n" + " nop\n" + " .globl sigframe\n" + "sigframe:\n" + " ret\n" + " .cfi_endproc"); Index: testsuite/gdb.arch/i386-signal.exp =================================================================== RCS file: testsuite/gdb.arch/i386-signal.exp diff -N testsuite/gdb.arch/i386-signal.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.arch/i386-signal.exp 27 Feb 2007 20:14:45 -0000 @@ -0,0 +1,43 @@ +# Copyright 2007 Free Software Foundation, Inc. + +# This file is part of the GDB testsuite. + +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then { + verbose "Skipping i386 unwinder tests." + return +} + +set testfile "i386-signal" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + untested i386-sigframe.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +runto func +gdb_test "backtrace 10" \ + "#0 ($hex in )?func.*\r\n#1 <signal handler called>\r\n#2 ($hex in)?main.*" + +gdb_test "finish" "Run till exit from \#0 func.*<signal handler called>" ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2007-02-27 20:18 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20060706222157.GA1377@nevyn.them.org>
[not found] ` <200607132020.k6DKKCSB023812@elgar.sibelius.xs4all.nl>
[not found] ` <20060718183910.GB17864@nevyn.them.org>
2007-01-01 19:19 ` [patch RFC] Re: Notes on a frame_unwind_address_in_block problem Daniel Jacobowitz
2007-01-01 19:54 ` Mark Kettenis
2007-01-01 20:02 ` Daniel Jacobowitz
2007-01-01 20:27 ` Mark Kettenis
2007-01-01 20:35 ` Daniel Jacobowitz
2007-01-02 0:51 ` Daniel Jacobowitz
2007-01-02 19:16 ` Mark Kettenis
2007-01-02 19:18 ` Daniel Jacobowitz
2007-01-02 19:20 ` Daniel Jacobowitz
2007-01-02 21:32 ` Mark Kettenis
2007-01-03 11:37 ` Mark Kettenis
2007-01-03 14:43 ` Daniel Jacobowitz
2007-01-03 16:13 ` Daniel Jacobowitz
2007-01-03 20:28 ` Mark Kettenis
2007-01-03 20:30 ` Daniel Jacobowitz
2007-01-03 21:58 ` Mark Kettenis
2007-01-03 22:02 ` Daniel Jacobowitz
2007-01-03 22:23 ` Mark Kettenis
2007-01-03 22:29 ` Daniel Jacobowitz
2007-02-20 12:39 ` Daniel Jacobowitz
2007-02-20 15:31 ` Daniel Jacobowitz
2007-02-20 16:20 ` Daniel Jacobowitz
2007-02-22 21:28 ` Mark Kettenis
2007-02-22 21:32 ` Daniel Jacobowitz
2007-02-27 20:18 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox