You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
8.0 KiB
269 lines
8.0 KiB
From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001 |
|
From: Jan Kratochvil <jan.kratochvil@redhat.com> |
|
Date: Sat, 1 Aug 2020 10:45:47 +0200 |
|
Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types |
|
section. |
|
|
|
--- |
|
tools/debugedit.c | 123 ++++++++++++++++++++++++++++++---------------- |
|
1 file changed, 80 insertions(+), 43 deletions(-) |
|
|
|
diff --git a/tools/debugedit.c b/tools/debugedit.c |
|
index cad0cc349..87c1cd622 100644 |
|
--- a/tools/debugedit.c |
|
+++ b/tools/debugedit.c |
|
@@ -433,7 +433,8 @@ typedef struct debug_section |
|
int sec, relsec; |
|
REL *relbuf; |
|
REL *relend; |
|
- struct debug_section *next; /* Only happens for COMDAT .debug_macro. */ |
|
+ /* Only happens for COMDAT .debug_macro and .debug_types. */ |
|
+ struct debug_section *next; |
|
} debug_section; |
|
|
|
static debug_section debug_sections[] = |
|
@@ -1269,7 +1270,9 @@ static int dirty_elf; |
|
static void |
|
dirty_section (unsigned int sec) |
|
{ |
|
- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); |
|
+ for (struct debug_section *secp = &debug_sections[sec]; secp != NULL; |
|
+ secp = secp->next) |
|
+ elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY); |
|
dirty_elf = 1; |
|
} |
|
|
|
@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) |
|
|
|
if (get_line_table (dso, off, &table) == false |
|
|| table == NULL) |
|
- { |
|
- if (table != NULL) |
|
- error (0, 0, ".debug_line offset 0x%x referenced multiple times", |
|
- off); |
|
- return false; |
|
- } |
|
+ return false; |
|
|
|
/* Skip to the directory table. The rest of the header has already |
|
been read and checked by get_line_table. */ |
|
@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b) |
|
} |
|
|
|
static int |
|
-edit_info (DSO *dso, int phase) |
|
+edit_info (DSO *dso, int phase, struct debug_section *sec) |
|
{ |
|
unsigned char *ptr, *endcu, *endsec; |
|
uint32_t value; |
|
htab_t abbrev; |
|
struct abbrev_tag tag, *t; |
|
|
|
- ptr = debug_sections[DEBUG_INFO].data; |
|
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); |
|
- endsec = ptr + debug_sections[DEBUG_INFO].size; |
|
+ ptr = sec->data; |
|
+ if (ptr == NULL) |
|
+ return 0; |
|
+ |
|
+ setup_relbuf(dso, sec, &reltype); |
|
+ endsec = ptr + sec->size; |
|
while (ptr < endsec) |
|
{ |
|
- if (ptr + 11 > endsec) |
|
+ if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) |
|
{ |
|
- error (0, 0, "%s: .debug_info CU header too small", |
|
- dso->filename); |
|
+ error (0, 0, "%s: %s CU header too small", |
|
+ dso->filename, sec->name); |
|
return 1; |
|
} |
|
|
|
@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase) |
|
|
|
if (endcu > endsec) |
|
{ |
|
- error (0, 0, "%s: .debug_info too small", dso->filename); |
|
+ error (0, 0, "%s: %s too small", dso->filename, sec->name); |
|
return 1; |
|
} |
|
|
|
@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase) |
|
return 1; |
|
} |
|
|
|
+ if (sec != &debug_sections[DEBUG_INFO]) |
|
+ ptr += 12; /* Skip type_signature and type_offset. */ |
|
+ |
|
abbrev = read_abbrev (dso, |
|
debug_sections[DEBUG_ABBREV].data + value); |
|
if (abbrev == NULL) |
|
@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso) |
|
struct debug_section *debug_sec = &debug_sections[j]; |
|
if (debug_sections[j].data) |
|
{ |
|
- if (j != DEBUG_MACRO) |
|
+ if (j != DEBUG_MACRO && j != DEBUG_TYPES) |
|
{ |
|
error (0, 0, "%s: Found two copies of %s section", |
|
dso->filename, name); |
|
@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso) |
|
} |
|
else |
|
{ |
|
- /* In relocatable files .debug_macro might |
|
- appear multiple times as COMDAT |
|
- section. */ |
|
+ /* In relocatable files .debug_macro and .debug_types |
|
+ might appear multiple times as COMDAT section. */ |
|
struct debug_section *sec; |
|
sec = calloc (sizeof (struct debug_section), 1); |
|
if (sec == NULL) |
|
error (1, errno, |
|
- "%s: Could not allocate more macro sections", |
|
- dso->filename); |
|
- sec->name = ".debug_macro"; |
|
+ "%s: Could not allocate more %s sections", |
|
+ dso->filename, name); |
|
+ sec->name = name; |
|
|
|
- struct debug_section *macro_sec = debug_sec; |
|
- while (macro_sec->next != NULL) |
|
- macro_sec = macro_sec->next; |
|
+ struct debug_section *multi_sec = debug_sec; |
|
+ while (multi_sec->next != NULL) |
|
+ multi_sec = multi_sec->next; |
|
|
|
- macro_sec->next = sec; |
|
+ multi_sec->next = sec; |
|
debug_sec = sec; |
|
} |
|
} |
|
@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso) |
|
+ (dso->shdr[i].sh_type == SHT_RELA), |
|
debug_sections[j].name) == 0) |
|
{ |
|
- if (j == DEBUG_MACRO) |
|
+ if (j == DEBUG_MACRO || j == DEBUG_TYPES) |
|
{ |
|
/* Pick the correct one. */ |
|
int rel_target = dso->shdr[i].sh_info; |
|
- struct debug_section *macro_sec = &debug_sections[j]; |
|
- while (macro_sec != NULL) |
|
+ struct debug_section *multi_sec = &debug_sections[j]; |
|
+ while (multi_sec != NULL) |
|
{ |
|
- if (macro_sec->sec == rel_target) |
|
+ if (multi_sec->sec == rel_target) |
|
{ |
|
- macro_sec->relsec = i; |
|
+ multi_sec->relsec = i; |
|
break; |
|
} |
|
- macro_sec = macro_sec->next; |
|
+ multi_sec = multi_sec->next; |
|
} |
|
- if (macro_sec == NULL) |
|
- error (0, 1, "No .debug_macro reloc section: %s", |
|
- dso->filename); |
|
+ if (multi_sec == NULL) |
|
+ error (0, 1, "No %s reloc section: %s", |
|
+ debug_sections[j].name, dso->filename); |
|
} |
|
else |
|
debug_sections[j].relsec = i; |
|
@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso) |
|
if (debug_sections[DEBUG_INFO].data == NULL) |
|
return 0; |
|
|
|
- unsigned char *ptr, *endcu, *endsec; |
|
- uint32_t value; |
|
- htab_t abbrev; |
|
- struct abbrev_tag tag, *t; |
|
+ unsigned char *ptr, *endsec; |
|
int phase; |
|
bool info_rel_updated = false; |
|
+ bool types_rel_updated = false; |
|
bool macro_rel_updated = false; |
|
|
|
for (phase = 0; phase < 2; phase++) |
|
@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso) |
|
break; |
|
|
|
rel_updated = false; |
|
- if (edit_info (dso, phase)) |
|
- return 1; |
|
+ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO])) |
|
+ return 1; |
|
|
|
/* Remember whether any .debug_info relocations might need |
|
to be updated. */ |
|
info_rel_updated = rel_updated; |
|
|
|
+ rel_updated = false; |
|
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; |
|
+ while (types_sec != NULL) |
|
+ { |
|
+ if (edit_info (dso, phase, types_sec)) |
|
+ return 1; |
|
+ types_sec = types_sec->next; |
|
+ } |
|
+ |
|
+ /* Remember whether any .debug_types relocations might need |
|
+ to be updated. */ |
|
+ types_rel_updated = rel_updated; |
|
+ |
|
/* We might have to recalculate/rewrite the debug_line |
|
section. We need to do that before going into phase one |
|
so we have all new offsets. We do this separately from |
|
@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso) |
|
|
|
/* After phase 1 we might have rewritten the debug_info with |
|
new strp, strings and/or linep offsets. */ |
|
- if (need_strp_update || need_string_replacement || need_stmt_update) |
|
+ if (need_strp_update || need_string_replacement || need_stmt_update) { |
|
dirty_section (DEBUG_INFO); |
|
+ if (debug_sections[DEBUG_TYPES].data != NULL) |
|
+ dirty_section (DEBUG_TYPES); |
|
+ } |
|
if (need_strp_update || need_stmt_update) |
|
dirty_section (DEBUG_MACRO); |
|
if (need_stmt_update) |
|
@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso) |
|
/* Update any relocations addends we might have touched. */ |
|
if (info_rel_updated) |
|
update_rela_data (dso, &debug_sections[DEBUG_INFO]); |
|
+ if (types_rel_updated) |
|
+ { |
|
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; |
|
+ while (types_sec != NULL) |
|
+ { |
|
+ update_rela_data (dso, types_sec); |
|
+ types_sec = types_sec->next; |
|
+ } |
|
+ } |
|
|
|
if (macro_rel_updated) |
|
{ |
|
@@ -3037,6 +3063,17 @@ main (int argc, char *argv[]) |
|
macro_sec = next; |
|
} |
|
|
|
+ /* In case there were multiple (COMDAT) .debug_types sections, |
|
+ free them. */ |
|
+ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; |
|
+ types_sec = types_sec->next; |
|
+ while (types_sec != NULL) |
|
+ { |
|
+ struct debug_section *next = types_sec->next; |
|
+ free (types_sec); |
|
+ types_sec = next; |
|
+ } |
|
+ |
|
poptFreeContext (optCon); |
|
|
|
return 0; |
|
-- |
|
2.18.4 |
|
|
|
|