diff --git a/tests/debugedit.at b/tests/debugedit.at index 49721a342..bcd86ac67 100644 --- a/tests/debugedit.at +++ b/tests/debugedit.at @@ -253,9 +253,8 @@ AT_CLEANUP # === # Make sure -fdebug-types-section has updated strings in objects. # === -AT_SETUP([debugedit .debug_types objects]) -AT_KEYWORDS([debugtypes] [debugedit]) -RPM_DEBUGEDIT_SETUP([-fdebug-types-section]) +m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS],[ +RPM_DEBUGEDIT_SETUP($1) AT_DATA([expout], [st1 @@ -283,15 +282,13 @@ for i in ./foo.o ./subdir_bar/bar.o ./baz.o;do \ | sort; done ]],[0],[expout]) - -AT_CLEANUP +]) # === # Make sure -fdebug-types-section has updated strings in partial linked object. # === -AT_SETUP([debugedit .debug_types partial]) -AT_KEYWORDS([debugtypes] [debugedit]) -RPM_DEBUGEDIT_SETUP([-fdebug-types-section]) +m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL],[ +RPM_DEBUGEDIT_SETUP($1) AT_DATA([expout], [st1 @@ -311,15 +308,13 @@ readelf --debug-dump=info ./foobarbaz.part.o \ | sed -n 's/^.*> *DW_AT_name *:.* \(stringp[^ ]*\|st.\)$/\1/p' \ | sort ]],[0],[expout]) - -AT_CLEANUP +]) # === # Make sure -fdebug-types-section has updated strings in executable. # === -AT_SETUP([debugedit .debug_types exe]) -AT_KEYWORDS([debugtypes] [debugedit]) -RPM_DEBUGEDIT_SETUP([-fdebug-types-section]) +m4_define([RPM_DEBUGEDIT_DEBUG_TYPES_EXE],[ +RPM_DEBUGEDIT_SETUP($1) AT_DATA([expout], [st1 @@ -339,7 +334,36 @@ readelf --debug-dump=info ./foobarbaz.exe \ | sed -n 's/^.*> *DW_AT_name *:.* \(stringp[^ ]*\|st.\)$/\1/p' \ | sort ]],[0],[expout]) +]) + +AT_SETUP([debugedit DWARF-4 .debug_types objects]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS([-gdwarf-4 -fdebug-types-section]) +AT_CLEANUP +AT_SETUP([debugedit DWARF-4 .debug_types partial]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL([-gdwarf-4 -fdebug-types-section]) +AT_CLEANUP + +AT_SETUP([debugedit DWARF-4 .debug_types exe]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_EXE([-gdwarf-4 -fdebug-types-section]) +AT_CLEANUP + +AT_SETUP([debugedit DWARF-5 .debug_types objects]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_OBJECTS([-gdwarf-5 -fdebug-types-section]) +AT_CLEANUP + +AT_SETUP([debugedit DWARF-5 .debug_types partial]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_PARTIAL([-gdwarf-5 -fdebug-types-section]) +AT_CLEANUP + +AT_SETUP([debugedit DWARF-5 .debug_types exe]) +AT_KEYWORDS([debugtypes] [debugedit]) +RPM_DEBUGEDIT_DEBUG_TYPES_EXE([-gdwarf-5 -fdebug-types-section]) AT_CLEANUP # foo.o and bar.o are build with relative paths and so will use the diff --git a/tools/debugedit.c b/tools/debugedit.c index 9f1dc2d3f..19f69e263 100644 --- a/tools/debugedit.c +++ b/tools/debugedit.c @@ -433,7 +433,8 @@ typedef struct debug_section int sec, relsec; REL *relbuf; REL *relend; - /* Only happens for COMDAT .debug_macro and .debug_types. */ + /* Only happens for COMDAT .debug_macro, .debug_types and DWARF-5 + .debug_info. */ struct debug_section *next; } debug_section; @@ -755,12 +756,19 @@ no_memory: } form = read_uleb128 (ptr); if (form == 2 - || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8)) + || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8 + && form != DW_FORM_implicit_const)) { - error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); + error (0, 0, "%s: Unknown DWARF abbrev DW_FORM_0x%x", + dso->filename, form); htab_delete (h); return NULL; } + if (form == DW_FORM_implicit_const) + { + /* It is SLEB128 but the value is dropped anyway. */ + read_uleb128 (ptr); + } t->attr[t->nattr].attr = attr; t->attr[t->nattr++].form = form; @@ -1505,6 +1513,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) *ptrp += 4; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_addr: *ptrp += ptr_size; @@ -2018,7 +2027,7 @@ line_rel_cmp (const void *a, const void *b) } static int -edit_info (DSO *dso, int phase, struct debug_section *sec) +edit_info (DSO *dso, int phase, struct debug_section *sec, bool is_types) { unsigned char *ptr, *endcu, *endsec; uint32_t value; @@ -2033,7 +2042,9 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) endsec = ptr + sec->size; while (ptr < endsec) { - if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) + unsigned char *sec_start = ptr; + + if (ptr + 4 + 2 + 1 + 1 > endsec) { error (0, 0, "%s: %s CU header too small", dso->filename, sec->name); @@ -2055,13 +2066,48 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) } cu_version = read_16 (ptr); - if (cu_version != 2 && cu_version != 3 && cu_version != 4) + if (cu_version != 2 && cu_version != 3 && cu_version != 4 + && cu_version != 5) { error (0, 0, "%s: DWARF version %d unhandled", dso->filename, cu_version); return 1; } + int cu_ptr_size; + bool cu_is_types; + + if (cu_version >= 5) + { + if (is_types) + { + error (0, 0, "%s: .debug_types are invalid for DWARF 5+", + dso->filename); + return 1; + } + + uint8_t unit_type = read_8 (ptr); + if (unit_type != DW_UT_compile && unit_type != DW_UT_type) + { + error (0, 0, "%s: Unit type %u unhandled", dso->filename, + unit_type); + return 1; + } + cu_is_types = unit_type == DW_UT_type; + + cu_ptr_size = read_8 (ptr); + } + else + cu_is_types = is_types; + + unsigned char *header_end = (sec_start + (!cu_is_types ? 11 : 23) + + (cu_version < 5 ? 0 : 1)); + if (header_end > endsec) + { + error (0, 0, "%s: %s CU header too small", dso->filename, sec->name); + return 1; + } + value = read_32_relocated (ptr); if (value >= debug_sections[DEBUG_ABBREV].size) { @@ -2073,9 +2119,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) return 1; } + if (cu_version < 5) + cu_ptr_size = read_8 (ptr); + if (ptr_size == 0) { - ptr_size = read_8 (ptr); + ptr_size = cu_ptr_size; if (ptr_size != 4 && ptr_size != 8) { error (0, 0, "%s: Invalid DWARF pointer size %d", @@ -2083,14 +2132,14 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) return 1; } } - else if (read_8 (ptr) != ptr_size) + else if (cu_ptr_size != ptr_size) { error (0, 0, "%s: DWARF pointer size differs between CUs", dso->filename); return 1; } - if (sec != &debug_sections[DEBUG_INFO]) + if (cu_is_types) ptr += 12; /* Skip type_signature and type_offset. */ abbrev = read_abbrev (dso, @@ -2179,7 +2228,8 @@ edit_dwarf2 (DSO *dso) struct debug_section *debug_sec = &debug_sections[j]; if (debug_sections[j].data) { - if (j != DEBUG_MACRO && j != DEBUG_TYPES) + if (j != DEBUG_MACRO && j != DEBUG_TYPES + && j != DEBUG_INFO) { error (0, 0, "%s: Found two copies of %s section", dso->filename, name); @@ -2187,8 +2237,9 @@ edit_dwarf2 (DSO *dso) } else { - /* In relocatable files .debug_macro and .debug_types - might appear multiple times as COMDAT section. */ + /* In relocatable files .debug_macro, .debug_types + and DWARF-5 .debug_info might appear multiple + times as COMDAT section. */ struct debug_section *sec; sec = calloc (sizeof (struct debug_section), 1); if (sec == NULL) @@ -2238,7 +2289,7 @@ edit_dwarf2 (DSO *dso) + (dso->shdr[i].sh_type == SHT_RELA), debug_sections[j].name) == 0) { - if (j == DEBUG_MACRO || j == DEBUG_TYPES) + if (j == DEBUG_MACRO || j == DEBUG_TYPES || j == DEBUG_INFO) { /* Pick the correct one. */ int rel_target = dso->shdr[i].sh_info; @@ -2302,8 +2353,13 @@ edit_dwarf2 (DSO *dso) break; rel_updated = false; - if (edit_info (dso, phase, &debug_sections[DEBUG_INFO])) - return 1; + struct debug_section *info_sec = &debug_sections[DEBUG_INFO]; + while (info_sec != NULL) + { + if (edit_info (dso, phase, info_sec, false /* is_types */)) + return 1; + info_sec = info_sec->next; + } /* Remember whether any .debug_info relocations might need to be updated. */ @@ -2313,7 +2369,7 @@ edit_dwarf2 (DSO *dso) struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; while (types_sec != NULL) { - if (edit_info (dso, phase, types_sec)) + if (edit_info (dso, phase, types_sec, true /* is_types */)) return 1; types_sec = types_sec->next; } @@ -2564,7 +2620,14 @@ edit_dwarf2 (DSO *dso) /* Update any relocations addends we might have touched. */ if (info_rel_updated) - update_rela_data (dso, &debug_sections[DEBUG_INFO]); + { + struct debug_section *info_sec = &debug_sections[DEBUG_INFO]; + while (info_sec != NULL) + { + update_rela_data (dso, info_sec); + info_sec = info_sec->next; + } + } if (types_rel_updated) { struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; @@ -2914,6 +2977,7 @@ main (int argc, char *argv[]) if (dso == NULL) exit (1); + bool have_info = false; for (i = 1; i < dso->ehdr.e_shnum; i++) { const char *name; @@ -2929,7 +2993,7 @@ main (int argc, char *argv[]) break; } if (strcmp (name, ".debug_info") == 0) - edit_dwarf2 (dso); + have_info = true; break; case SHT_NOTE: @@ -2960,6 +3024,9 @@ main (int argc, char *argv[]) } } + if (have_info) + edit_dwarf2 (dso); + /* Normally we only need to explicitly update the section headers and data when any section data changed size. But because of a bug in elfutils before 0.169 we will have to update and write out all @@ -3136,6 +3203,17 @@ main (int argc, char *argv[]) types_sec = next; } + /* In case there were multiple (COMDAT) DWARF-5 .debug_info sections, + free them. */ + struct debug_section *info_sec = &debug_sections[DEBUG_INFO]; + info_sec = info_sec->next; + while (info_sec != NULL) + { + struct debug_section *next = info_sec->next; + free (info_sec); + info_sec = next; + } + poptFreeContext (optCon); return 0;
_______________________________________________ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint