aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbacktrace/elf.c39
-rw-r--r--libbacktrace/fileline.c27
-rw-r--r--libbacktrace/internal.h25
-rw-r--r--libbacktrace/mtest.c63
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");