]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Optionally allow unknown symbols in the backtrace tests
authorUlf Hermann <ulf.hermann@qt.io>
Fri, 10 Feb 2017 14:19:40 +0000 (15:19 +0100)
committerMark Wielaard <mark@klomp.org>
Tue, 14 Feb 2017 09:24:36 +0000 (10:24 +0100)
This is useful to test unwinding without debug information. The
binaries being examined might still have frame pointers that allow
us to bridge the unknown symbols.

Signed-off-by: Ulf Hermann <ulf.hermann@qt.io>
tests/ChangeLog
tests/backtrace-subr.sh
tests/backtrace.c

index 7040ac843446c6c21e0017cf46ec7f82d5ec8704..bca47be15c1a9d1f1ea3d0f8a684ea88afdf345a 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+       * backtrace.c: Add an option to allow unknown symbols in the trace
+       * backtrace-substr.sh: Add an option to allow unknown symbols
+       to check_core() and allow failed symbol lookups in check_err()
+
 2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
 
        * backtrace-data.c: Don't assert that symbols are found.
index 790b4f4459bff523093ad9d99297e616593fcbea..5d3937c2ff4a2c4c7935af51b8a6a5aafd595c4d 100644 (file)
@@ -44,9 +44,12 @@ check_gsignal()
 # In some cases we cannot reliably find out we got behind _start as some
 # operating system do not properly terminate CFI by undefined PC.
 # Ignore it here as it is a bug of OS, not a bug of elfutils.
+# If the CFI is not terminated correctly, we might find another frame by
+# checking for frame pointers. This is still not our problem, but only
+# gives an error message when trying to look up the function name.
 check_err()
 {
-  if [ $(egrep -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range)$' \
+  if [ $(egrep -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range|address out of range)$' \
          | wc -c) \
        -eq 0 ]
   then
@@ -61,7 +64,9 @@ check_all()
   bt=$1
   err=$2
   testname=$3
-  check_main $bt $testname
+  if [ "x$4" != "x--allow-unknown" ]; then
+    check_main $bt $testname
+  fi
   check_gsignal $bt $testname
   check_err $err $testname
 }
@@ -98,13 +103,14 @@ check_native_unsupported()
 check_core()
 {
   arch=$1
+  args=$2
   testfiles backtrace.$arch.{exec,core}
   tempfiles backtrace.$arch.{bt,err}
   echo ./backtrace ./backtrace.$arch.{exec,core}
-  testrun ${abs_builddir}/backtrace -e ./backtrace.$arch.exec --core=./backtrace.$arch.core 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
+  testrun ${abs_builddir}/backtrace $args -e ./backtrace.$arch.exec --core=./backtrace.$arch.core 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
   cat backtrace.$arch.{bt,err}
   check_unsupported backtrace.$arch.err backtrace.$arch.core
-  check_all backtrace.$arch.{bt,err} backtrace.$arch.core
+  check_all backtrace.$arch.{bt,err} backtrace.$arch.core $args
 }
 
 # Backtrace live process.
index 1ff6353c2d6f1fa595ad835ff71527d03e613df7..34a2ab0be9bc2b54a0198b217955107bd0c07b92 100644 (file)
@@ -64,6 +64,7 @@ dump_modules (Dwfl_Module *mod, void **userdata __attribute__ ((unused)),
   return DWARF_CB_OK;
 }
 
+static bool allow_unknown;
 static bool use_raise_jmp_patching;
 static pid_t check_tid;
 
@@ -78,7 +79,8 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
     seen_main = true;
   if (pc == 0)
     {
-      assert (seen_main);
+      if (!allow_unknown)
+        assert (seen_main);
       return;
     }
   if (check_tid == 0)
@@ -103,11 +105,12 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
               && (strcmp (symname, "__kernel_vsyscall") == 0
                   || strcmp (symname, "__libc_do_syscall") == 0))
        reduce_frameno = true;
-      else
+      else if (!allow_unknown || symname)
        assert (symname && strcmp (symname, "raise") == 0);
       break;
     case 1:
-      assert (symname != NULL && strcmp (symname, "sigusr2") == 0);
+      if (!allow_unknown || symname)
+        assert (symname != NULL && strcmp (symname, "sigusr2") == 0);
       break;
     case 2: // x86_64 only
       /* __restore_rt - glibc maybe does not have to have this symbol.  */
@@ -116,20 +119,24 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
       if (use_raise_jmp_patching)
        {
          /* Verify we trapped on the very first instruction of jmp.  */
-         assert (symname != NULL && strcmp (symname, "jmp") == 0);
+          if (!allow_unknown || symname)
+            assert (symname != NULL && strcmp (symname, "jmp") == 0);
          mod = dwfl_addrmodule (dwfl, pc - 1);
          if (mod)
            symname2 = dwfl_module_addrname (mod, pc - 1);
-         assert (symname2 == NULL || strcmp (symname2, "jmp") != 0);
+          if (!allow_unknown || symname2)
+            assert (symname2 == NULL || strcmp (symname2, "jmp") != 0);
          break;
        }
       /* FALLTHRU */
     case 4:
-      assert (symname != NULL && strcmp (symname, "stdarg") == 0);
+      if (!allow_unknown || symname)
+        assert (symname != NULL && strcmp (symname, "stdarg") == 0);
       break;
     case 5:
       /* Verify we trapped on the very last instruction of child.  */
-      assert (symname != NULL && strcmp (symname, "backtracegen") == 0);
+      if (!allow_unknown || symname)
+        assert (symname != NULL && strcmp (symname, "backtracegen") == 0);
       mod = dwfl_addrmodule (dwfl, pc);
       if (mod)
        symname2 = dwfl_module_addrname (mod, pc);
@@ -138,7 +145,7 @@ callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
       // there is no guarantee that the compiler doesn't reorder the
       // instructions or even inserts some padding instructions at the end
       // (which apparently happens on ppc64).
-      if (use_raise_jmp_patching)
+      if (use_raise_jmp_patching && (!allow_unknown || symname2))
         assert (symname2 == NULL || strcmp (symname2, "backtracegen") != 0);
       break;
   }
@@ -424,10 +431,12 @@ exec_dump (const char *exec)
 }
 
 #define OPT_BACKTRACE_EXEC 0x100
+#define OPT_ALLOW_UNKNOWN 0x200
 
 static const struct argp_option options[] =
   {
     { "backtrace-exec", OPT_BACKTRACE_EXEC, "EXEC", 0, N_("Run executable"), 0 },
+    { "allow-unknown", OPT_ALLOW_UNKNOWN, 0, 0, N_("Allow unknown symbols"), 0 },
     { NULL, 0, NULL, 0, NULL, 0 }
   };
 
@@ -445,6 +454,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       exec_dump (arg);
       exit (0);
 
+    case OPT_ALLOW_UNKNOWN:
+      allow_unknown = true;
+      break;
+
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -463,6 +476,7 @@ main (int argc __attribute__ ((unused)), char **argv)
   (void) setlocale (LC_ALL, "");
 
   elf_version (EV_CURRENT);
+  allow_unknown = false;
 
   Dwfl *dwfl = NULL;
   const struct argp_child argp_children[] =