diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-09-16 17:03:52 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-09-16 17:04:43 -0700 |
commit | 90c254565122fa5c02114698ce35ac46679c03b0 (patch) | |
tree | c893c6c0c0e87f702441fd7d31f57e522083aa22 | |
parent | fd111c419d146ee47c7df9a36a535e8d843d4802 (diff) | |
download | gcc-90c254565122fa5c02114698ce35ac46679c03b0.zip gcc-90c254565122fa5c02114698ce35ac46679c03b0.tar.gz gcc-90c254565122fa5c02114698ce35ac46679c03b0.tar.bz2 |
libbacktrace: use ELF symbol table if no debug info available
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.
-rw-r--r-- | libbacktrace/elf.c | 39 | ||||
-rw-r--r-- | libbacktrace/fileline.c | 27 | ||||
-rw-r--r-- | libbacktrace/internal.h | 25 | ||||
-rw-r--r-- | libbacktrace/mtest.c | 63 |
4 files changed, 115 insertions, 39 deletions
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index dd00470..941f820d 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 be62b98..cd1e10d 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 0986233..047a700 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 d90fd1e..d73c98d 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"); |