diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2015-06-01 14:02:34 +0200 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2015-06-01 14:02:34 +0200 |
commit | e0619de699ae6e86d8b93fa96a7668aef2e9636a (patch) | |
tree | dd75616a50cb569a8592870ce89e36938e5a597f /gdb/dwarf2loc.c | |
parent | bd16da5114e2f04772bf05604a608fbe006a485a (diff) | |
download | gdb-e0619de699ae6e86d8b93fa96a7668aef2e9636a.zip gdb-e0619de699ae6e86d8b93fa96a7668aef2e9636a.tar.gz gdb-e0619de699ae6e86d8b93fa96a7668aef2e9636a.tar.bz2 |
PR symtab/18392
Initially there is some chain (let's say the longest one
but that doe snot matter). Consequently its elements from the middle are
being removed and there remains only some few unambiguous top and bottom ones.
The original idea why the comparison should be sharp ("<") was that if there
are multiple chains like (0xaddr show jmp instruction address):
main(0x100) -> a(0x200) -> d(0x400)
main(0x100) -> a(0x200) -> c(0x300) -> d(0x400)
then - such situation cannot exist - if two jmp instructions in "a" have the
same address they must also jump to the same address (*).
(*) jump to a computed address would be never considered for the DWARF
tail-call records.
So there could be:
main(0x100) -> a(0x200) -> d(0x400)
main(0x100) -> a(0x270) -> c(0x300) -> d(0x400)
But then "a" frame itself is ambiguous and it must not be displayed.
I did not realize that there can be self-tail-call:
main(0x100) -> a(0x200) -> d(0x400)
main(0x100) -> a(0x280) -> a(0x200) -> d(0x400)
which intersects to:
main(0x100) -> <???>? -> a(0x200) -> d(0x400)
And so if the first chain was chosen the
main(0x100) -> a(0x200) -> d(0x400)
then the final intersection has callers+callees==length.
> for example, if CALLERS is 3 and
> CALLEES is 2, what does the chain look like?
main(0x100) -> x(0x150) -> y(0x200) -> <???>? -> a(0x200) -> d(0x400)
And if LENGTH is 7 then:
call_site[0] = main(0x100)
call_site[1] = x(0x150)
call_site[2] = y(0x200)
call_site[3] = garbage
call_site[4] = garbage
call_site[5] = a(0x200)
call_site[6] = d(0x400)
gdb/ChangeLog
2015-06-01 Andreas Schwab <schwab@linux-m68k.org>
Jan Kratochvil <jan.kratochvil@redhat.com>
PR symtab/18392
* dwarf2-frame-tailcall.c (pretended_chain_levels): Correct
assertion.
* dwarf2loc.c (chain_candidate): Likewise.
gdb/testsuite/ChangeLog
2015-06-01 Jan Kratochvil <jan.kratochvil@redhat.com>
PR symtab/18392
* gdb.arch/amd64-tailcall-self.S: New file.
* gdb.arch/amd64-tailcall-self.c: New file.
* gdb.arch/amd64-tailcall-self.exp: New file.
Diffstat (limited to 'gdb/dwarf2loc.c')
-rw-r--r-- | gdb/dwarf2loc.c | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 3aa8ddd..c75767e 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -825,9 +825,8 @@ chain_candidate (struct gdbarch *gdbarch, struct call_site_chain **resultp, /* See call_site_find_chain_1 why there is no way to reach the bottom callee PC again. In such case there must be two different code paths to reach - it, therefore some of the former determined intermediate PCs must differ - and the unambiguous chain gets shortened. */ - gdb_assert (result->callers + result->callees < result->length); + it. CALLERS + CALLEES equal to LENGTH in the case of self tail-call. */ + gdb_assert (result->callers + result->callees <= result->length); } /* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the |