* New ARI warning Thu Oct 13 01:55:36 UTC 2011
@ 2011-10-13 1:55 GDB Administrator
2011-10-13 13:54 ` Jan Kratochvil
0 siblings, 1 reply; 7+ messages in thread
From: GDB Administrator @ 2011-10-13 1:55 UTC (permalink / raw)
To: gdb-patches
216a217
> gdb/dwarf2-frame-tailcall.c:283: obsolete: get_frame_base: Replace get_frame_base with get_frame_id, get_frame_base_address, get_frame_locals_address, or get_frame_args_address.
gdb/dwarf2-frame-tailcall.c:283: addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset;
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011 2011-10-13 1:55 New ARI warning Thu Oct 13 01:55:36 UTC 2011 GDB Administrator @ 2011-10-13 13:54 ` Jan Kratochvil 2011-10-13 15:00 ` Ulrich Weigand 0 siblings, 1 reply; 7+ messages in thread From: Jan Kratochvil @ 2011-10-13 13:54 UTC (permalink / raw) To: GDB Administrator; +Cc: gdb-patches On Thu, 13 Oct 2011 03:55:36 +0200, GDB Administrator wrote: > 216a217 > > gdb/dwarf2-frame-tailcall.c:283: obsolete: get_frame_base: Replace get_frame_base with get_frame_id, get_frame_base_address, get_frame_locals_address, or get_frame_args_address. > gdb/dwarf2-frame-tailcall.c:283: addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset; This comes from my: [patch 04/12] entryval#3: Virtual tail call frames http://sourceware.org/ml/gdb-patches/2011-09/msg00556.html where the code is specific to gdbarch_sp_regnum, so I think it should operate with this_frame->stack_addr, which is exactly what get_frame_base does. I understand such code ($sp simulation with shift for return address in tail call frames) could have been rather gdbarch-specific but I am not aware of any gdbarch where it should be done differently. If such gdbarch exists and there is interest in fixing this very minor feature of the entryval patchset this can be moved to gdbarch-specific code where maybe get_frame_base may not be appropriate. I have no idea without being aware of any such gdbarch. Regards, Jan ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011 2011-10-13 13:54 ` Jan Kratochvil @ 2011-10-13 15:00 ` Ulrich Weigand 2011-10-13 21:15 ` entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] Jan Kratochvil 0 siblings, 1 reply; 7+ messages in thread From: Ulrich Weigand @ 2011-10-13 15:00 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches Jan Kratochvil wrote: > On Thu, 13 Oct 2011 03:55:36 +0200, GDB Administrator wrote: > > 216a217 > > > gdb/dwarf2-frame-tailcall.c:283: obsolete: get_frame_base: Replace get_frame_base with get_frame_id, get_frame_base_address, get_frame_locals_address, or get_frame_args_address. > > gdb/dwarf2-frame-tailcall.c:283: addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset; > > This comes from my: > [patch 04/12] entryval#3: Virtual tail call frames > http://sourceware.org/ml/gdb-patches/2011-09/msg00556.html > > where the code is specific to gdbarch_sp_regnum, so I think it should operate > with this_frame->stack_addr, which is exactly what get_frame_base does. Unfortunately this code reintroduced a number of platform-specific assumptions that Andrew went to a lot of effort to eliminate from common frame-handling code. Generic code is not supposed to make the assumption that there *is* a single "sp" (or "pc") register; instead it should leave the details up to the gdbarch's unwind_pc and unwind_sp routines. (And on various platforms those routines *are* more complicated that just unwinding one particular register ...) I don't like re-introducing a new use of get_frame_base in common code; we've been really close to eliminating this (for good reasons; see the various comments in the code). The problem is that frame->stack_addr is supposed to be opaque to common code; it is explicitly *not* defined to equal the value of some SP register. It's meaning is solely up to the frame unwinders. For DWARF frames specifically, the convention is that ->stack_addr will equal the CFA. So if you are in DWARF-specific code, and need the CFA, you can make use of that convention; but the best way to do that would probably be to call dwarf2_frame_cfa instead of get_frame_base. Note however, that even the CFA is not automatically equal to some "value of a SP register"; for example, on s390(x), the CFA is always biased by 96 (or 160) bytes against the SP at function entry ... > I understand such code ($sp simulation with shift for return address in tail > call frames) could have been rather gdbarch-specific but I am not aware of any > gdbarch where it should be done differently. If such gdbarch exists and there > is interest in fixing this very minor feature of the entryval patchset this > can be moved to gdbarch-specific code where maybe get_frame_base may not be > appropriate. I have no idea without being aware of any such gdbarch. I'm afraid I'm not sure exactly what all this SP manipulation code is intended to achieve; could you elaborate (or is there documentation somewhere that I missed)? Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 7+ messages in thread
* entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] 2011-10-13 15:00 ` Ulrich Weigand @ 2011-10-13 21:15 ` Jan Kratochvil 2011-10-19 16:05 ` Ulrich Weigand 0 siblings, 1 reply; 7+ messages in thread From: Jan Kratochvil @ 2011-10-13 21:15 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches On Thu, 13 Oct 2011 16:59:37 +0200, Ulrich Weigand wrote: > Generic code is not supposed to make the assumption that there *is* > a single "sp" (or "pc") register; The current code does everything in a "best effort" mode. If anything fails $sp in tail call frames is just not adjusted - it should not be such a problem. So far I would set such behavior for all gdbarches anyway (*). (*) I guess the correct approach is to set it only for gdbarches where one verifies it is correct. Still if the code succeeds I believe the result is always correct - so what is the point of gdbarch in such case? > For DWARF frames specifically, the convention is that ->stack_addr will > equal the CFA. So if you are in DWARF-specific code, and need the CFA, > you can make use of that convention; but the best way to do that would > probably be to call dwarf2_frame_cfa instead of get_frame_base. I see now dwarf2_frame_cfa is more appropriate by its name. The detection code is based on CFA (CFA_REG_OFFSET, regs.cfa_reg etc.). And dwarf2_frame_cfa in such case effectively just calls get_frame_base. Unless you advice me differently I will change it this way. > Note however, that even the CFA is not automatically equal to some "value > of a SP register"; for example, on s390(x), the CFA is always biased by 96 > (or 160) bytes against the SP at function entry ... On s390x the adjustment code in dwarf2_tailcall_prev_register_first (detected inside dwarf2_frame_cache, from .debug_frame) gets into effect but in fact it does not change the $sp value. Which is correct, as "brasl" does not modify $sp. > I'm afraid I'm not sure exactly what all this SP manipulation code is intended > to achieve; could you elaborate (or is there documentation somewhere that I > missed)? I dd not think it needs to be documented in the manual as it just simulates the expected state of inferior. In the x86_64 sample code below when we unwind function `f' the register set there should be already the unwound one - the same like in the function `main'. `f' just stands on the jmp instruction so it does not have any its own register state to unwind. Just there is the exception $sp - in function `f' the value of $sp should not be the same like in the function `main' as there is the return address there. The two lines `XXX' - the real register state should match the later unwound register state. Thanks, Jan x86_64: static __attribute__ ((noinline, noclone)) void g (void) { asm volatile (""); } static __attribute__ ((noinline, noclone)) void f (void) { g (); } int main (void) { f (); return 0; } gcchead-root/bin/gcc -o tailcall4 tailcall4.c -Wall -g -O2 gdb -nx -x ~/.gdbinit ./tailcall4 -ex 'set disassemble-next-line on' -ex start 3 int main (void) { f (); return 0; } => 0x0000000000400360 <main+0>: e8 ab 00 00 00 callq 0x400410 <f> 0x0000000000400365 <main+5>: 31 c0 xor %eax,%eax 0x0000000000400367 <main+7>: c3 retq (gdb) display/x $sp 1: /x $sp = 0x7fffffffdb08 (gdb) stepi f () at tailcall4.c:2 2 static __attribute__ ((noinline, noclone)) void f (void) { g (); } => 0x0000000000400410 <f+0>: eb ee jmp 0x400400 <g> 1: /x $sp = 0x7fffffffdb00 XXX ^^^^^^^^^^^^^^ (gdb) stepi g () at tailcall4.c:1 1 static __attribute__ ((noinline, noclone)) void g (void) { asm volatile (""); } => 0x0000000000400400 <g+0>: c3 retq 0x0000000000400401: 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 data32 data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1) 1: /x $sp = 0x7fffffffdb00 (gdb) bt #0 g () at tailcall4.c:1 #1 0x0000000000400412 in f () at tailcall4.c:2 #2 0x0000000000400365 in main () at tailcall4.c:3 (gdb) up #1 0x0000000000400412 in f () at tailcall4.c:2 2 static __attribute__ ((noinline, noclone)) void f (void) { g (); } 0x0000000000400410 <f+0>: eb ee jmp 0x400400 <g> (gdb) p/x $sp $1 = 0x7fffffffdb00 XXX ^^^^^^^^^^^^^^ (gdb) up #2 0x0000000000400365 in main () at tailcall4.c:3 3 int main (void) { f (); return 0; } 0x0000000000400360 <main+0>: e8 ab 00 00 00 callq 0x400410 <f> => 0x0000000000400365 <main+5>: 31 c0 xor %eax,%eax 0x0000000000400367 <main+7>: c3 retq (gdb) p/x $sp $2 = 0x7fffffffdb08 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] 2011-10-13 21:15 ` entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] Jan Kratochvil @ 2011-10-19 16:05 ` Ulrich Weigand 2011-10-21 0:34 ` Jan Kratochvil 2011-10-21 0:45 ` Jan Kratochvil 0 siblings, 2 replies; 7+ messages in thread From: Ulrich Weigand @ 2011-10-19 16:05 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches Jan Kratochvil wrote: > On Thu, 13 Oct 2011 16:59:37 +0200, Ulrich Weigand wrote: > > Generic code is not supposed to make the assumption that there *is* > > a single "sp" (or "pc") register; > > The current code does everything in a "best effort" mode. If anything fails > $sp in tail call frames is just not adjusted - it should not be such a problem. > So far I would set such behavior for all gdbarches anyway (*). > > (*) I guess the correct approach is to set it only for gdbarches where one > verifies it is correct. Still if the code succeeds I believe the result is > always correct - so what is the point of gdbarch in such case? It's just that some of those assumptions seem really unnecessary to me. For example, the assumption that there is a fixed "PC" register: prev_gdbarch = frame_unwind_arch (this_frame); pc_regnum = gdbarch_pc_regnum (prev_gdbarch); if (pc_regnum == -1) break; /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ prev_pc = frame_unwind_register_unsigned (this_frame, pc_regnum); Why don't you just do something like: prev_gdbarch = frame_unwind_arch (this_frame); /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); Similarly, when injecting the tailcall PC values, you hook into the prev_register routine -- which assumes that unwind_pc will end up doing an unwind_register of pc_regnum. This assumptium would be unnecessary if you just hooked into frame_unwind_pc directly instead. Now as to SP, what happens is that you detect the rule for the CFA at the entry point is CFA = <sp_register> + <some_offset> Tailcall unwinding doesn't directly know the value of sp_register, but it does know the CFA, so you hook into prev_register to return a value of sp_register that is designed such that the above computation will yield the desired CFA. However -- nothing in that design depends on the CFA being relative to the SP register in particular. You could avoid this by detecting the more general rule CFA = <some_register> + <some_offset> and then remember both the register and the offset, and hook into prev_register for whatever the register is -- no need at all to enforce that this must be gdbarch_sp_regnum ... (You could then even generalize this to even more generic expressions to compute the CFA, if necessary for certain platforms.) > > For DWARF frames specifically, the convention is that ->stack_addr will > > equal the CFA. So if you are in DWARF-specific code, and need the CFA, > > you can make use of that convention; but the best way to do that would > > probably be to call dwarf2_frame_cfa instead of get_frame_base. > > I see now dwarf2_frame_cfa is more appropriate by its name. The detection > code is based on CFA (CFA_REG_OFFSET, regs.cfa_reg etc.). > And dwarf2_frame_cfa in such case effectively just calls get_frame_base. > > Unless you advice me differently I will change it this way. Yes, dwarf2_frame_cfa would be preferable here. > > Note however, that even the CFA is not automatically equal to some "value > > of a SP register"; for example, on s390(x), the CFA is always biased by 96 > > (or 160) bytes against the SP at function entry ... > > On s390x the adjustment code in dwarf2_tailcall_prev_register_first (detected > inside dwarf2_frame_cache, from .debug_frame) gets into effect but in fact it > does not change the $sp value. Which is correct, as "brasl" does not modify > $sp. I see that I misunderstood your code; it does take the offset between SP and CFA into account correctly, so it will work on s390 too. > > I'm afraid I'm not sure exactly what all this SP manipulation code is intended > > to achieve; could you elaborate (or is there documentation somewhere that I > > missed)? > > I dd not think it needs to be documented in the manual as it just simulates > the expected state of inferior. > > In the x86_64 sample code below when we unwind function `f' the register set > there should be already the unwound one - the same like in the function > `main'. `f' just stands on the jmp instruction so it does not have any its > own register state to unwind. > > Just there is the exception $sp - in function `f' the value of $sp should not > be the same like in the function `main' as there is the return address there. > The two lines `XXX' - the real register state should match the later unwound > register state. OK, thanks for the explanation. Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] 2011-10-19 16:05 ` Ulrich Weigand @ 2011-10-21 0:34 ` Jan Kratochvil 2011-10-21 0:45 ` Jan Kratochvil 1 sibling, 0 replies; 7+ messages in thread From: Jan Kratochvil @ 2011-10-21 0:34 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches On Wed, 19 Oct 2011 17:51:45 +0200, Ulrich Weigand wrote: > It's just that some of those assumptions seem really unnecessary to me. > For example, the assumption that there is a fixed "PC" register: > > prev_gdbarch = frame_unwind_arch (this_frame); > pc_regnum = gdbarch_pc_regnum (prev_gdbarch); > if (pc_regnum == -1) > break; > > /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ > prev_pc = frame_unwind_register_unsigned (this_frame, pc_regnum); > > Why don't you just do something like: > > prev_gdbarch = frame_unwind_arch (this_frame); > > /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ > prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); I agree with this simplification, used it. > Yes, dwarf2_frame_cfa would be preferable here. Also I agree. Checked in both changes. No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu. Thanks, Jan http://sourceware.org/ml/gdb-cvs/2011-10/msg00156.html --- src/gdb/ChangeLog 2011/10/20 23:12:59 1.13448 +++ src/gdb/ChangeLog 2011/10/20 23:57:23 1.13449 @@ -1,3 +1,12 @@ +2011-10-20 Jan Kratochvil <jan.kratochvil@redhat.com> + Ulrich Weigand <uweigand@de.ibm.com> + + * dwarf2-frame-tailcall.c: Include dwarf2-frame.h. + (dwarf2_tailcall_prev_register_first): Use dwarf2_frame_cfa. + (dwarf2_tailcall_sniffer_first): Remove variable pc_regnum. Replace + gdbarch_pc_regnum and frame_unwind_register_unsigned by + gdbarch_unwind_pc. + 2011-10-20 Cary Coutant <ccoutant@google.com> * dwarf2read.c (dw2_get_file_names): Move adjustment for type --- src/gdb/dwarf2-frame-tailcall.c 2011/10/09 20:21:48 1.1 +++ src/gdb/dwarf2-frame-tailcall.c 2011/10/20 23:57:23 1.2 @@ -29,6 +29,7 @@ #include "gdbtypes.h" #include "regcache.h" #include "value.h" +#include "dwarf2-frame.h" /* Contains struct tailcall_cache indexed by next_bottom_frame. */ static htab_t cache_htab; @@ -280,7 +281,7 @@ if (next_levels == cache->chain_levels - 1) addr = cache->prev_sp; else - addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset; + addr = dwarf2_frame_cfa (this_frame) - cache->entry_cfa_sp_offset; } else return NULL; @@ -380,15 +381,12 @@ /* Catch any unwinding errors. */ TRY_CATCH (except, RETURN_MASK_ERROR) { - int pc_regnum, sp_regnum; + int sp_regnum; prev_gdbarch = frame_unwind_arch (this_frame); - pc_regnum = gdbarch_pc_regnum (prev_gdbarch); - if (pc_regnum == -1) - break; /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ - prev_pc = frame_unwind_register_unsigned (this_frame, pc_regnum); + prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); /* call_site_find_chain can throw an exception. */ chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] 2011-10-19 16:05 ` Ulrich Weigand 2011-10-21 0:34 ` Jan Kratochvil @ 2011-10-21 0:45 ` Jan Kratochvil 1 sibling, 0 replies; 7+ messages in thread From: Jan Kratochvil @ 2011-10-21 0:45 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches Hello Ulrich, On Wed, 19 Oct 2011 17:51:45 +0200, Ulrich Weigand wrote: > Similarly, when injecting the tailcall PC values, you hook into the > prev_register routine struct frame_unwind has only the prev_register method. > -- which assumes that unwind_pc will end up > doing an unwind_register of pc_regnum. This assumptium would be > unnecessary if you just hooked into frame_unwind_pc directly instead. This way the tail call frames are implemented only in the specific DWARF unwinder. They do not need to be hooked into the generic unwinding code. There are now two phases - first phase, before dwarf2_tailcall_frame_unwind gets installed, the outer non-tailcall frame gets unwound. Then runs the second phase - with dwarf2_tailcall_frame_unwind installed. Only then the PC + SP registers simulation gets into effect. Moving this code somewhere outside of dwarf2_tailcall_frame_unwind seems incorrect to me. > Now as to SP, what happens is that you detect the rule for the CFA > at the entry point is > CFA = <sp_register> + <some_offset> > > Tailcall unwinding doesn't directly know the value of sp_register, but > it does know the CFA, so you hook into prev_register to return a value > of sp_register that is designed such that the above computation will > yield the desired CFA. > > However -- nothing in that design depends on the CFA being relative to > the SP register in particular. You could avoid this by detecting the > more general rule > CFA = <some_register> + <some_offset> > > and then remember both the register and the offset, and hook into > prev_register for whatever the register is -- no need at all to > enforce that this must be gdbarch_sp_regnum ... > > (You could then even generalize this to even more generic expressions > to compute the CFA, if necessary for certain platforms.) This depends on some chosen general approach and personal opinions IMO. The most logical way would be to use gdbarch-specific SP adjustment. Attaching below a proof of concept. It can then drop the whole CFI analysis from dwarf2-frame.c . The major disadvantage is it requires gdbarch specific code for each arch needing SP adjustment. Another problem is one IMO needs to create a new gdbarch method (or possibly a gdbarch value). One cannot reuse / extend gdbarch_unwind_sp as it has a chicken-and-egg problem with detecting whether we unwind into TAILCALL_FRAME. There would be needed some non-standard detection into which frame type the unwind is being made. It also violates the first / second phase separation. Therefore I originally chose the gdbarch-independent way with CFI analysis. But I find it possibly fragile. It is not such a concern if the SP adjustment fails. As it is only SP adjustment - not CFA adjustment - even if unwound SP is wrong still frame relative objects are relative to CFA (not SP) so it does not matter much. Moreover tailcall frames do not have any active frame objects. It is more a concern if the fragile CFI detection would mistakenly corrupt some arbitrary register by an inappropriate adjustment. This was the reason why I made the autodetection as strict as possible, without any flexibility outside of what was required for existing known gdbarches needing the SP adjustment. I do not have an idea on which gdbarch can the current detection fail (making itself inactive) and/or on which gdbarch your way could corrupt a register. I just followed some such design idea. Thanks, Jan Brief proof-of-concept for the gdbarch specific way: --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -2184,6 +2184,12 @@ amd64_gen_return_address (struct gdbarch *gdbarch, value->kind = axs_lvalue_memory; } \f +static CORE_ADDR +amd64_unwind_tailcall (struct gdbarch *gdbarch, struct frame_info *this_frame, + CORE_ADDR prev_sp) +{ + return prev_sp - 8; +} /* Signal trampolines. */ @@ -2690,6 +2696,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction); set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address); + + set_gdbarch_unwind_tailcall (gdbarch, amd64_unwind_tailcall); } /* Provide a prototype to silence -Wmissing-prototypes. */ --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -794,6 +794,13 @@ default_gen_return_address (struct gdbarch *gdbarch, error (_("This architecture has no method to collect a return address.")); } +CORE_ADDR +default_unwind_tailcall (struct gdbarch *gdbarch, struct frame_info *this_frame, + CORE_ADDR prev_sp) +{ + return prev_sp; +} + /* */ /* -Wmissing-prototypes */ --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -169,6 +169,10 @@ extern void default_gen_return_address (struct gdbarch *gdbarch, struct axs_value *value, CORE_ADDR scope); +extern CORE_ADDR default_unwind_tailcall (struct gdbarch *gdbarch, + struct frame_info *this_frame, + CORE_ADDR prev_sp); + extern const char *default_auto_charset (void); extern const char *default_auto_wide_charset (void); --- a/gdb/dwarf2-frame-tailcall.c +++ b/gdb/dwarf2-frame-tailcall.c @@ -56,13 +56,10 @@ struct tailcall_cache in CHAIN. */ CORE_ADDR prev_pc; - /* Compensate SP in caller frames appropriately. prev_sp and - entry_cfa_sp_offset are valid only if PREV_SP_P. PREV_SP is SP at the top - (caller) frame. ENTRY_CFA_SP_OFFSET is shift of SP in tail call frames - against next_bottom_frame SP. */ + /* Compensate SP in caller frames appropriately. prev_sp is valid iff + PREV_SP_P. PREV_SP is SP at the top (caller) frame. */ unsigned prev_sp_p : 1; CORE_ADDR prev_sp; - LONGEST entry_cfa_sp_offset; }; /* hash_f for htab_create_alloc of cache_htab. */ @@ -281,7 +278,8 @@ dwarf2_tailcall_prev_register_first (struct frame_info *this_frame, if (next_levels == cache->chain_levels - 1) addr = cache->prev_sp; else - addr = dwarf2_frame_cfa (this_frame) - cache->entry_cfa_sp_offset; + addr = gdbarch_unwind_tailcall (this_gdbarch, this_frame, + cache->prev_sp); } else return NULL; @@ -353,17 +351,11 @@ tailcall_frame_sniffer (const struct frame_unwind *self, /* The initial "sniffer" whether THIS_FRAME is a bottom (callee) frame of a new chain to create. Keep TAILCALL_CACHEP NULL if it did not find any chain, initialize it otherwise. No tail call chain is created if there are no - unambiguous virtual tail call frames to report. - - ENTRY_CFA_SP_OFFSETP is NULL if no special SP handling is possible, - otherwise *ENTRY_CFA_SP_OFFSETP is the number of bytes to subtract from tail - call frames frame base to get the SP value there - to simulate return - address pushed on the stack. */ + unambiguous virtual tail call frames to report. */ void dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, - void **tailcall_cachep, - const LONGEST *entry_cfa_sp_offsetp) + void **tailcall_cachep) { CORE_ADDR prev_pc = 0, prev_sp = 0; /* GCC warning. */ int prev_sp_p = 0; @@ -391,8 +383,6 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, /* call_site_find_chain can throw an exception. */ chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); - if (entry_cfa_sp_offsetp == NULL) - break; sp_regnum = gdbarch_sp_regnum (prev_gdbarch); if (sp_regnum == -1) break; @@ -420,10 +410,7 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, cache->chain_levels = pretended_chain_levels (chain); cache->prev_sp_p = prev_sp_p; if (cache->prev_sp_p) - { - cache->prev_sp = prev_sp; - cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp; - } + cache->prev_sp = prev_sp; gdb_assert (cache->chain_levels > 0); } --- a/gdb/dwarf2-frame-tailcall.h +++ b/gdb/dwarf2-frame-tailcall.h @@ -27,8 +27,7 @@ struct frame_unwind; extern void dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, - void **tailcall_cachep, - const LONGEST *entry_cfa_sp_offsetp); + void **tailcall_cachep); extern struct value * dwarf2_tailcall_prev_register_first (struct frame_info *this_frame, --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -400,11 +400,7 @@ Not implemented: computing unwound register using explicit value operator")); } \f -/* Execute FDE program from INSN_PTR possibly up to INSN_END or up to inferior - PC. Modify FS state accordingly. Return current INSN_PTR where the - execution has stopped, one can resume it on the next call. */ - -static const gdb_byte * +static void execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, const gdb_byte *insn_end, struct gdbarch *gdbarch, CORE_ADDR pc, struct dwarf2_frame_state *fs) @@ -687,14 +683,9 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"), } } - if (fs->initial.reg == NULL) - { - /* Don't allow remember/restore between CIE and FDE programs. */ - dwarf2_frame_state_free_regs (fs->regs.prev); - fs->regs.prev = NULL; - } - - return insn_ptr; + /* Don't allow remember/restore between CIE and FDE programs. */ + dwarf2_frame_state_free_regs (fs->regs.prev); + fs->regs.prev = NULL; } \f @@ -1007,8 +998,6 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) struct dwarf2_fde *fde; volatile struct gdb_exception ex; CORE_ADDR entry_pc; - LONGEST entry_cfa_sp_offset; - int entry_cfa_sp_offset_p = 0; const gdb_byte *instr; if (*this_cache) @@ -1061,25 +1050,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); - if (get_frame_func_if_available (this_frame, &entry_pc)) - { - /* Decode the insns in the FDE up to the entry PC. */ - instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, - entry_pc, fs); - - if (fs->regs.cfa_how == CFA_REG_OFFSET - && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg) - == gdbarch_sp_regnum (gdbarch))) - { - entry_cfa_sp_offset = fs->regs.cfa_offset; - entry_cfa_sp_offset_p = 1; - } - } - else - instr = fde->instructions; - /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde, instr, fde->end, gdbarch, + execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, get_frame_pc (this_frame), fs); TRY_CATCH (ex, RETURN_MASK_ERROR) @@ -1222,9 +1194,7 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"), /* Try to find a virtual tail call frames chain with bottom (callee) frame starting at THIS_FRAME. */ - dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache, - (entry_cfa_sp_offset_p - ? &entry_cfa_sp_offset : NULL)); + dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache); return cache; } --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -831,6 +831,10 @@ v:int:has_dos_based_file_system:::0:0::0 # places that the return address may be found. m:void:gen_return_address:struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope:ax, value, scope::default_gen_return_address::0 +# Simulate SP register for TAILCALL_FRAME. PREV_SP is the first previous +# non-tailcall frame. +m:CORE_ADDR:unwind_tailcall:struct frame_info *this_frame, CORE_ADDR prev_sp:this_frame, prev_sp::default_unwind_tailcall::0 + EOF } ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-10-21 0:34 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-10-13 1:55 New ARI warning Thu Oct 13 01:55:36 UTC 2011 GDB Administrator 2011-10-13 13:54 ` Jan Kratochvil 2011-10-13 15:00 ` Ulrich Weigand 2011-10-13 21:15 ` entryval tail call frames $sp adjustment vs. gdbarches [Re: New ARI warning Thu Oct 13 01:55:36 UTC 2011] Jan Kratochvil 2011-10-19 16:05 ` Ulrich Weigand 2011-10-21 0:34 ` Jan Kratochvil 2011-10-21 0:45 ` Jan Kratochvil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox