|
|
a5e32e |
From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001
|
|
|
a5e32e |
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
|
|
a5e32e |
Date: Sat, 1 Aug 2020 10:43:12 +0200
|
|
|
a5e32e |
Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to
|
|
|
a5e32e |
edit_info().
|
|
|
a5e32e |
|
|
|
a5e32e |
---
|
|
|
a5e32e |
tools/debugedit.c | 672 +++++++++++++++++++++++-----------------------
|
|
|
a5e32e |
1 file changed, 343 insertions(+), 329 deletions(-)
|
|
|
a5e32e |
|
|
|
a5e32e |
diff --git a/tools/debugedit.c b/tools/debugedit.c
|
|
|
a5e32e |
index a351adec8..cad0cc349 100644
|
|
|
a5e32e |
--- a/tools/debugedit.c
|
|
|
a5e32e |
+++ b/tools/debugedit.c
|
|
|
a5e32e |
@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b)
|
|
|
a5e32e |
return 0;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
+static int
|
|
|
a5e32e |
+edit_info (DSO *dso, int phase)
|
|
|
a5e32e |
+{
|
|
|
a5e32e |
+ unsigned char *ptr, *endcu, *endsec;
|
|
|
a5e32e |
+ uint32_t value;
|
|
|
a5e32e |
+ htab_t abbrev;
|
|
|
a5e32e |
+ struct abbrev_tag tag, *t;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ ptr = debug_sections[DEBUG_INFO].data;
|
|
|
a5e32e |
+ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
|
|
|
a5e32e |
+ endsec = ptr + debug_sections[DEBUG_INFO].size;
|
|
|
a5e32e |
+ while (ptr < endsec)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ if (ptr + 11 > endsec)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: .debug_info CU header too small",
|
|
|
a5e32e |
+ dso->filename);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ endcu = ptr + 4;
|
|
|
a5e32e |
+ endcu += read_32 (ptr);
|
|
|
a5e32e |
+ if (endcu == ptr + 0xffffffff)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ if (endcu > endsec)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: .debug_info too small", dso->filename);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ cu_version = read_16 (ptr);
|
|
|
a5e32e |
+ if (cu_version != 2 && cu_version != 3 && cu_version != 4)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
|
|
|
a5e32e |
+ cu_version);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ value = read_32_relocated (ptr);
|
|
|
a5e32e |
+ if (value >= debug_sections[DEBUG_ABBREV].size)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ if (debug_sections[DEBUG_ABBREV].data == NULL)
|
|
|
a5e32e |
+ error (0, 0, "%s: .debug_abbrev not present", dso->filename);
|
|
|
a5e32e |
+ else
|
|
|
a5e32e |
+ error (0, 0, "%s: DWARF CU abbrev offset too large",
|
|
|
a5e32e |
+ dso->filename);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ if (ptr_size == 0)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ ptr_size = read_8 (ptr);
|
|
|
a5e32e |
+ if (ptr_size != 4 && ptr_size != 8)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: Invalid DWARF pointer size %d",
|
|
|
a5e32e |
+ dso->filename, ptr_size);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+ else if (read_8 (ptr) != ptr_size)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: DWARF pointer size differs between CUs",
|
|
|
a5e32e |
+ dso->filename);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ abbrev = read_abbrev (dso,
|
|
|
a5e32e |
+ debug_sections[DEBUG_ABBREV].data + value);
|
|
|
a5e32e |
+ if (abbrev == NULL)
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ while (ptr < endcu)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ tag.entry = read_uleb128 (ptr);
|
|
|
a5e32e |
+ if (tag.entry == 0)
|
|
|
a5e32e |
+ continue;
|
|
|
a5e32e |
+ t = htab_find_with_hash (abbrev, &tag, tag.entry);
|
|
|
a5e32e |
+ if (t == NULL)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ error (0, 0, "%s: Could not find DWARF abbreviation %d",
|
|
|
a5e32e |
+ dso->filename, tag.entry);
|
|
|
a5e32e |
+ htab_delete (abbrev);
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ ptr = edit_attributes (dso, ptr, t, phase);
|
|
|
a5e32e |
+ if (ptr == NULL)
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ htab_delete (abbrev);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ return 0;
|
|
|
a5e32e |
+}
|
|
|
a5e32e |
+
|
|
|
a5e32e |
static int
|
|
|
a5e32e |
edit_dwarf2 (DSO *dso)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso)
|
|
|
a5e32e |
return 1;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
- if (debug_sections[DEBUG_INFO].data != NULL)
|
|
|
a5e32e |
+ if (debug_sections[DEBUG_INFO].data == NULL)
|
|
|
a5e32e |
+ return 0;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ unsigned char *ptr, *endcu, *endsec;
|
|
|
a5e32e |
+ uint32_t value;
|
|
|
a5e32e |
+ htab_t abbrev;
|
|
|
a5e32e |
+ struct abbrev_tag tag, *t;
|
|
|
a5e32e |
+ int phase;
|
|
|
a5e32e |
+ bool info_rel_updated = false;
|
|
|
a5e32e |
+ bool macro_rel_updated = false;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ for (phase = 0; phase < 2; phase++)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- unsigned char *ptr, *endcu, *endsec;
|
|
|
a5e32e |
- uint32_t value;
|
|
|
a5e32e |
- htab_t abbrev;
|
|
|
a5e32e |
- struct abbrev_tag tag, *t;
|
|
|
a5e32e |
- int phase;
|
|
|
a5e32e |
- bool info_rel_updated = false;
|
|
|
a5e32e |
- bool macro_rel_updated = false;
|
|
|
a5e32e |
+ /* If we don't need to update anyhing, skip phase 1. */
|
|
|
a5e32e |
+ if (phase == 1
|
|
|
a5e32e |
+ && !need_strp_update
|
|
|
a5e32e |
+ && !need_string_replacement
|
|
|
a5e32e |
+ && !need_stmt_update)
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
|
|
|
a5e32e |
- for (phase = 0; phase < 2; phase++)
|
|
|
a5e32e |
+ rel_updated = false;
|
|
|
a5e32e |
+ if (edit_info (dso, phase))
|
|
|
a5e32e |
+ return 1;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* Remember whether any .debug_info relocations might need
|
|
|
a5e32e |
+ to be updated. */
|
|
|
a5e32e |
+ info_rel_updated = rel_updated;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* We might have to recalculate/rewrite the debug_line
|
|
|
a5e32e |
+ section. We need to do that before going into phase one
|
|
|
a5e32e |
+ so we have all new offsets. We do this separately from
|
|
|
a5e32e |
+ scanning the dirs/file names because the DW_AT_stmt_lists
|
|
|
a5e32e |
+ might not be in order or skip some padding we might have
|
|
|
a5e32e |
+ to (re)move. */
|
|
|
a5e32e |
+ if (phase == 0 && need_stmt_update)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- /* If we don't need to update anyhing, skip phase 1. */
|
|
|
a5e32e |
- if (phase == 1
|
|
|
a5e32e |
- && !need_strp_update
|
|
|
a5e32e |
- && !need_string_replacement
|
|
|
a5e32e |
- && !need_stmt_update)
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
+ edit_dwarf2_line (dso);
|
|
|
a5e32e |
|
|
|
a5e32e |
- ptr = debug_sections[DEBUG_INFO].data;
|
|
|
a5e32e |
- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
|
|
|
a5e32e |
- rel_updated = false;
|
|
|
a5e32e |
- endsec = ptr + debug_sections[DEBUG_INFO].size;
|
|
|
a5e32e |
- while (ptr < endsec)
|
|
|
a5e32e |
+ /* The line table programs will be moved
|
|
|
a5e32e |
+ forward/backwards a bit in the new data. Update the
|
|
|
a5e32e |
+ debug_line relocations to the new offsets. */
|
|
|
a5e32e |
+ int rndx = debug_sections[DEBUG_LINE].relsec;
|
|
|
a5e32e |
+ if (rndx != 0)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- if (ptr + 11 > endsec)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- error (0, 0, "%s: .debug_info CU header too small",
|
|
|
a5e32e |
- dso->filename);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- endcu = ptr + 4;
|
|
|
a5e32e |
- endcu += read_32 (ptr);
|
|
|
a5e32e |
- if (endcu == ptr + 0xffffffff)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- if (endcu > endsec)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- error (0, 0, "%s: .debug_info too small", dso->filename);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- cu_version = read_16 (ptr);
|
|
|
a5e32e |
- if (cu_version != 2 && cu_version != 3 && cu_version != 4)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
|
|
|
a5e32e |
- cu_version);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- value = read_32_relocated (ptr);
|
|
|
a5e32e |
- if (value >= debug_sections[DEBUG_ABBREV].size)
|
|
|
a5e32e |
+ LINE_REL *rbuf;
|
|
|
a5e32e |
+ size_t rels;
|
|
|
a5e32e |
+ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
|
|
|
a5e32e |
+ int rtype = dso->shdr[rndx].sh_type;
|
|
|
a5e32e |
+ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
|
|
|
a5e32e |
+ rbuf = malloc (rels * sizeof (LINE_REL));
|
|
|
a5e32e |
+ if (rbuf == NULL)
|
|
|
a5e32e |
+ error (1, errno, "%s: Could not allocate line relocations",
|
|
|
a5e32e |
+ dso->filename);
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* Sort them by offset into section. */
|
|
|
a5e32e |
+ for (size_t i = 0; i < rels; i++)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- if (debug_sections[DEBUG_ABBREV].data == NULL)
|
|
|
a5e32e |
- error (0, 0, "%s: .debug_abbrev not present", dso->filename);
|
|
|
a5e32e |
+ if (rtype == SHT_RELA)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ GElf_Rela rela;
|
|
|
a5e32e |
+ if (gelf_getrela (rdata, i, &rela) == NULL)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
+ rbuf[i].r_offset = rela.r_offset;
|
|
|
a5e32e |
+ rbuf[i].ndx = i;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
else
|
|
|
a5e32e |
- error (0, 0, "%s: DWARF CU abbrev offset too large",
|
|
|
a5e32e |
- dso->filename);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- if (ptr_size == 0)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- ptr_size = read_8 (ptr);
|
|
|
a5e32e |
- if (ptr_size != 4 && ptr_size != 8)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- error (0, 0, "%s: Invalid DWARF pointer size %d",
|
|
|
a5e32e |
- dso->filename, ptr_size);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
+ GElf_Rel rel;
|
|
|
a5e32e |
+ if (gelf_getrel (rdata, i, &rel) == NULL)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
+ rbuf[i].r_offset = rel.r_offset;
|
|
|
a5e32e |
+ rbuf[i].ndx = i;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
}
|
|
|
a5e32e |
- else if (read_8 (ptr) != ptr_size)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- error (0, 0, "%s: DWARF pointer size differs between CUs",
|
|
|
a5e32e |
- dso->filename);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
|
|
|
a5e32e |
|
|
|
a5e32e |
- abbrev = read_abbrev (dso,
|
|
|
a5e32e |
- debug_sections[DEBUG_ABBREV].data + value);
|
|
|
a5e32e |
- if (abbrev == NULL)
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- while (ptr < endcu)
|
|
|
a5e32e |
+ size_t lndx = 0;
|
|
|
a5e32e |
+ for (size_t i = 0; i < rels; i++)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- tag.entry = read_uleb128 (ptr);
|
|
|
a5e32e |
- if (tag.entry == 0)
|
|
|
a5e32e |
- continue;
|
|
|
a5e32e |
- t = htab_find_with_hash (abbrev, &tag, tag.entry);
|
|
|
a5e32e |
- if (t == NULL)
|
|
|
a5e32e |
+ /* These relocations only happen in ET_REL files
|
|
|
a5e32e |
+ and are section offsets. */
|
|
|
a5e32e |
+ GElf_Addr r_offset;
|
|
|
a5e32e |
+ size_t ndx = rbuf[i].ndx;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ GElf_Rel rel;
|
|
|
a5e32e |
+ GElf_Rela rela;
|
|
|
a5e32e |
+ if (rtype == SHT_RELA)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- error (0, 0, "%s: Could not find DWARF abbreviation %d",
|
|
|
a5e32e |
- dso->filename, tag.entry);
|
|
|
a5e32e |
- htab_delete (abbrev);
|
|
|
a5e32e |
- return 1;
|
|
|
a5e32e |
+ if (gelf_getrela (rdata, ndx, &rela) == NULL)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
+ r_offset = rela.r_offset;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+ else
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ if (gelf_getrel (rdata, ndx, &rel) == NULL)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
+ r_offset = rel.r_offset;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
- ptr = edit_attributes (dso, ptr, t, phase);
|
|
|
a5e32e |
- if (ptr == NULL)
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ while (lndx < dso->lines.used
|
|
|
a5e32e |
+ && r_offset > (dso->lines.table[lndx].old_idx
|
|
|
a5e32e |
+ + 4
|
|
|
a5e32e |
+ + dso->lines.table[lndx].unit_length))
|
|
|
a5e32e |
+ lndx++;
|
|
|
a5e32e |
|
|
|
a5e32e |
- htab_delete (abbrev);
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ if (lndx >= dso->lines.used)
|
|
|
a5e32e |
+ error (1, 0,
|
|
|
a5e32e |
+ ".debug_line relocation offset out of range");
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* Remember whether any .debug_info relocations might need
|
|
|
a5e32e |
- to be updated. */
|
|
|
a5e32e |
- info_rel_updated = rel_updated;
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* We might have to recalculate/rewrite the debug_line
|
|
|
a5e32e |
- section. We need to do that before going into phase one
|
|
|
a5e32e |
- so we have all new offsets. We do this separately from
|
|
|
a5e32e |
- scanning the dirs/file names because the DW_AT_stmt_lists
|
|
|
a5e32e |
- might not be in order or skip some padding we might have
|
|
|
a5e32e |
- to (re)move. */
|
|
|
a5e32e |
- if (phase == 0 && need_stmt_update)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- edit_dwarf2_line (dso);
|
|
|
a5e32e |
+ /* Offset (pointing into the line program) moves
|
|
|
a5e32e |
+ from old to new index including the header
|
|
|
a5e32e |
+ size diff. */
|
|
|
a5e32e |
+ r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
|
|
|
a5e32e |
+ - dso->lines.table[lndx].old_idx)
|
|
|
a5e32e |
+ + dso->lines.table[lndx].size_diff);
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* The line table programs will be moved
|
|
|
a5e32e |
- forward/backwards a bit in the new data. Update the
|
|
|
a5e32e |
- debug_line relocations to the new offsets. */
|
|
|
a5e32e |
- int rndx = debug_sections[DEBUG_LINE].relsec;
|
|
|
a5e32e |
- if (rndx != 0)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- LINE_REL *rbuf;
|
|
|
a5e32e |
- size_t rels;
|
|
|
a5e32e |
- Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
|
|
|
a5e32e |
- int rtype = dso->shdr[rndx].sh_type;
|
|
|
a5e32e |
- rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
|
|
|
a5e32e |
- rbuf = malloc (rels * sizeof (LINE_REL));
|
|
|
a5e32e |
- if (rbuf == NULL)
|
|
|
a5e32e |
- error (1, errno, "%s: Could not allocate line relocations",
|
|
|
a5e32e |
- dso->filename);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* Sort them by offset into section. */
|
|
|
a5e32e |
- for (size_t i = 0; i < rels; i++)
|
|
|
a5e32e |
+ if (rtype == SHT_RELA)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- if (rtype == SHT_RELA)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- GElf_Rela rela;
|
|
|
a5e32e |
- if (gelf_getrela (rdata, i, &rela) == NULL)
|
|
|
a5e32e |
- error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- rbuf[i].r_offset = rela.r_offset;
|
|
|
a5e32e |
- rbuf[i].ndx = i;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
- else
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- GElf_Rel rel;
|
|
|
a5e32e |
- if (gelf_getrel (rdata, i, &rel) == NULL)
|
|
|
a5e32e |
- error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- rbuf[i].r_offset = rel.r_offset;
|
|
|
a5e32e |
- rbuf[i].ndx = i;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ rela.r_offset = r_offset;
|
|
|
a5e32e |
+ if (gelf_update_rela (rdata, ndx, &rela) == 0)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't update relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
}
|
|
|
a5e32e |
- qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- size_t lndx = 0;
|
|
|
a5e32e |
- for (size_t i = 0; i < rels; i++)
|
|
|
a5e32e |
+ else
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- /* These relocations only happen in ET_REL files
|
|
|
a5e32e |
- and are section offsets. */
|
|
|
a5e32e |
- GElf_Addr r_offset;
|
|
|
a5e32e |
- size_t ndx = rbuf[i].ndx;
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- GElf_Rel rel;
|
|
|
a5e32e |
- GElf_Rela rela;
|
|
|
a5e32e |
- if (rtype == SHT_RELA)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- if (gelf_getrela (rdata, ndx, &rela) == NULL)
|
|
|
a5e32e |
- error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- r_offset = rela.r_offset;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
- else
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- if (gelf_getrel (rdata, ndx, &rel) == NULL)
|
|
|
a5e32e |
- error (1, 0, "Couldn't get relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- r_offset = rel.r_offset;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- while (lndx < dso->lines.used
|
|
|
a5e32e |
- && r_offset > (dso->lines.table[lndx].old_idx
|
|
|
a5e32e |
- + 4
|
|
|
a5e32e |
- + dso->lines.table[lndx].unit_length))
|
|
|
a5e32e |
- lndx++;
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- if (lndx >= dso->lines.used)
|
|
|
a5e32e |
- error (1, 0,
|
|
|
a5e32e |
- ".debug_line relocation offset out of range");
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* Offset (pointing into the line program) moves
|
|
|
a5e32e |
- from old to new index including the header
|
|
|
a5e32e |
- size diff. */
|
|
|
a5e32e |
- r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
|
|
|
a5e32e |
- - dso->lines.table[lndx].old_idx)
|
|
|
a5e32e |
- + dso->lines.table[lndx].size_diff);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- if (rtype == SHT_RELA)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- rela.r_offset = r_offset;
|
|
|
a5e32e |
- if (gelf_update_rela (rdata, ndx, &rela) == 0)
|
|
|
a5e32e |
- error (1, 0, "Couldn't update relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
- else
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- rel.r_offset = r_offset;
|
|
|
a5e32e |
- if (gelf_update_rel (rdata, ndx, &rel) == 0)
|
|
|
a5e32e |
- error (1, 0, "Couldn't update relocation: %s",
|
|
|
a5e32e |
- elf_errmsg (-1));
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ rel.r_offset = r_offset;
|
|
|
a5e32e |
+ if (gelf_update_rel (rdata, ndx, &rel) == 0)
|
|
|
a5e32e |
+ error (1, 0, "Couldn't update relocation: %s",
|
|
|
a5e32e |
+ elf_errmsg (-1));
|
|
|
a5e32e |
}
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
|
|
|
a5e32e |
- free (rbuf);
|
|
|
a5e32e |
}
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
|
|
|
a5e32e |
+ free (rbuf);
|
|
|
a5e32e |
}
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* The .debug_macro section also contains offsets into the
|
|
|
a5e32e |
- .debug_str section and references to the .debug_line
|
|
|
a5e32e |
- tables, so we need to update those as well if we update
|
|
|
a5e32e |
- the strings or the stmts. */
|
|
|
a5e32e |
- if ((need_strp_update || need_stmt_update)
|
|
|
a5e32e |
- && debug_sections[DEBUG_MACRO].data)
|
|
|
a5e32e |
+ /* The .debug_macro section also contains offsets into the
|
|
|
a5e32e |
+ .debug_str section and references to the .debug_line
|
|
|
a5e32e |
+ tables, so we need to update those as well if we update
|
|
|
a5e32e |
+ the strings or the stmts. */
|
|
|
a5e32e |
+ if ((need_strp_update || need_stmt_update)
|
|
|
a5e32e |
+ && debug_sections[DEBUG_MACRO].data)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ /* There might be multiple (COMDAT) .debug_macro sections. */
|
|
|
a5e32e |
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
|
|
|
a5e32e |
+ while (macro_sec != NULL)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- /* There might be multiple (COMDAT) .debug_macro sections. */
|
|
|
a5e32e |
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
|
|
|
a5e32e |
- while (macro_sec != NULL)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- setup_relbuf(dso, macro_sec, &reltype);
|
|
|
a5e32e |
- rel_updated = false;
|
|
|
a5e32e |
+ setup_relbuf(dso, macro_sec, &reltype);
|
|
|
a5e32e |
+ rel_updated = false;
|
|
|
a5e32e |
|
|
|
a5e32e |
- ptr = macro_sec->data;
|
|
|
a5e32e |
- endsec = ptr + macro_sec->size;
|
|
|
a5e32e |
- int op = 0, macro_version, macro_flags;
|
|
|
a5e32e |
- int offset_len = 4, line_offset = 0;
|
|
|
a5e32e |
+ ptr = macro_sec->data;
|
|
|
a5e32e |
+ endsec = ptr + macro_sec->size;
|
|
|
a5e32e |
+ int op = 0, macro_version, macro_flags;
|
|
|
a5e32e |
+ int offset_len = 4, line_offset = 0;
|
|
|
a5e32e |
|
|
|
a5e32e |
- while (ptr < endsec)
|
|
|
a5e32e |
+ while (ptr < endsec)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ if (!op)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- if (!op)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- macro_version = read_16 (ptr);
|
|
|
a5e32e |
- macro_flags = read_8 (ptr);
|
|
|
a5e32e |
- if (macro_version < 4 || macro_version > 5)
|
|
|
a5e32e |
- error (1, 0, "unhandled .debug_macro version: %d",
|
|
|
a5e32e |
- macro_version);
|
|
|
a5e32e |
- if ((macro_flags & ~2) != 0)
|
|
|
a5e32e |
- error (1, 0, "unhandled .debug_macro flags: 0x%x",
|
|
|
a5e32e |
- macro_flags);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- offset_len = (macro_flags & 0x01) ? 8 : 4;
|
|
|
a5e32e |
- line_offset = (macro_flags & 0x02) ? 1 : 0;
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- if (offset_len != 4)
|
|
|
a5e32e |
- error (0, 1,
|
|
|
a5e32e |
- "Cannot handle 8 byte macro offsets: %s",
|
|
|
a5e32e |
- dso->filename);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* Update the line_offset if it is there. */
|
|
|
a5e32e |
- if (line_offset)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- if (phase == 0)
|
|
|
a5e32e |
- ptr += offset_len;
|
|
|
a5e32e |
- else
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- size_t idx, new_idx;
|
|
|
a5e32e |
- idx = do_read_32_relocated (ptr);
|
|
|
a5e32e |
- new_idx = find_new_list_offs (&dso->lines,
|
|
|
a5e32e |
- idx);
|
|
|
a5e32e |
- write_32_relocated (ptr, new_idx);
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ macro_version = read_16 (ptr);
|
|
|
a5e32e |
+ macro_flags = read_8 (ptr);
|
|
|
a5e32e |
+ if (macro_version < 4 || macro_version > 5)
|
|
|
a5e32e |
+ error (1, 0, "unhandled .debug_macro version: %d",
|
|
|
a5e32e |
+ macro_version);
|
|
|
a5e32e |
+ if ((macro_flags & ~2) != 0)
|
|
|
a5e32e |
+ error (1, 0, "unhandled .debug_macro flags: 0x%x",
|
|
|
a5e32e |
+ macro_flags);
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ offset_len = (macro_flags & 0x01) ? 8 : 4;
|
|
|
a5e32e |
+ line_offset = (macro_flags & 0x02) ? 1 : 0;
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ if (offset_len != 4)
|
|
|
a5e32e |
+ error (0, 1,
|
|
|
a5e32e |
+ "Cannot handle 8 byte macro offsets: %s",
|
|
|
a5e32e |
+ dso->filename);
|
|
|
a5e32e |
|
|
|
a5e32e |
- op = read_8 (ptr);
|
|
|
a5e32e |
- if (!op)
|
|
|
a5e32e |
- continue;
|
|
|
a5e32e |
- switch(op)
|
|
|
a5e32e |
+ /* Update the line_offset if it is there. */
|
|
|
a5e32e |
+ if (line_offset)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- case DW_MACRO_GNU_define:
|
|
|
a5e32e |
- case DW_MACRO_GNU_undef:
|
|
|
a5e32e |
- read_uleb128 (ptr);
|
|
|
a5e32e |
- ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
|
|
|
a5e32e |
- + 1);
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- case DW_MACRO_GNU_start_file:
|
|
|
a5e32e |
- read_uleb128 (ptr);
|
|
|
a5e32e |
- read_uleb128 (ptr);
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- case DW_MACRO_GNU_end_file:
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- case DW_MACRO_GNU_define_indirect:
|
|
|
a5e32e |
- case DW_MACRO_GNU_undef_indirect:
|
|
|
a5e32e |
- read_uleb128 (ptr);
|
|
|
a5e32e |
if (phase == 0)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- size_t idx = read_32_relocated (ptr);
|
|
|
a5e32e |
- record_existing_string_entry_idx (&dso->strings,
|
|
|
a5e32e |
- idx);
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ ptr += offset_len;
|
|
|
a5e32e |
else
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- struct stridxentry *entry;
|
|
|
a5e32e |
size_t idx, new_idx;
|
|
|
a5e32e |
idx = do_read_32_relocated (ptr);
|
|
|
a5e32e |
- entry = string_find_entry (&dso->strings, idx);
|
|
|
a5e32e |
- new_idx = strent_offset (entry->entry);
|
|
|
a5e32e |
+ new_idx = find_new_list_offs (&dso->lines,
|
|
|
a5e32e |
+ idx);
|
|
|
a5e32e |
write_32_relocated (ptr, new_idx);
|
|
|
a5e32e |
}
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- case DW_MACRO_GNU_transparent_include:
|
|
|
a5e32e |
- ptr += offset_len;
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
- default:
|
|
|
a5e32e |
- error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
|
|
|
a5e32e |
- break;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
- if (rel_updated)
|
|
|
a5e32e |
- macro_rel_updated = true;
|
|
|
a5e32e |
- macro_sec = macro_sec->next;
|
|
|
a5e32e |
+ op = read_8 (ptr);
|
|
|
a5e32e |
+ if (!op)
|
|
|
a5e32e |
+ continue;
|
|
|
a5e32e |
+ switch(op)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ case DW_MACRO_GNU_define:
|
|
|
a5e32e |
+ case DW_MACRO_GNU_undef:
|
|
|
a5e32e |
+ read_uleb128 (ptr);
|
|
|
a5e32e |
+ ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
|
|
|
a5e32e |
+ + 1);
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ case DW_MACRO_GNU_start_file:
|
|
|
a5e32e |
+ read_uleb128 (ptr);
|
|
|
a5e32e |
+ read_uleb128 (ptr);
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ case DW_MACRO_GNU_end_file:
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ case DW_MACRO_GNU_define_indirect:
|
|
|
a5e32e |
+ case DW_MACRO_GNU_undef_indirect:
|
|
|
a5e32e |
+ read_uleb128 (ptr);
|
|
|
a5e32e |
+ if (phase == 0)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ size_t idx = read_32_relocated (ptr);
|
|
|
a5e32e |
+ record_existing_string_entry_idx (&dso->strings,
|
|
|
a5e32e |
+ idx);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+ else
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ struct stridxentry *entry;
|
|
|
a5e32e |
+ size_t idx, new_idx;
|
|
|
a5e32e |
+ idx = do_read_32_relocated (ptr);
|
|
|
a5e32e |
+ entry = string_find_entry (&dso->strings, idx);
|
|
|
a5e32e |
+ new_idx = strent_offset (entry->entry);
|
|
|
a5e32e |
+ write_32_relocated (ptr, new_idx);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ case DW_MACRO_GNU_transparent_include:
|
|
|
a5e32e |
+ ptr += offset_len;
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ default:
|
|
|
a5e32e |
+ error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
|
|
|
a5e32e |
+ break;
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
}
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* Same for the debug_str section. Make sure everything is
|
|
|
a5e32e |
- in place for phase 1 updating of debug_info
|
|
|
a5e32e |
- references. */
|
|
|
a5e32e |
- if (phase == 0 && need_strp_update)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- Strtab *strtab = dso->strings.str_tab;
|
|
|
a5e32e |
- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
|
|
|
a5e32e |
- int strndx = debug_sections[DEBUG_STR].sec;
|
|
|
a5e32e |
- Elf_Scn *strscn = dso->scn[strndx];
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* Out with the old. */
|
|
|
a5e32e |
- strdata->d_size = 0;
|
|
|
a5e32e |
- /* In with the new. */
|
|
|
a5e32e |
- strdata = elf_newdata (strscn);
|
|
|
a5e32e |
-
|
|
|
a5e32e |
- /* We really should check whether we had enough memory,
|
|
|
a5e32e |
- but the old ebl version will just abort on out of
|
|
|
a5e32e |
- memory... */
|
|
|
a5e32e |
- strtab_finalize (strtab, strdata);
|
|
|
a5e32e |
- debug_sections[DEBUG_STR].size = strdata->d_size;
|
|
|
a5e32e |
- dso->strings.str_buf = strdata->d_buf;
|
|
|
a5e32e |
+ if (rel_updated)
|
|
|
a5e32e |
+ macro_rel_updated = true;
|
|
|
a5e32e |
+ macro_sec = macro_sec->next;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
|
|
|
a5e32e |
+ /* Same for the debug_str section. Make sure everything is
|
|
|
a5e32e |
+ in place for phase 1 updating of debug_info
|
|
|
a5e32e |
+ references. */
|
|
|
a5e32e |
+ if (phase == 0 && need_strp_update)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ Strtab *strtab = dso->strings.str_tab;
|
|
|
a5e32e |
+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
|
|
|
a5e32e |
+ int strndx = debug_sections[DEBUG_STR].sec;
|
|
|
a5e32e |
+ Elf_Scn *strscn = dso->scn[strndx];
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* Out with the old. */
|
|
|
a5e32e |
+ strdata->d_size = 0;
|
|
|
a5e32e |
+ /* In with the new. */
|
|
|
a5e32e |
+ strdata = elf_newdata (strscn);
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* We really should check whether we had enough memory,
|
|
|
a5e32e |
+ but the old ebl version will just abort on out of
|
|
|
a5e32e |
+ memory... */
|
|
|
a5e32e |
+ strtab_finalize (strtab, strdata);
|
|
|
a5e32e |
+ debug_sections[DEBUG_STR].size = strdata->d_size;
|
|
|
a5e32e |
+ dso->strings.str_buf = strdata->d_buf;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* After phase 1 we might have rewritten the debug_info with
|
|
|
a5e32e |
- new strp, strings and/or linep offsets. */
|
|
|
a5e32e |
- if (need_strp_update || need_string_replacement || need_stmt_update)
|
|
|
a5e32e |
- dirty_section (DEBUG_INFO);
|
|
|
a5e32e |
- if (need_strp_update || need_stmt_update)
|
|
|
a5e32e |
- dirty_section (DEBUG_MACRO);
|
|
|
a5e32e |
- if (need_stmt_update)
|
|
|
a5e32e |
- dirty_section (DEBUG_LINE);
|
|
|
a5e32e |
+ }
|
|
|
a5e32e |
+
|
|
|
a5e32e |
+ /* After phase 1 we might have rewritten the debug_info with
|
|
|
a5e32e |
+ new strp, strings and/or linep offsets. */
|
|
|
a5e32e |
+ if (need_strp_update || need_string_replacement || need_stmt_update)
|
|
|
a5e32e |
+ dirty_section (DEBUG_INFO);
|
|
|
a5e32e |
+ if (need_strp_update || need_stmt_update)
|
|
|
a5e32e |
+ dirty_section (DEBUG_MACRO);
|
|
|
a5e32e |
+ if (need_stmt_update)
|
|
|
a5e32e |
+ dirty_section (DEBUG_LINE);
|
|
|
a5e32e |
|
|
|
a5e32e |
- /* Update any relocations addends we might have touched. */
|
|
|
a5e32e |
- if (info_rel_updated)
|
|
|
a5e32e |
- update_rela_data (dso, &debug_sections[DEBUG_INFO]);
|
|
|
a5e32e |
+ /* Update any relocations addends we might have touched. */
|
|
|
a5e32e |
+ if (info_rel_updated)
|
|
|
a5e32e |
+ update_rela_data (dso, &debug_sections[DEBUG_INFO]);
|
|
|
a5e32e |
|
|
|
a5e32e |
- if (macro_rel_updated)
|
|
|
a5e32e |
+ if (macro_rel_updated)
|
|
|
a5e32e |
+ {
|
|
|
a5e32e |
+ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
|
|
|
a5e32e |
+ while (macro_sec != NULL)
|
|
|
a5e32e |
{
|
|
|
a5e32e |
- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
|
|
|
a5e32e |
- while (macro_sec != NULL)
|
|
|
a5e32e |
- {
|
|
|
a5e32e |
- update_rela_data (dso, macro_sec);
|
|
|
a5e32e |
- macro_sec = macro_sec->next;
|
|
|
a5e32e |
- }
|
|
|
a5e32e |
+ update_rela_data (dso, macro_sec);
|
|
|
a5e32e |
+ macro_sec = macro_sec->next;
|
|
|
a5e32e |
}
|
|
|
a5e32e |
}
|
|
|
a5e32e |
|
|
|
a5e32e |
--
|
|
|
a5e32e |
2.18.4
|
|
|
a5e32e |
|