[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[committed] Ignore SHT_NOBITS sections in write_dso
Hi,
In a hello world executable, we find a NOBITS section:
...
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[24] .data PROGBITS 0000000000601020 00001020
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 0000000000601030 00001030
0000000000000008 0000000000000000 WA 0 0 1
[26] .comment PROGBITS 0000000000000000 00001030
0000000000000080 0000000000000001 MS 0 0 1
...
For this type of section, the 'Size' indicates the in-memory size, but the
section occupies no space in the file. The 'Offset' locates the "conceptual
placement" in the file.
When we do an objcopy --only-keep-debug on the executable:
...
$ objcopy hello -o hello.debug --only-keep-debug
...
some sections are dropped, but are kept in the section header table, set to
the NOBITS type.
Some of the "conceptual placement" of dropped sections is updated,
f.i. for section .gnu.hash:
...
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
- [ 4] .hash HASH 0000000000400298 00000298
+ [ 4] .hash NOBITS 0000000000400298 00000298
0000000000000024 0000000000000004 A 6 0 8
- [ 5] .gnu.hash GNU_HASH 00000000004002c0 000002c0
+ [ 5] .gnu.hash NOBITS 00000000004002c0 00000298
000000000000001c 0000000000000000 A 6 0 8
...
But for others (f.i. .init_array), it's not:
...
- [18] .eh_frame PROGBITS 00000000004005e0 000005e0
+ [18] .eh_frame NOBITS 00000000004005e0 00000298
00000000000000f0 0000000000000000 A 0 0 8
- [19] .init_array INIT_ARRAY 0000000000600e00 00000e00
+ [19] .init_array NOBITS 0000000000600e00 00000e00
0000000000000008 0000000000000008 WA 0 0 8
...
which puts .init_array's "conceptual placement" in the middle of
.debug_line:
...
[30] .debug_line PROGBITS 0000000000000000 00000c7b
00000000000002d6 0000000000000000 0 0 1
...
which leads to this error when dwz-ing the executable:
...
dwz: Allocatable section in hello.debug after non-allocatable ones
...
There seems to be no reason why we can't do dwz compression when encountering
stray NOBITS sections. OTOH, that introduces the question if and how these
sections sh_offset should be updated. We choose the strategy to not update
the sh_offset of any NOBITS section.
The fix consists of three parts:
- making sure that we don't run into the "Allocatable section in *.debug after
non-allocatable ones" error
- recording the NOBITS sh_offset at the start of write_dso, and reusing those
after the sh_offsets updates (rather than special-casing NOBITS sections in
the update code)
- ensuring that the NOBITS sh_size or sh_addralign does not affect the
sh_offset of other sections
Committed to trunk.
Thanks,
- Tom
Ignore SHT_NOBITS sections in write_dso
2019-07-10 Tom de Vries <tdevries@suse.de>
PR dwz/24251
* dwz.c (write_dso): Ignore SHT_NOBITS sections.
* testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh: New test.
* testsuite/dwz.tests/objcopy-eu-unstrip.sh: New test.
---
dwz.c | 13 +++++++++++++
testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh | 16 ++++++++++++++++
testsuite/dwz.tests/objcopy-eu-unstrip.sh | 12 ++++++++++++
3 files changed, 41 insertions(+)
diff --git a/dwz.c b/dwz.c
index 7f6db58..4457f8c 100644
--- a/dwz.c
+++ b/dwz.c
@@ -10566,6 +10566,10 @@ write_dso (DSO *dso, const char *file, struct stat *st)
GElf_Off distance[dso->ehdr.e_shnum + 1];
/* Array of sections and section header table sorted by file offset. */
unsigned int sorted_section_numbers[dso->ehdr.e_shnum + 1];
+ GElf_Off old_sh_offset[dso->ehdr.e_shnum];
+
+ for (i = 1; i < dso->ehdr.e_shnum; ++i)
+ old_sh_offset[i] = dso->shdr[i].sh_offset;
memset (remove_sections, '\0', sizeof (remove_sections));
ehdr = dso->ehdr;
@@ -10693,6 +10697,8 @@ write_dso (DSO *dso, const char *file, struct stat *st)
&& (dso->shdr[j].sh_size == 0
|| dso->shdr[j].sh_type == SHT_NOBITS))))
continue;
+ else if (dso->shdr[j].sh_type == SHT_NOBITS)
+ continue;
else if ((dso->shdr[j].sh_flags & SHF_ALLOC) != 0)
{
error (0, 0, "Allocatable section in %s after "
@@ -10721,6 +10727,9 @@ write_dso (DSO *dso, const char *file, struct stat *st)
last_shoff = ehdr.e_shoff + ehdr.e_shnum * ehdr.e_shentsize;
continue;
}
+ /* Ignore SHT_NOBITS sections. */
+ if (dso->shdr[j].sh_type == SHT_NOBITS)
+ continue;
dso->shdr[j].sh_offset = last_shoff;
if (dso->shdr[j].sh_addralign > 1)
dso->shdr[j].sh_offset
@@ -10733,6 +10742,10 @@ write_dso (DSO *dso, const char *file, struct stat *st)
}
}
+ for (i = 1; i < dso->ehdr.e_shnum; ++i)
+ if (dso->shdr[i].sh_type == SHT_NOBITS)
+ dso->shdr[i].sh_offset = old_sh_offset[i];
+
verify_sections (dso, sorted_section_numbers, NULL, addsec, addsize,
ehdr);
diff --git a/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh b/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh
new file mode 100644
index 0000000..87cf313
--- /dev/null
+++ b/testsuite/dwz.tests/objcopy-eu-unstrip-multifile.sh
@@ -0,0 +1,16 @@
+cp ../hello 1
+
+objcopy --only-keep-debug 1 1.debug
+objcopy --strip-debug 1 1.stripped
+
+cp 1.debug 2.debug
+
+dwz -m 3 1.debug 2.debug
+
+rm 2.debug
+
+eu-unstrip 1.stripped 1.debug -o 1.unstripped
+
+smaller-than.sh 1.unstripped 1
+
+rm -f 1 1.debug 1.stripped 1.unstripped 3
diff --git a/testsuite/dwz.tests/objcopy-eu-unstrip.sh b/testsuite/dwz.tests/objcopy-eu-unstrip.sh
new file mode 100644
index 0000000..2645d25
--- /dev/null
+++ b/testsuite/dwz.tests/objcopy-eu-unstrip.sh
@@ -0,0 +1,12 @@
+cp ../hello 1
+
+objcopy --only-keep-debug 1 1.debug
+objcopy --strip-debug 1 1.stripped
+
+dwz 1.debug
+
+eu-unstrip 1.stripped 1.debug -o 1.unstripped
+
+smaller-than.sh 1.unstripped 1
+
+rm -f 1 1.debug 1.stripped 1.unstripped