diff options
| -rw-r--r-- | tests/ChangeLog | 6 | ||||
| -rw-r--r-- | tests/backtrace-subr.sh | 14 | ||||
| -rw-r--r-- | tests/backtrace.c | 30 |
3 files changed, 38 insertions, 12 deletions
diff --git a/tests/ChangeLog b/tests/ChangeLog index 7040ac84..bca47be1 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,11 @@ 2017-02-09 Ulf Hermann <[email protected]> + * 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 <[email protected]> + * backtrace-data.c: Don't assert that symbols are found. The unwinder is allowed to ask for invalid addresses. We deny such requests, rather than make the test fail. diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh index 790b4f44..5d3937c2 100644 --- a/tests/backtrace-subr.sh +++ b/tests/backtrace-subr.sh @@ -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. diff --git a/tests/backtrace.c b/tests/backtrace.c index 1ff6353c..34a2ab0b 100644 --- a/tests/backtrace.c +++ b/tests/backtrace.c @@ -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[] = |
