]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Drop no_fde, it is too slow without much benefits.
authorroot <jan.kratochvil@redhat.com>
Tue, 20 Nov 2012 15:04:05 +0000 (16:04 +0100)
committerroot <jan.kratochvil@redhat.com>
Tue, 20 Nov 2012 15:04:05 +0000 (16:04 +0100)
libdwfl/dwfl_frame_unwind.c
tests/run-backtrace.sh

index 5705f515a04a4d4c560d7b38999eb454bf0a9a38..d329b35ec51d371e786f67bd352d3697969a6ffc 100644 (file)
@@ -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)
            {
index 6e146531e127a360455b518755c73a0bafd74746..2890b188e1610f1ab2fd54b9d04c3ae1846ea2f0 100755 (executable)
@@ -27,30 +27,56 @@ 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
 
 exit 0