From: Tom de Vries <tdevries@suse.de>
To: dwz@sourceware.org, jakub@redhat.com
Subject: [PATCH] Error out for invalid DW_FORM_ref_addr
Date: Tue, 01 Jan 2019 00:00:00 -0000 [thread overview]
Message-ID: <20190307131218.GA6377@delia> (raw)
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))
reply other threads:[~2019-03-07 13:11 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190307131218.GA6377@delia \
--to=tdevries@suse.de \
--cc=dwz@sourceware.org \
--cc=jakub@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).