summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2012-11-20 16:14:23 +0100
committerJan Kratochvil <jan.kratochvil@redhat.com>2012-11-20 16:14:23 +0100
commitae270c0db975005b86213167dc8539254dce41d9 (patch)
tree84c1a8967146d2775930a40201f4943f2f796e73
parent3841068b5560f991c20e3c54b479ba4cc74c87ab (diff)
parent3d64327cf0d06cba090e9f734381ced18291c569 (diff)
downloadelfutils-ae270c0db975005b86213167dc8539254dce41d9.tar.gz
Merge branch 'jankratochvil/forunwind-baseaddr-hookvars-corereport-unwindx86-nonx86-fddebuginfo' into jankratochvil/forunwind-baseaddr-hookvars-corereport-unwindx86-nonx86-fddebuginfo-ports
-rw-r--r--backends/ppc64_init.c2
-rw-r--r--libdwfl/dwfl_frame_unwind.c58
-rwxr-xr-xtests/run-backtrace.sh54
3 files changed, 45 insertions, 69 deletions
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
index 32ca876e..8b3c9462 100644
--- a/backends/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -71,8 +71,6 @@ ppc64_init (elf, machine, eh, ehlen)
HOOK (eh, frame_state);
HOOK (eh, abi_cfi);
HOOK (eh, frame_dwarf_to_regno);
- HOOK (eh, get_func_pc);
- HOOK (eh, destr);
return MODVERSION;
}
diff --git a/libdwfl/dwfl_frame_unwind.c b/libdwfl/dwfl_frame_unwind.c
index e35ccb5d..c1a81b15 100644
--- a/libdwfl/dwfl_frame_unwind.c
+++ b/libdwfl/dwfl_frame_unwind.c
@@ -312,46 +312,6 @@ have_unwound (Dwfl_Frame_State **statep)
abort ();
}
-/* Check if PC is in the "_start" function which may have no FDE.
- It corresponds to the GDB get_prev_frame logic "inside entry func".
- Return TRUE if PC is in an outer frame. Return FALSE (and call
- __libdwfl_seterrno) otherwise. */
-
-static bool
-no_fde (Dwarf_Addr pc, Dwfl_Module *mod, Dwarf_Addr bias)
-{
- GElf_Sym sym;
- const char *symname = INTUSE(dwfl_module_addrsym) (mod, pc, &sym, NULL);
- if (symname == NULL)
- {
- __libdwfl_seterrno (DWFL_E_NO_DWARF);
- return false;
- }
- /* It has no FDE on PPC64; it can be still unwound via the stack frame. */
- if (strcmp (symname, ".generic_start_main") == 0)
- return true;
- GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
- if (ehdr == NULL)
- {
- __libdwfl_seterrno (DWFL_E_LIBELF);
- return false;
- }
- if (pc < ehdr->e_entry + bias)
- {
- __libdwfl_seterrno (DWFL_E_NO_DWARF);
- return false;
- }
- /* "_start" is size-less. Search for PC, if the closest symbol is the one
- for E_ENTRY it belongs into the function starting at E_ENTRY. */
- if (sym.st_value != ehdr->e_entry + bias
- || (sym.st_size != 0 && pc >= sym.st_value + sym.st_size))
- {
- __libdwfl_seterrno (DWFL_E_NO_DWARF);
- return false;
- }
- return true;
-}
-
/* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation
error so one can easily catch the problem with a debugger. Still there are
archs with invalid CFI for some registers where the registers are never used
@@ -362,22 +322,12 @@ no_fde (Dwarf_Addr pc, Dwfl_Module *mod, Dwarf_Addr bias)
an undefined PC register (due to an error unwinding it). */
static bool
-handle_cfi (Dwfl_Frame_State **statep, Dwarf_Addr pc, Dwfl_Module *mod,
- Dwarf_CFI *cfi, Dwarf_Addr bias)
+handle_cfi (Dwfl_Frame_State **statep, Dwarf_Addr pc, Dwarf_CFI *cfi)
{
Dwfl_Frame_State *state = *statep;
Dwarf_Frame *frame;
- if (INTUSE(dwarf_cfi_addrframe) (cfi, pc - bias, &frame) != 0)
+ if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0)
{
- int dw_errno = dwarf_errno ();
- if (dw_errno == DWARF_E_NO_MATCH)
- {
- if (! no_fde (pc, mod, bias))
- return false;
- *statep = NULL;
- return true;
- }
- __libdw_seterrno (dw_errno);
__libdwfl_seterrno (DWFL_E_LIBDW);
return false;
}
@@ -474,7 +424,7 @@ dwfl_frame_unwind (Dwfl_Frame_State **statep)
Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias);
if (cfi_eh)
{
- if (handle_cfi (statep, pc, mod, cfi_eh, bias))
+ if (handle_cfi (statep, pc - bias, cfi_eh))
return true;
if (state->unwound)
{
@@ -485,7 +435,7 @@ dwfl_frame_unwind (Dwfl_Frame_State **statep)
Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias);
if (cfi_dwarf)
{
- if (handle_cfi (statep, pc, mod, cfi_dwarf, bias) && state->unwound)
+ if (handle_cfi (statep, pc - bias, cfi_dwarf) && state->unwound)
return true;
if (state->unwound)
{
diff --git a/tests/run-backtrace.sh b/tests/run-backtrace.sh
index a57d4744..0d1e7370 100755
--- a/tests/run-backtrace.sh
+++ b/tests/run-backtrace.sh
@@ -27,41 +27,69 @@ mytestrun()
testrun "$@"
}
+check_main()
+{
+ if grep -w main $1; then
+ return
+ fi
+ cat >&2 $1
+ echo >&2 $2: no main
+ false
+}
+
check_gsignal()
{
# Without proper ELF symbols resolution we could get inappropriate weak
# symbol "gsignal" with the same address as the correct symbol "raise".
- if grep -w gsignal $1; then
- false
+ if ! grep -w gsignal $1; then
+ return
fi
+ cat >&2 $1
+ echo >&2 $2: found gsignal
+ false
}
-check_empty()
+check_err()
{
- if test -s $1; then
- false
+ if test ! -s $1; then
+ return
+ fi
+ # In some cases we cannot reliably find out we got behind _start.
+ if echo "No DWARF information found" | cmp -s - $1; then
+ return
fi
+ cat >&2 $1
+ echo >&2 $2: neither empty nor just out of DWARF
}
for child in backtrace-child{,-biarch}; do
- mytestrun ./backtrace ./$child
+ tempfiles $child{.bt,err}
+ ./backtrace ./$child 1>$child.bt 2>$child.err \
+ || true
+ check_main $child.bt $child
+ check_gsignal $child.bt $child
+ check_err $child.err $child
core="core.`ulimit -c unlimited; set +e; ./$child --gencore --run; true`"
tempfiles $core{,.bt,.err}
- mytestrun ./backtrace ./$child ./$core 1>$core.bt 2>$core.err
+ ./backtrace ./$child ./$core 1>$core.bt 2>$core.err \
+ || true
cat $core.{bt,err}
- check_gsignal $core.bt
- check_empty $core.err
+ check_main $core.bt $child-$core
+ check_gsignal $core.bt $child-$core
+ check_err $core.err $child-$core
done
for arch in ppc ppc64 s390 s390x; do
testfiles backtrace.$arch.{exec,core}
tempfiles backtrace.$arch.{bt,err}
echo ./backtrace ./backtrace.$arch.{exec,core}
- mytestrun ./backtrace ./backtrace.$arch.{exec,core} 1>backtrace.$arch.bt \
- 2>backtrace.$arch.err
+ ./backtrace ./backtrace.$arch.{exec,core} 1>backtrace.$arch.bt \
+ 2>backtrace.$arch.err \
+ || true
cat backtrace.$arch.{bt,err}
- check_gsignal backtrace.$arch.bt
- check_empty backtrace.$arch.err
+ check_main backtrace.$arch.bt $arch
+ check_gsignal backtrace.$arch.bt $arch
+ check_err backtrace.$arch.err $arch
done
exit 0