Skip to content

Commit c8a81d4

Browse files
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.
1 parent 753968c commit c8a81d4

File tree

4 files changed

+115
-39
lines changed

4 files changed

+115
-39
lines changed

elf.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -547,18 +547,6 @@ elf_crc32_file (struct backtrace_state *state, int descriptor,
547547
return ret;
548548
}
549549

550-
/* A dummy callback function used when we can't find any debug info. */
551-
552-
static int
553-
elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
554-
uintptr_t pc ATTRIBUTE_UNUSED,
555-
backtrace_full_callback callback ATTRIBUTE_UNUSED,
556-
backtrace_error_callback error_callback, void *data)
557-
{
558-
error_callback (data, "no debug info in ELF executable", -1);
559-
return 0;
560-
}
561-
562550
/* A dummy callback function used when we can't find a symbol
563551
table. */
564552

@@ -571,6 +559,33 @@ elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
571559
error_callback (data, "no symbol table in ELF executable", -1);
572560
}
573561

562+
/* A callback function used when we can't find any debug info. */
563+
564+
static int
565+
elf_nodebug (struct backtrace_state *state, uintptr_t pc,
566+
backtrace_full_callback callback,
567+
backtrace_error_callback error_callback, void *data)
568+
{
569+
if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms)
570+
{
571+
struct backtrace_call_full bdata;
572+
573+
/* Fetch symbol information so that we can least get the
574+
function name. */
575+
576+
bdata.full_callback = callback;
577+
bdata.full_error_callback = error_callback;
578+
bdata.full_data = data;
579+
bdata.ret = 0;
580+
state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback,
581+
backtrace_syminfo_to_full_error_callback, &bdata);
582+
return bdata.ret;
583+
}
584+
585+
error_callback (data, "no debug info in ELF executable", -1);
586+
return 0;
587+
}
588+
574589
/* Compare struct elf_symbol for qsort. */
575590

576591
static int

fileline.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,30 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
317317
state->syminfo_fn (state, pc, callback, error_callback, data);
318318
return 1;
319319
}
320+
321+
/* A backtrace_syminfo_callback that can call into a
322+
backtrace_full_callback, used when we have a symbol table but no
323+
debug info. */
324+
325+
void
326+
backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
327+
const char *symname,
328+
uintptr_t symval ATTRIBUTE_UNUSED,
329+
uintptr_t symsize ATTRIBUTE_UNUSED)
330+
{
331+
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
332+
333+
bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);
334+
}
335+
336+
/* An error callback that corresponds to
337+
backtrace_syminfo_to_full_callback. */
338+
339+
void
340+
backtrace_syminfo_to_full_error_callback (void *data, const char *msg,
341+
int errnum)
342+
{
343+
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
344+
345+
bdata->full_error_callback (bdata->full_data, msg, errnum);
346+
}

internal.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,31 @@ extern int backtrace_dwarf_add (struct backtrace_state *state,
326326
void *data, fileline *fileline_fn,
327327
struct dwarf_data **fileline_entry);
328328

329+
/* A data structure to pass to backtrace_syminfo_to_full. */
330+
331+
struct backtrace_call_full
332+
{
333+
backtrace_full_callback full_callback;
334+
backtrace_error_callback full_error_callback;
335+
void *full_data;
336+
int ret;
337+
};
338+
339+
/* A backtrace_syminfo_callback that can call into a
340+
backtrace_full_callback, used when we have a symbol table but no
341+
debug info. */
342+
343+
extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
344+
const char *symname,
345+
uintptr_t symval,
346+
uintptr_t symsize);
347+
348+
/* An error callback that corresponds to
349+
backtrace_syminfo_to_full_callback. */
350+
351+
extern void backtrace_syminfo_to_full_error_callback (void *, const char *,
352+
int);
353+
329354
/* A test-only hook for elf_uncompress_zdebug. */
330355

331356
extern int backtrace_uncompress_zdebug (struct backtrace_state *,

mtest.c

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -156,40 +156,49 @@ f3 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))
156156
}
157157
}
158158

159-
if (all[0].function == NULL)
159+
if (data.index > 0)
160160
{
161-
fprintf (stderr, "test1: [0]: missing function name\n");
162-
data.failed = 1;
163-
}
164-
else if (strcmp (all[0].function, "f3") != 0)
165-
{
166-
fprintf (stderr, "test1: [0]: got %s expected %s\n",
167-
all[0].function, "f3");
168-
data.failed = 1;
161+
if (all[0].function == NULL)
162+
{
163+
fprintf (stderr, "test1: [0]: missing function name\n");
164+
data.failed = 1;
165+
}
166+
else if (strcmp (all[0].function, "f3") != 0)
167+
{
168+
fprintf (stderr, "test1: [0]: got %s expected %s\n",
169+
all[0].function, "f3");
170+
data.failed = 1;
171+
}
169172
}
170173

171-
if (all[1].function == NULL)
172-
{
173-
fprintf (stderr, "test1: [1]: missing function name\n");
174-
data.failed = 1;
175-
}
176-
else if (strcmp (all[1].function, "f2") != 0)
174+
if (data.index > 1)
177175
{
178-
fprintf (stderr, "test1: [1]: got %s expected %s\n",
179-
all[0].function, "f2");
180-
data.failed = 1;
176+
if (all[1].function == NULL)
177+
{
178+
fprintf (stderr, "test1: [1]: missing function name\n");
179+
data.failed = 1;
180+
}
181+
else if (strcmp (all[1].function, "f2") != 0)
182+
{
183+
fprintf (stderr, "test1: [1]: got %s expected %s\n",
184+
all[0].function, "f2");
185+
data.failed = 1;
186+
}
181187
}
182188

183-
if (all[2].function == NULL)
184-
{
185-
fprintf (stderr, "test1: [2]: missing function name\n");
186-
data.failed = 1;
187-
}
188-
else if (strcmp (all[2].function, "test1") != 0)
189+
if (data.index > 2)
189190
{
190-
fprintf (stderr, "test1: [2]: got %s expected %s\n",
191-
all[0].function, "test1");
192-
data.failed = 1;
191+
if (all[2].function == NULL)
192+
{
193+
fprintf (stderr, "test1: [2]: missing function name\n");
194+
data.failed = 1;
195+
}
196+
else if (strcmp (all[2].function, "test1") != 0)
197+
{
198+
fprintf (stderr, "test1: [2]: got %s expected %s\n",
199+
all[0].function, "test1");
200+
data.failed = 1;
201+
}
193202
}
194203

195204
printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");

0 commit comments

Comments
 (0)