|
|
a5e32e |
From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001
|
|
|
a5e32e |
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
a5e32e |
Date: Mon, 18 Jan 2021 22:56:53 +0100
|
|
|
a5e32e |
Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms
|
|
|
a5e32e |
parsing.
|
|
|
a5e32e |
|
|
|
a5e32e |
Recognize the various new DWARF5 .debug sections.
|
|
|
a5e32e |
Parse and skip new DWARF5 forms in read_abbrev and skip_form.
|
|
|
a5e32e |
Read DWARF5 unit headers for compile and partial units in edit_info.
|
|
|
a5e32e |
|
|
|
a5e32e |
This is enough to be able to process gcc -gdwarf-5 produced binaries
|
|
|
a5e32e |
without the new DWARF5 .debug_line format (which isn't produced with
|
|
|
a5e32e |
binutils < 2.36).
|
|
|
a5e32e |
|
|
|
a5e32e |
Patches slightly edited/merged by Mark Wielaard <mark@klomp.org>
|
|
|
a5e32e |
---
|
|
|
a5e32e |
tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++----
|
|
|
a5e32e |
1 file changed, 81 insertions(+), 7 deletions(-)
|
|
|
a5e32e |
|
|
|
a5e32e |
diff --git a/tools/debugedit.c b/tools/debugedit.c
|
|
|
a5e32e |
index 7464883c5..be5fee85b 100644
|
|
|
a5e32e |
--- a/tools/debugedit.c
|
|
|
a5e32e |
+++ b/tools/debugedit.c
|
|
|
a5e32e |
@@ -453,6 +453,11 @@ static debug_section debug_sections[] =
|
|
|
a5e32e |
#define DEBUG_TYPES 11
|
|
|
a5e32e |
#define DEBUG_MACRO 12
|
|
|
a5e32e |
#define DEBUG_GDB_SCRIPT 13
|
|
|
a5e32e |
+#define DEBUG_RNGLISTS 14
|
|
|
a5e32e |
+#define DEBUG_LINE_STR 15
|
|
|
a5e32e |
+#define DEBUG_ADDR 16
|
|
|
a5e32e |
+#define DEBUG_STR_OFFSETS 17
|
|
|
a5e32e |
+#define DEBUG_LOCLISTS 18
|
|
|
a5e32e |
{ ".debug_info", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
{ ".debug_abbrev", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
{ ".debug_line", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
@@ -467,6 +472,11 @@ static debug_section debug_sections[] =
|
|
|
a5e32e |
{ ".debug_types", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
{ ".debug_macro", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
{ ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
+ { ".debug_rnglists", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
+ { ".debug_line_str", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
+ { ".debug_addr", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
+ { ".debug_str_offsets", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
+ { ".debug_loclists", NULL, NULL, 0, 0, 0 },
|
|
|
a5e32e |
{ NULL, NULL, NULL, 0, 0, 0 }
|
|
|
a5e32e |
};
|
|
|
a5e32e |
|
|
|
a5e32e |
@@ -755,12 +765,28 @@ no_memory:
|
|
|
a5e32e |
}
|
|
|
a5e32e |
form = read_uleb128 (ptr);
|
|
|
a5e32e |
if (form == 2
|
|
|
a5e32e |
- || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
|
|
|
a5e32e |
+ || (form > DW_FORM_flag_present
|
|
|
a5e32e |
+ && !(form == DW_FORM_ref_sig8
|
|
|
a5e32e |
+ || form == DW_FORM_data16
|
|
|
a5e32e |
+ || form == DW_FORM_implicit_const
|
|
|
a5e32e |
+ || form == DW_FORM_addrx
|
|
|
a5e32e |
+ || form == DW_FORM_loclistx
|
|
|
a5e32e |
+ || form == DW_FORM_rnglistx
|
|
|
a5e32e |
+ || form == DW_FORM_addrx1
|
|
|
a5e32e |
+ || form == DW_FORM_addrx2
|
|
|
a5e32e |
+ || form == DW_FORM_addrx3
|
|
|
a5e32e |
+ || form == DW_FORM_addrx4)))
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
|
|
|
a5e32e |
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename,
|
|
|
a5e32e |
+ form);
|
|
|
a5e32e |
htab_delete (h);
|
|
|
a5e32e |
return NULL;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
+ if (form == DW_FORM_implicit_const)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ /* It is SLEB128 but the value is dropped anyway. */
|
|
|
a5e32e |
+ read_uleb128 (ptr);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
|
|
|
a5e32e |
t->attr[t->nattr].attr = attr;
|
|
|
a5e32e |
t->attr[t->nattr++].form = form;
|
|
|
a5e32e |
@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
|
|
|
a5e32e |
*ptrp += 4;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
case DW_FORM_flag_present:
|
|
|
a5e32e |
+ case DW_FORM_implicit_const:
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
case DW_FORM_addr:
|
|
|
a5e32e |
*ptrp += ptr_size;
|
|
|
a5e32e |
@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
|
|
|
a5e32e |
case DW_FORM_ref1:
|
|
|
a5e32e |
case DW_FORM_flag:
|
|
|
a5e32e |
case DW_FORM_data1:
|
|
|
a5e32e |
+ case DW_FORM_strx1:
|
|
|
a5e32e |
+ case DW_FORM_addrx1:
|
|
|
a5e32e |
++*ptrp;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
case DW_FORM_ref2:
|
|
|
a5e32e |
case DW_FORM_data2:
|
|
|
a5e32e |
+ case DW_FORM_strx2:
|
|
|
a5e32e |
+ case DW_FORM_addrx2:
|
|
|
a5e32e |
*ptrp += 2;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
+ case DW_FORM_strx3:
|
|
|
a5e32e |
+ case DW_FORM_addrx3:
|
|
|
a5e32e |
+ *ptrp += 3;
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
case DW_FORM_ref4:
|
|
|
a5e32e |
case DW_FORM_data4:
|
|
|
a5e32e |
+ case DW_FORM_strx4:
|
|
|
a5e32e |
+ case DW_FORM_addrx4:
|
|
|
a5e32e |
case DW_FORM_sec_offset:
|
|
|
a5e32e |
*ptrp += 4;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
|
|
|
a5e32e |
case DW_FORM_ref_sig8:
|
|
|
a5e32e |
*ptrp += 8;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
+ case DW_FORM_data16:
|
|
|
a5e32e |
+ *ptrp += 16;
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
case DW_FORM_sdata:
|
|
|
a5e32e |
case DW_FORM_ref_udata:
|
|
|
a5e32e |
case DW_FORM_udata:
|
|
|
a5e32e |
+ case DW_FORM_strx:
|
|
|
a5e32e |
+ case DW_FORM_loclistx:
|
|
|
a5e32e |
+ case DW_FORM_rnglistx:
|
|
|
a5e32e |
+ case DW_FORM_addrx:
|
|
|
a5e32e |
read_uleb128 (*ptrp);
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
case DW_FORM_strp:
|
|
|
a5e32e |
+ case DW_FORM_line_strp:
|
|
|
a5e32e |
*ptrp += 4;
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
case DW_FORM_string:
|
|
|
a5e32e |
@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp)
|
|
|
a5e32e |
assert (len < UINT_MAX);
|
|
|
a5e32e |
break;
|
|
|
a5e32e |
default:
|
|
|
a5e32e |
- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp);
|
|
|
a5e32e |
+ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp);
|
|
|
a5e32e |
return FORM_ERROR;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
|
|
|
a5e32e |
endsec = ptr + sec->size;
|
|
|
a5e32e |
while (ptr < endsec)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
|
|
|
a5e32e |
+ unsigned char *cu_start = ptr;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* header size, version, unit_type, ptr_size. */
|
|
|
a5e32e |
+ if (ptr + 4 + 2 + 1 + 1 > endsec)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
error (0, 0, "%s: %s CU header too small",
|
|
|
a5e32e |
dso->filename, sec->name);
|
|
|
a5e32e |
@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
cu_version = read_16 (ptr);
|
|
|
a5e32e |
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
|
|
|
a5e32e |
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4
|
|
|
a5e32e |
+ && cu_version != 5)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
|
|
|
a5e32e |
cu_version);
|
|
|
a5e32e |
return 1;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
+ int cu_ptr_size = 0;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ if (cu_version >= 5)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ uint8_t unit_type = read_8 (ptr);
|
|
|
a5e32e |
+ if (unit_type != DW_UT_compile && unit_type != DW_UT_partial)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: Unit type %u unhandled", dso->filename,
|
|
|
a5e32e |
+ unit_type);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ cu_ptr_size = read_8 (ptr);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1));
|
|
|
a5e32e |
+ if (header_end > endsec)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: %s CU header too small", dso->filename, sec->name);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
value = read_32_relocated (ptr);
|
|
|
a5e32e |
if (value >= debug_sections[DEBUG_ABBREV].size)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
|
|
|
a5e32e |
return 1;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
+ if (cu_version < 5)
|
|
|
a5e32e |
+ cu_ptr_size = read_8 (ptr);
|
|
|
a5e32e |
+
|
|
|
a5e32e |
if (ptr_size == 0)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- ptr_size = read_8 (ptr);
|
|
|
a5e32e |
+ ptr_size = cu_ptr_size;
|
|
|
a5e32e |
if (ptr_size != 4 && ptr_size != 8)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
error (0, 0, "%s: Invalid DWARF pointer size %d",
|
|
|
a5e32e |
@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
|
|
|
a5e32e |
return 1;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
}
|
|
|
a5e32e |
- else if (read_8 (ptr) != ptr_size)
|
|
|
a5e32e |
+ else if (cu_ptr_size != ptr_size)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
error (0, 0, "%s: DWARF pointer size differs between CUs",
|
|
|
a5e32e |
dso->filename);
|
|
|
a5e32e |
--
|
|
|
a5e32e |
2.18.4
|
|
|
a5e32e |
|