On Wed, Sep 16, 2020 at 8:54 AM Alex Coplan <alex.cop...@arm.com> wrote: > > On 16/09/2020 07:26, Ian Lance Taylor wrote: > > On Wed, Sep 16, 2020, 4:03 AM Alex Coplan <alex.cop...@arm.com> wrote: > > > > > Hi Ian, > > > > > > On 14/09/2020 14:12, Ian Lance Taylor via Gcc-patches wrote: > > > > This patch to libbacktrace adds support for MiniDebugInfo, as > > > > requested in PR 93608. > > > > > > This appears to introduce a failure in the libbacktrace testsuite > > > (observed on both x86 and aarch64): > > > > > > ../gcc/libbacktrace/../test-driver: line 107: 7905 Segmentation fault > > > (core dumped) "$@" > $log_file 2>&1 > > > FAIL: mtest_minidebug > > > > > > > > I tested on x86 without seeing anything like this. Can you give me any > > more details? Thanks. > > Sure. On an Ubuntu 18.04 / x86-64 system with current trunk, configuring > with: > > ~/toolchain/src/gcc/configure \ > --prefix=`pwd` \ > --enable-languages=c,c++ \ > --disable-multilib \ > --disable-bootstrap > > running `make && make check-libbacktrace` gives the failure described > above. Here is the contents of libbacktrace/test-suite.log: > > ===================================================== > package-unused version-unused: ./test-suite.log > ===================================================== > > # TOTAL: 33 > # PASS: 32 > # SKIP: 0 > # XFAIL: 0 > # FAIL: 1 > # XPASS: 0 > # ERROR: 0 > > .. contents:: :depth: 2 > > FAIL: mtest_minidebug > ===================== > > no debug info in ELF executable > no debug info in ELF executable > no debug info in ELF executable > no debug info in ELF executable > no debug info in ELF executable > no debug info in ELF executable > no debug info in ELF executable > test1: not enough frames; got 0, expected at least 3 > test1: [0]: got expected f3 > test1: [1]: got expected f2 > FAIL mtest_minidebug (exit status: 139) > > --- > > Let me know if you need any more info.
Thanks. I think the problem arises when libbacktrace is unable to find debug info for any shared library involved in the link. This patch should fix it. Bootstrapped and ran libbacktrace tests on x86_64-pc-linux-gnu and aarch64-linux-gnu. Committed to mainline. Ian PR libbacktrace/97080 * fileline.c (backtrace_syminfo_to_full_callback): New function. (backtrace_syminfo_to_full_error_callback): New function. * elf.c (elf_nodebug): Call syminfo_fn if possible. * internal.h (struct backtrace_call_full): Define. (backtrace_syminfo_to_full_callback): Declare. (backtrace_syminfo_to_full_error_callback): Declare. * mtest.c (f3): Only check all[i] if data.index permits.
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index dd004708246..941f820d944 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -547,18 +547,6 @@ elf_crc32_file (struct backtrace_state *state, int descriptor, return ret; } -/* A dummy callback function used when we can't find any debug info. */ - -static int -elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, - uintptr_t pc ATTRIBUTE_UNUSED, - backtrace_full_callback callback ATTRIBUTE_UNUSED, - backtrace_error_callback error_callback, void *data) -{ - error_callback (data, "no debug info in ELF executable", -1); - return 0; -} - /* A dummy callback function used when we can't find a symbol table. */ @@ -571,6 +559,33 @@ elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, error_callback (data, "no symbol table in ELF executable", -1); } +/* A callback function used when we can't find any debug info. */ + +static int +elf_nodebug (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data) +{ + if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms) + { + struct backtrace_call_full bdata; + + /* Fetch symbol information so that we can least get the + function name. */ + + bdata.full_callback = callback; + bdata.full_error_callback = error_callback; + bdata.full_data = data; + bdata.ret = 0; + state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback, + backtrace_syminfo_to_full_error_callback, &bdata); + return bdata.ret; + } + + error_callback (data, "no debug info in ELF executable", -1); + return 0; +} + /* Compare struct elf_symbol for qsort. */ static int diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index be62b9899c5..cd1e10dd58c 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -317,3 +317,30 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc, state->syminfo_fn (state, pc, callback, error_callback, data); return 1; } + +/* A backtrace_syminfo_callback that can call into a + backtrace_full_callback, used when we have a symbol table but no + debug info. */ + +void +backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval ATTRIBUTE_UNUSED, + uintptr_t symsize ATTRIBUTE_UNUSED) +{ + struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; + + bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname); +} + +/* An error callback that corresponds to + backtrace_syminfo_to_full_callback. */ + +void +backtrace_syminfo_to_full_error_callback (void *data, const char *msg, + int errnum) +{ + struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; + + bdata->full_error_callback (bdata->full_data, msg, errnum); +} diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h index 09862337456..047a700c0ce 100644 --- a/libbacktrace/internal.h +++ b/libbacktrace/internal.h @@ -326,6 +326,31 @@ extern int backtrace_dwarf_add (struct backtrace_state *state, void *data, fileline *fileline_fn, struct dwarf_data **fileline_entry); +/* A data structure to pass to backtrace_syminfo_to_full. */ + +struct backtrace_call_full +{ + backtrace_full_callback full_callback; + backtrace_error_callback full_error_callback; + void *full_data; + int ret; +}; + +/* A backtrace_syminfo_callback that can call into a + backtrace_full_callback, used when we have a symbol table but no + debug info. */ + +extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval, + uintptr_t symsize); + +/* An error callback that corresponds to + backtrace_syminfo_to_full_callback. */ + +extern void backtrace_syminfo_to_full_error_callback (void *, const char *, + int); + /* A test-only hook for elf_uncompress_zdebug. */ extern int backtrace_uncompress_zdebug (struct backtrace_state *, diff --git a/libbacktrace/mtest.c b/libbacktrace/mtest.c index d90fd1e33cc..d73c98d44f8 100644 --- a/libbacktrace/mtest.c +++ b/libbacktrace/mtest.c @@ -156,40 +156,49 @@ f3 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused))) } } - if (all[0].function == NULL) + if (data.index > 0) { - fprintf (stderr, "test1: [0]: missing function name\n"); - data.failed = 1; - } - else if (strcmp (all[0].function, "f3") != 0) - { - fprintf (stderr, "test1: [0]: got %s expected %s\n", - all[0].function, "f3"); - data.failed = 1; + if (all[0].function == NULL) + { + fprintf (stderr, "test1: [0]: missing function name\n"); + data.failed = 1; + } + else if (strcmp (all[0].function, "f3") != 0) + { + fprintf (stderr, "test1: [0]: got %s expected %s\n", + all[0].function, "f3"); + data.failed = 1; + } } - if (all[1].function == NULL) - { - fprintf (stderr, "test1: [1]: missing function name\n"); - data.failed = 1; - } - else if (strcmp (all[1].function, "f2") != 0) + if (data.index > 1) { - fprintf (stderr, "test1: [1]: got %s expected %s\n", - all[0].function, "f2"); - data.failed = 1; + if (all[1].function == NULL) + { + fprintf (stderr, "test1: [1]: missing function name\n"); + data.failed = 1; + } + else if (strcmp (all[1].function, "f2") != 0) + { + fprintf (stderr, "test1: [1]: got %s expected %s\n", + all[0].function, "f2"); + data.failed = 1; + } } - if (all[2].function == NULL) - { - fprintf (stderr, "test1: [2]: missing function name\n"); - data.failed = 1; - } - else if (strcmp (all[2].function, "test1") != 0) + if (data.index > 2) { - fprintf (stderr, "test1: [2]: got %s expected %s\n", - all[0].function, "test1"); - data.failed = 1; + if (all[2].function == NULL) + { + fprintf (stderr, "test1: [2]: missing function name\n"); + data.failed = 1; + } + else if (strcmp (all[2].function, "test1") != 0) + { + fprintf (stderr, "test1: [2]: got %s expected %s\n", + all[0].function, "test1"); + data.failed = 1; + } } printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");