Commit 944f59ff by Tom de Vries Committed by Tom de Vries

[libbacktrace] Handle alt FORMS without .gnu_debugaltlink

Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
presence of missing .gnu_debugaltlink file.

2019-01-17  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
	(read_attribute): Add altlink parameter.  Handle missing altlink for
	DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
	(find_address_ranges, build_address_map, build_dwarf_data): Add and
	handle altlink parameter.
	(read_referenced_name, read_function_entry): Add argument to
	read_attribute call.

From-SVN: r267995
parent 9ad458d5
2019-01-17 Tom de Vries <tdevries@suse.de> 2019-01-17 Tom de Vries <tdevries@suse.de>
* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
(read_attribute): Add altlink parameter. Handle missing altlink for
DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
(find_address_ranges, build_address_map, build_dwarf_data): Add and
handle altlink parameter.
(read_referenced_name, read_function_entry): Add argument to
read_attribute call.
2019-01-17 Tom de Vries <tdevries@suse.de>
* dwarf.c (struct dwarf_data): Add altlink field. * dwarf.c (struct dwarf_data): Add altlink field.
(backtrace_dwarf_add): Add and handle fileline_altlink parameter. (backtrace_dwarf_add): Add and handle fileline_altlink parameter.
* elf.c (elf_add): Add argument to backtrace_dwarf_add call. * elf.c (elf_add): Add argument to backtrace_dwarf_add call.
......
...@@ -129,6 +129,8 @@ struct abbrevs ...@@ -129,6 +129,8 @@ struct abbrevs
enum attr_val_encoding enum attr_val_encoding
{ {
/* No attribute value. */
ATTR_VAL_NONE,
/* An address. */ /* An address. */
ATTR_VAL_ADDRESS, ATTR_VAL_ADDRESS,
/* A unsigned integer. */ /* A unsigned integer. */
...@@ -700,7 +702,7 @@ static int ...@@ -700,7 +702,7 @@ static int
read_attribute (enum dwarf_form form, struct dwarf_buf *buf, read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
int is_dwarf64, int version, int addrsize, int is_dwarf64, int version, int addrsize,
const unsigned char *dwarf_str, size_t dwarf_str_size, const unsigned char *dwarf_str, size_t dwarf_str_size,
struct attr_val *val) struct dwarf_data *altlink, struct attr_val *val)
{ {
/* Avoid warnings about val.u.FIELD may be used uninitialized if /* Avoid warnings about val.u.FIELD may be used uninitialized if
this function is inlined. The warnings aren't valid but can this function is inlined. The warnings aren't valid but can
...@@ -806,7 +808,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf, ...@@ -806,7 +808,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
form = read_uleb128 (buf); form = read_uleb128 (buf);
return read_attribute ((enum dwarf_form) form, buf, is_dwarf64, return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
version, addrsize, dwarf_str, dwarf_str_size, version, addrsize, dwarf_str, dwarf_str_size,
val); altlink, val);
} }
case DW_FORM_sec_offset: case DW_FORM_sec_offset:
val->encoding = ATTR_VAL_REF_SECTION; val->encoding = ATTR_VAL_REF_SECTION;
...@@ -832,12 +834,22 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf, ...@@ -832,12 +834,22 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
val->u.uint = read_uleb128 (buf); val->u.uint = read_uleb128 (buf);
return 1; return 1;
case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_ref_alt:
val->encoding = ATTR_VAL_REF_SECTION;
val->u.uint = read_offset (buf, is_dwarf64); val->u.uint = read_offset (buf, is_dwarf64);
if (altlink == NULL)
{
val->encoding = ATTR_VAL_NONE;
return 1;
}
val->encoding = ATTR_VAL_REF_SECTION;
return 1; return 1;
case DW_FORM_GNU_strp_alt: case DW_FORM_GNU_strp_alt:
val->encoding = ATTR_VAL_REF_SECTION;
val->u.uint = read_offset (buf, is_dwarf64); val->u.uint = read_offset (buf, is_dwarf64);
if (altlink == NULL)
{
val->encoding = ATTR_VAL_NONE;
return 1;
}
val->encoding = ATTR_VAL_REF_SECTION;
return 1; return 1;
default: default:
dwarf_buf_error (buf, "unrecognized DWARF form"); dwarf_buf_error (buf, "unrecognized DWARF form");
...@@ -1275,9 +1287,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address, ...@@ -1275,9 +1287,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
const unsigned char *dwarf_str, size_t dwarf_str_size, const unsigned char *dwarf_str, size_t dwarf_str_size,
const unsigned char *dwarf_ranges, const unsigned char *dwarf_ranges,
size_t dwarf_ranges_size, size_t dwarf_ranges_size,
int is_bigendian, backtrace_error_callback error_callback, int is_bigendian, struct dwarf_data *altlink,
void *data, struct unit *u, backtrace_error_callback error_callback, void *data,
struct unit_addrs_vector *addrs) struct unit *u, struct unit_addrs_vector *addrs)
{ {
while (unit_buf->left > 0) while (unit_buf->left > 0)
{ {
...@@ -1313,7 +1325,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address, ...@@ -1313,7 +1325,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
if (!read_attribute (abbrev->attrs[i].form, unit_buf, if (!read_attribute (abbrev->attrs[i].form, unit_buf,
u->is_dwarf64, u->version, u->addrsize, u->is_dwarf64, u->version, u->addrsize,
dwarf_str, dwarf_str_size, &val)) dwarf_str, dwarf_str_size, altlink, &val))
return 0; return 0;
switch (abbrev->attrs[i].name) switch (abbrev->attrs[i].name)
...@@ -1411,7 +1423,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address, ...@@ -1411,7 +1423,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
if (!find_address_ranges (state, base_address, unit_buf, if (!find_address_ranges (state, base_address, unit_buf,
dwarf_str, dwarf_str_size, dwarf_str, dwarf_str_size,
dwarf_ranges, dwarf_ranges_size, dwarf_ranges, dwarf_ranges_size,
is_bigendian, error_callback, data, is_bigendian, altlink, error_callback, data,
u, addrs)) u, addrs))
return 0; return 0;
} }
...@@ -1430,8 +1442,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, ...@@ -1430,8 +1442,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size, const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
const unsigned char *dwarf_ranges, size_t dwarf_ranges_size, const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
const unsigned char *dwarf_str, size_t dwarf_str_size, const unsigned char *dwarf_str, size_t dwarf_str_size,
int is_bigendian, backtrace_error_callback error_callback, int is_bigendian, struct dwarf_data *altlink,
void *data, struct unit_addrs_vector *addrs) backtrace_error_callback error_callback, void *data,
struct unit_addrs_vector *addrs)
{ {
struct dwarf_buf info; struct dwarf_buf info;
struct backtrace_vector units; struct backtrace_vector units;
...@@ -1532,7 +1545,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, ...@@ -1532,7 +1545,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
if (!find_address_ranges (state, base_address, &unit_buf, if (!find_address_ranges (state, base_address, &unit_buf,
dwarf_str, dwarf_str_size, dwarf_str, dwarf_str_size,
dwarf_ranges, dwarf_ranges_size, dwarf_ranges, dwarf_ranges_size,
is_bigendian, error_callback, data, is_bigendian, altlink, error_callback, data,
u, addrs)) u, addrs))
goto fail; goto fail;
...@@ -2184,7 +2197,7 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u, ...@@ -2184,7 +2197,7 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
if (!read_attribute (abbrev->attrs[i].form, &unit_buf, if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
u->is_dwarf64, u->version, u->addrsize, u->is_dwarf64, u->version, u->addrsize,
ddata->dwarf_str, ddata->dwarf_str_size, ddata->dwarf_str, ddata->dwarf_str_size,
&val)) ddata->altlink, &val))
return NULL; return NULL;
switch (abbrev->attrs[i].name) switch (abbrev->attrs[i].name)
...@@ -2396,7 +2409,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata, ...@@ -2396,7 +2409,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
if (!read_attribute (abbrev->attrs[i].form, unit_buf, if (!read_attribute (abbrev->attrs[i].form, unit_buf,
u->is_dwarf64, u->version, u->addrsize, u->is_dwarf64, u->version, u->addrsize,
ddata->dwarf_str, ddata->dwarf_str_size, ddata->dwarf_str, ddata->dwarf_str_size,
&val)) ddata->altlink, &val))
return 0; return 0;
/* The compile unit sets the base address for any address /* The compile unit sets the base address for any address
...@@ -3014,7 +3027,8 @@ build_dwarf_data (struct backtrace_state *state, ...@@ -3014,7 +3027,8 @@ build_dwarf_data (struct backtrace_state *state,
if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size, if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges, dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
dwarf_ranges_size, dwarf_str, dwarf_str_size, dwarf_ranges_size, dwarf_str, dwarf_str_size,
is_bigendian, error_callback, data, &addrs_vec)) is_bigendian, altlink, error_callback, data,
&addrs_vec))
return NULL; return NULL;
if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data)) if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment