* 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