mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54: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:
parent
fd111c419d
commit
90c2545651
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *,
|
||||
|
@ -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)
|
||||
if (data.index > 1)
|
||||
{
|
||||
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[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)
|
||||
if (data.index > 2)
|
||||
{
|
||||
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;
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user