mirror of
https://github.com/ianlancetaylor/libbacktrace.git
synced 2026-03-30 14:09:07 +08:00
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.
This commit is contained in:
39
elf.c
39
elf.c
@@ -547,18 +547,6 @@ elf_crc32_file (struct backtrace_state *state, int descriptor,
|
|||||||
return ret;
|
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
|
/* A dummy callback function used when we can't find a symbol
|
||||||
table. */
|
table. */
|
||||||
|
|
||||||
@@ -571,6 +559,33 @@ elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
|||||||
error_callback (data, "no symbol table in ELF executable", -1);
|
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. */
|
/* Compare struct elf_symbol for qsort. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
27
fileline.c
27
fileline.c
@@ -317,3 +317,30 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
|
|||||||
state->syminfo_fn (state, pc, callback, error_callback, data);
|
state->syminfo_fn (state, pc, callback, error_callback, data);
|
||||||
return 1;
|
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);
|
||||||
|
}
|
||||||
|
|||||||
25
internal.h
25
internal.h
@@ -326,6 +326,31 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
|
|||||||
void *data, fileline *fileline_fn,
|
void *data, fileline *fileline_fn,
|
||||||
struct dwarf_data **fileline_entry);
|
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. */
|
/* A test-only hook for elf_uncompress_zdebug. */
|
||||||
|
|
||||||
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
extern int backtrace_uncompress_zdebug (struct backtrace_state *,
|
||||||
|
|||||||
63
mtest.c
63
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");
|
if (all[0].function == NULL)
|
||||||
data.failed = 1;
|
{
|
||||||
}
|
fprintf (stderr, "test1: [0]: missing function name\n");
|
||||||
else if (strcmp (all[0].function, "f3") != 0)
|
data.failed = 1;
|
||||||
{
|
}
|
||||||
fprintf (stderr, "test1: [0]: got %s expected %s\n",
|
else if (strcmp (all[0].function, "f3") != 0)
|
||||||
all[0].function, "f3");
|
{
|
||||||
data.failed = 1;
|
fprintf (stderr, "test1: [0]: got %s expected %s\n",
|
||||||
|
all[0].function, "f3");
|
||||||
|
data.failed = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all[1].function == NULL)
|
if (data.index > 1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "test1: [1]: missing function name\n");
|
if (all[1].function == NULL)
|
||||||
data.failed = 1;
|
{
|
||||||
}
|
fprintf (stderr, "test1: [1]: missing function name\n");
|
||||||
else if (strcmp (all[1].function, "f2") != 0)
|
data.failed = 1;
|
||||||
{
|
}
|
||||||
fprintf (stderr, "test1: [1]: got %s expected %s\n",
|
else if (strcmp (all[1].function, "f2") != 0)
|
||||||
all[0].function, "f2");
|
{
|
||||||
data.failed = 1;
|
fprintf (stderr, "test1: [1]: got %s expected %s\n",
|
||||||
|
all[0].function, "f2");
|
||||||
|
data.failed = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all[2].function == NULL)
|
if (data.index > 2)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "test1: [2]: missing function name\n");
|
if (all[2].function == NULL)
|
||||||
data.failed = 1;
|
{
|
||||||
}
|
fprintf (stderr, "test1: [2]: missing function name\n");
|
||||||
else if (strcmp (all[2].function, "test1") != 0)
|
data.failed = 1;
|
||||||
{
|
}
|
||||||
fprintf (stderr, "test1: [2]: got %s expected %s\n",
|
else if (strcmp (all[2].function, "test1") != 0)
|
||||||
all[0].function, "test1");
|
{
|
||||||
data.failed = 1;
|
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");
|
printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
|
||||||
|
|||||||
Reference in New Issue
Block a user