92 lines
3.4 KiB
Diff
92 lines
3.4 KiB
Diff
commit f9fc50c3eced243c0648fb0fbfe2c9877c25e1e4
|
|
Author: Mark Wielaard <mjw@redhat.com>
|
|
Date: Wed Jul 29 17:51:27 2015 +0200
|
|
|
|
unstrip: Handle debuginfo files with missing SHF_INFO_LINK section flags.
|
|
|
|
With GCC 5 there might be a .rela.plt section with SHF_INFO_LINK set.
|
|
Buggy binutils objdump might strip it from the section in the debug file.
|
|
Ignore such differences for relocation sections and put the flag back
|
|
if necessary.
|
|
|
|
Also improve the error message a little by only discarding the already
|
|
matched sections if there is an prelink undo section. Otherwise we will
|
|
report all sections as not matching if the file wasn't prelinked instead
|
|
of just the non-matching sections.
|
|
|
|
New testfiles generated by gcc5 and binutils objdump added.
|
|
|
|
Signed-off-by: Mark Wielaard <mjw@redhat.com>
|
|
|
|
diff --git a/src/unstrip.c b/src/unstrip.c
|
|
index 4a8e5fa..8833094 100644
|
|
--- a/src/unstrip.c
|
|
+++ b/src/unstrip.c
|
|
@@ -867,12 +867,28 @@ compare_symbols_output (const void *a, const void *b)
|
|
|
|
#undef CMP
|
|
|
|
+/* Return true if the flags of the sections match, ignoring the SHF_INFO_LINK
|
|
+ flag if the section contains relocation information. */
|
|
+static bool
|
|
+sections_flags_match (Elf64_Xword sh_flags1, Elf64_Xword sh_flags2,
|
|
+ Elf64_Word sh_type)
|
|
+{
|
|
+ if (sh_type == SHT_REL || sh_type == SHT_RELA)
|
|
+ {
|
|
+ sh_flags1 &= ~SHF_INFO_LINK;
|
|
+ sh_flags2 &= ~SHF_INFO_LINK;
|
|
+ }
|
|
+
|
|
+ return sh_flags1 == sh_flags2;
|
|
+}
|
|
+
|
|
/* Return true iff the flags, size, and name match. */
|
|
static bool
|
|
sections_match (const struct section *sections, size_t i,
|
|
const GElf_Shdr *shdr, const char *name)
|
|
{
|
|
- return (sections[i].shdr.sh_flags == shdr->sh_flags
|
|
+ return (sections_flags_match (sections[i].shdr.sh_flags, shdr->sh_flags,
|
|
+ sections[i].shdr.sh_type)
|
|
&& (sections[i].shdr.sh_size == shdr->sh_size
|
|
|| (sections[i].shdr.sh_size < shdr->sh_size
|
|
&& section_can_shrink (§ions[i].shdr)))
|
|
@@ -930,10 +946,6 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
|
|
struct section *sections,
|
|
size_t nalloc, size_t nsections)
|
|
{
|
|
- /* Clear assignments that might have been bogus. */
|
|
- for (size_t i = 0; i < nalloc; ++i)
|
|
- sections[i].outscn = NULL;
|
|
-
|
|
Elf_Scn *undo = NULL;
|
|
for (size_t i = nalloc; i < nsections; ++i)
|
|
{
|
|
@@ -952,6 +964,10 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
|
|
size_t undo_nalloc = 0;
|
|
if (undo != NULL)
|
|
{
|
|
+ /* Clear assignments that might have been bogus. */
|
|
+ for (size_t i = 0; i < nalloc; ++i)
|
|
+ sections[i].outscn = NULL;
|
|
+
|
|
Elf_Data *undodata = elf_rawdata (undo, NULL);
|
|
ELF_CHECK (undodata != NULL,
|
|
_("cannot read '.gnu.prelink_undo' section: %s"));
|
|
@@ -1500,6 +1516,14 @@ more sections in stripped file than debug file -- arguments reversed?"));
|
|
shdr_mem.sh_size = sec->shdr.sh_size;
|
|
shdr_mem.sh_info = sec->shdr.sh_info;
|
|
shdr_mem.sh_link = sec->shdr.sh_link;
|
|
+
|
|
+ /* Buggy binutils objdump might have stripped the SHF_INFO_LINK
|
|
+ put it back if necessary. */
|
|
+ if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
|
|
+ && sec->shdr.sh_flags != shdr_mem.sh_flags
|
|
+ && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
|
|
+ shdr_mem.sh_flags |= SHF_INFO_LINK;
|
|
+
|
|
if (sec->shdr.sh_link != SHN_UNDEF)
|
|
shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
|
|
if (shdr_mem.sh_flags & SHF_INFO_LINK)
|