[K/N] Patch libbacktrace for columns support

This commit is contained in:
Pavel Kunyavskiy
2021-08-06 18:23:31 +03:00
committed by Space
parent 91dd9dc9b0
commit 45317ca221
5 changed files with 36 additions and 21 deletions
@@ -86,7 +86,7 @@ unwind (struct _Unwind_Context *context, void *vdata)
--pc; --pc;
if (!bdata->can_alloc) if (!bdata->can_alloc)
bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL); bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, 0, NULL);
else else
bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
bdata->error_callback, bdata->data); bdata->error_callback, bdata->data);
@@ -567,6 +567,8 @@ struct line
const char *filename; const char *filename;
/* Line number. */ /* Line number. */
int lineno; int lineno;
/* Column number */
int column;
/* Index of the object in the original array read from the DWARF /* Index of the object in the original array read from the DWARF
section, before it has been sorted. The index makes it possible section, before it has been sorted. The index makes it possible
to use Quicksort and maintain stability. */ to use Quicksort and maintain stability. */
@@ -596,6 +598,9 @@ struct function
/* If this is an inlined function, the line number of the call /* If this is an inlined function, the line number of the call
site. */ site. */
int caller_lineno; int caller_lineno;
/* If this is an inlined function, the column of the call
site. */
int caller_column;
/* Map PC ranges to inlined functions. */ /* Map PC ranges to inlined functions. */
struct function_addrs *function_addrs; struct function_addrs *function_addrs;
size_t function_addrs_count; size_t function_addrs_count;
@@ -2611,7 +2616,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
static int static int
add_line (struct backtrace_state *state, struct dwarf_data *ddata, add_line (struct backtrace_state *state, struct dwarf_data *ddata,
uintptr_t pc, const char *filename, int lineno, uintptr_t pc, const char *filename, int lineno, int column,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
struct line_vector *vec) struct line_vector *vec)
{ {
@@ -2638,6 +2643,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
ln->filename = filename; ln->filename = filename;
ln->lineno = lineno; ln->lineno = lineno;
ln->column = column;
ln->idx = vec->count; ln->idx = vec->count;
++vec->count; ++vec->count;
@@ -3056,6 +3062,7 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
const char *reset_filename; const char *reset_filename;
const char *filename; const char *filename;
int lineno; int lineno;
int column;
address = 0; address = 0;
op_index = 0; op_index = 0;
@@ -3064,6 +3071,7 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
else else
reset_filename = ""; reset_filename = "";
filename = reset_filename; filename = reset_filename;
column = 0;
lineno = 1; lineno = 1;
while (line_buf->left > 0) while (line_buf->left > 0)
{ {
@@ -3081,7 +3089,7 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
/ hdr->max_ops_per_insn); / hdr->max_ops_per_insn);
op_index = (op_index + advance) % hdr->max_ops_per_insn; op_index = (op_index + advance) % hdr->max_ops_per_insn;
lineno += hdr->line_base + (int) (op % hdr->line_range); lineno += hdr->line_base + (int) (op % hdr->line_range);
add_line (state, ddata, address, filename, lineno, add_line (state, ddata, address, filename, lineno, column,
line_buf->error_callback, line_buf->data, vec); line_buf->error_callback, line_buf->data, vec);
} }
else if (op == DW_LNS_extended_op) else if (op == DW_LNS_extended_op)
@@ -3169,7 +3177,7 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
switch (op) switch (op)
{ {
case DW_LNS_copy: case DW_LNS_copy:
add_line (state, ddata, address, filename, lineno, add_line (state, ddata, address, filename, lineno, column,
line_buf->error_callback, line_buf->data, vec); line_buf->error_callback, line_buf->data, vec);
break; break;
case DW_LNS_advance_pc: case DW_LNS_advance_pc:
@@ -3202,7 +3210,7 @@ read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
} }
break; break;
case DW_LNS_set_column: case DW_LNS_set_column:
read_uleb128 (line_buf); column = read_uleb128 (line_buf);
break; break;
case DW_LNS_negate_stmt: case DW_LNS_negate_stmt:
break; break;
@@ -3642,6 +3650,10 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
if (val.encoding == ATTR_VAL_UINT) if (val.encoding == ATTR_VAL_UINT)
function->caller_lineno = val.u.uint; function->caller_lineno = val.u.uint;
break; break;
case DW_AT_call_column:
if (val.encoding == ATTR_VAL_UINT)
function->caller_column = val.u.uint;
break;
case DW_AT_abstract_origin: case DW_AT_abstract_origin:
case DW_AT_specification: case DW_AT_specification:
@@ -3884,7 +3896,7 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
static int static int
report_inlined_functions (uintptr_t pc, struct function *function, report_inlined_functions (uintptr_t pc, struct function *function,
backtrace_full_callback callback, void *data, backtrace_full_callback callback, void *data,
const char **filename, int *lineno) const char **filename, int *lineno, int *column)
{ {
struct function_addrs *p; struct function_addrs *p;
struct function_addrs *match; struct function_addrs *match;
@@ -3937,12 +3949,12 @@ report_inlined_functions (uintptr_t pc, struct function *function,
/* Report any calls inlined into this one. */ /* Report any calls inlined into this one. */
ret = report_inlined_functions (pc, inlined, callback, data, ret = report_inlined_functions (pc, inlined, callback, data,
filename, lineno); filename, lineno, column);
if (ret != 0) if (ret != 0)
return ret; return ret;
/* Report this inlined call. */ /* Report this inlined call. */
ret = callback (data, pc, *filename, *lineno, inlined->name); ret = callback (data, pc, *filename, *lineno, *column, inlined->name);
if (ret != 0) if (ret != 0)
return ret; return ret;
@@ -3950,6 +3962,7 @@ report_inlined_functions (uintptr_t pc, struct function *function,
it the appropriate filename and line number. */ it the appropriate filename and line number. */
*filename = inlined->caller_filename; *filename = inlined->caller_filename;
*lineno = inlined->caller_lineno; *lineno = inlined->caller_lineno;
*column = inlined->caller_column;
return 0; return 0;
} }
@@ -3976,6 +3989,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
struct function *function; struct function *function;
const char *filename; const char *filename;
int lineno; int lineno;
int column;
int ret; int ret;
*found = 1; *found = 1;
@@ -4117,7 +4131,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
if (new_data) if (new_data)
return dwarf_lookup_pc (state, ddata, pc, callback, error_callback, return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
data, found); data, found);
return callback (data, pc, NULL, 0, NULL); return callback (data, pc, NULL, 0, 0, NULL);
} }
/* Search for PC within this unit. */ /* Search for PC within this unit. */
@@ -4164,13 +4178,13 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
entry->u->abs_filename = filename; entry->u->abs_filename = filename;
} }
return callback (data, pc, entry->u->abs_filename, 0, NULL); return callback (data, pc, entry->u->abs_filename, 0, 0, NULL);
} }
/* Search for function name within this unit. */ /* Search for function name within this unit. */
if (entry->u->function_addrs_count == 0) if (entry->u->function_addrs_count == 0)
return callback (data, pc, ln->filename, ln->lineno, NULL); return callback (data, pc, ln->filename, ln->lineno, ln->column, NULL);
p = ((struct function_addrs *) p = ((struct function_addrs *)
bsearch (&pc, entry->u->function_addrs, bsearch (&pc, entry->u->function_addrs,
@@ -4178,7 +4192,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
sizeof (struct function_addrs), sizeof (struct function_addrs),
function_addrs_search)); function_addrs_search));
if (p == NULL) if (p == NULL)
return callback (data, pc, ln->filename, ln->lineno, NULL); return callback (data, pc, ln->filename, ln->lineno, ln->column, NULL);
/* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
sorted by low, so if pc > p->low we are at the end of a range of sorted by low, so if pc > p->low we are at the end of a range of
@@ -4202,19 +4216,20 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
--p; --p;
} }
if (fmatch == NULL) if (fmatch == NULL)
return callback (data, pc, ln->filename, ln->lineno, NULL); return callback (data, pc, ln->filename, ln->lineno, ln->column, NULL);
function = fmatch->function; function = fmatch->function;
filename = ln->filename; filename = ln->filename;
lineno = ln->lineno; lineno = ln->lineno;
column = ln->column;
ret = report_inlined_functions (pc, function, callback, data, ret = report_inlined_functions (pc, function, callback, data,
&filename, &lineno); &filename, &lineno, &column);
if (ret != 0) if (ret != 0)
return ret; return ret;
return callback (data, pc, filename, lineno, function->name); return callback (data, pc, filename, lineno, column, function->name);
} }
@@ -4264,7 +4279,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
/* FIXME: See if any libraries have been dlopen'ed. */ /* FIXME: See if any libraries have been dlopen'ed. */
return callback (data, pc, NULL, 0, NULL); return callback (data, pc, NULL, 0, 0, NULL);
} }
/* Initialize our data structures from the DWARF debug info for a /* Initialize our data structures from the DWARF debug info for a
@@ -330,7 +330,7 @@ backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
{ {
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname); bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, 0, symname);
} }
/* An error callback that corresponds to /* An error callback that corresponds to
@@ -98,7 +98,7 @@ extern struct backtrace_state *backtrace_create_state (
invalid after this function returns. */ invalid after this function returns. */
typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
const char *filename, int lineno, const char *filename, int lineno, int column,
const char *function); const char *function);
/* Get a full stack backtrace. SKIP is the number of frames to skip; /* Get a full stack backtrace. SKIP is the number of frames to skip;
@@ -50,16 +50,16 @@ struct print_data
/* Print one level of a backtrace. */ /* Print one level of a backtrace. */
static int static int
print_callback (void *data, uintptr_t pc, const char *filename, int lineno, print_callback (void *data, uintptr_t pc, const char *filename, int lineno, int column,
const char *function) const char *function)
{ {
struct print_data *pdata = (struct print_data *) data; struct print_data *pdata = (struct print_data *) data;
fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n", fprintf (pdata->f, "0x%lx %s\n\t%s:%d:%d\n",
(unsigned long) pc, (unsigned long) pc,
function == NULL ? "???" : function, function == NULL ? "???" : function,
filename == NULL ? "???" : filename, filename == NULL ? "???" : filename,
lineno); lineno, column);
return 0; return 0;
} }