* [PATCH] Error out for invalid DW_FORM_ref_addr
@ 2019-01-01 0:00 Tom de Vries
0 siblings, 0 replies; only message in thread
From: Tom de Vries @ 2019-01-01 0:00 UTC (permalink / raw)
To: dwz, jakub
Hi,
When running dwz on a file that contains invalid DW_FORM_ref_addr attributes
(which has been observed to be generated by a google go compiler) we run
either into an assert:
...
$ dwz f
dwz: dwz.c:8792: write_die: Assertion `refd != NULL' failed.
Aborted (core dumped)
...
or a segmentation fault:
...
$ dwz -l0 f
Segmentation fault (core dumped)
...
Fix this by verifying the DW_FORM_ref_addr attributes after parsing the
.debug_info section.
This gives a detailed error message in regular mode:
...
$ dwz f
dwz: Couldn't find DIE at DW_FORM_ref_addr offset 0x85e89c (referenced by \
DW_AT_abstract_origin in DIE at offset 0x85eacb)
...
and a more basic error message in low-memory mode:
...
$ dwz -l0 f
dwz: Couldn't find DIE at DW_FORM_ref_addr offset 0x85e848
...
OK for trunk?
Thanks,
- Tom
Error out for invalid DW_FORM_ref_addr
2019-02-05 Tom de Vries <tdevries@suse.de>
PR dwz/24169
* dwz.c (verify_ref_addr_die, verify_ref_addr_low_mem, verify_ref_addr):
New function.
(read_debug_info): Call verify_ref_addr.
---
dwz.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/dwz.c b/dwz.c
index e4e5d5c..7ec1347 100644
--- a/dwz.c
+++ b/dwz.c
@@ -4401,6 +4401,81 @@ collapse_children (dw_cu_ref cu, dw_die_ref die)
}
}
+/* Verify DW_FORM_ref_addr in DIE. */
+static inline void
+verify_ref_addr_die (dw_cu_ref cu, dw_die_ref die)
+{
+ dw_die_ref child;
+ for (child = die->die_child; child; child = child->die_sib)
+ verify_ref_addr_die (cu, child);
+
+ if (die->die_offset == -1U)
+ return;
+
+ struct abbrev_tag *t = die->die_abbrev;
+ unsigned int i;
+ unsigned char *section_ptr;
+ unsigned char *ptr;
+ if (unlikely (fi_multifile) && cu->cu_kind == CU_ALT)
+ section_ptr = alt_data[DEBUG_INFO];
+ else if (cu->cu_kind == CU_TYPES)
+ section_ptr = debug_sections[DEBUG_TYPES].data;
+ else
+ section_ptr = debug_sections[DEBUG_INFO].data;
+ ptr = section_ptr + die->die_offset;
+ read_uleb128 (ptr);
+ for (i = 0; i < t->nattr; ++i)
+ {
+ struct abbrev_attr *attr = &t->attr[i];
+ if (attr->form == DW_FORM_ref_addr)
+ {
+ uint64_t value;
+ dw_die_ref ref;
+
+ value = read_size (ptr, cu->cu_version == 2
+ ? ptr_size : 4);
+
+ ref = off_htab_lookup (cu, value);
+ if (ref == NULL)
+ {
+ error (1, 0,
+ "Couldn't find DIE at DW_FORM_ref_addr offset 0x%lx"
+ " (referenced by %s in DIE at offset 0x%x)",
+ value, get_DW_AT_str (attr->attr), die->die_offset);
+
+ }
+ }
+ ptr = skip_attr (cu, attr, ptr);
+ }
+}
+
+/* Verify DW_FORM_ref_addr in low_mem mode. */
+static int
+verify_ref_addr_low_mem (void **slot, void *data __attribute__((unused)))
+{
+ dw_die_ref die = (dw_die_ref) *slot;
+ if (die->die_tag == 0)
+ error (1, 0, "Couldn't find DIE at DW_FORM_ref_addr offset 0x%x",
+ die->die_offset);
+
+ return 1;
+}
+
+/* Verify DW_FORM_ref_addr. */
+static void
+verify_ref_addr (void)
+{
+ if (unlikely (low_mem))
+ htab_traverse (off_htab, verify_ref_addr_low_mem, NULL);
+ else
+ {
+ dw_cu_ref cu;
+
+ for (cu = first_cu; cu; cu = cu->cu_next)
+ verify_ref_addr_die (cu, cu->cu_die);
+ }
+}
+
/* First phase of the DWARF compression. Parse .debug_info section
(for kind == DEBUG_INFO) or .debug_types section (for kind == DEBUG_TYPES)
for each CU in it construct internal represetnation for the CU
@@ -4428,6 +4503,7 @@ read_debug_info (DSO *dso, int kind)
bool low_mem_phase1 = low_mem && kind == DEBUG_INFO;
struct dw_cu cu_buf;
struct dw_die die_buf;
+ bool seen_ref_addr = false;
if (likely (!fi_multifile && kind != DEBUG_TYPES))
{
@@ -4523,6 +4599,9 @@ read_debug_info (DSO *dso, int kind)
{
if (ptr == endcu)
{
+ if (seen_ref_addr)
+ verify_ref_addr ();
+
dw_cu_ref cuf = cu_tail ? cu_tail->cu_next : first_cu;
/* Inside of optimize_multifile, DIE hashes are computed
only after all the CUs from a particular DSO or
@@ -4748,6 +4827,7 @@ read_debug_info (DSO *dso, int kind)
switch (form)
{
case DW_FORM_ref_addr:
+ seen_ref_addr = true;
if (unlikely (low_mem_phase1))
{
dw_die_ref ref;
@@ -5019,6 +5099,9 @@ read_debug_info (DSO *dso, int kind)
goto low_mem_phase2;
}
+ if (seen_ref_addr && !(unlikely (op_multifile)))
+ verify_ref_addr ();
+
if (unlikely (low_mem))
;
else if (unlikely (meta_abbrev_htab != NULL))
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-03-07 13:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-01 0:00 [PATCH] Error out for invalid DW_FORM_ref_addr Tom de Vries
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).