d3c2ef0ac8
Resolves: #1380961 eu-strip on rust libraries breaks dynamic symbols
93 lines
3.4 KiB
Diff
93 lines
3.4 KiB
Diff
commit 7bf4b63a4980788e6c1969cae02f0483e79c069f
|
|
Author: Mark Wielaard <mjw@redhat.com>
|
|
Date: Thu Oct 6 16:06:32 2016 +0200
|
|
|
|
strip: Don't remove real symbols from allocated symbol tables.
|
|
|
|
Having a symbol in an allocated symbol table (like .dynsym) that
|
|
points to an unallocated section is wrong. Traditionally strip
|
|
has removed such symbols if they are section or group symbols.
|
|
But removing a real symbol from an allocate symbol table is hard
|
|
and probably a mistake. Really removing it means rewriting the
|
|
dynamic segment and hash sections. Since we don't do that, don't
|
|
remove the symbol (and corrupt the ELF file). Do warn and set
|
|
the symbol section to SHN_UNDEF.
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1380961
|
|
|
|
Signed-off-by: Mark Wielaard <mjw@redhat.com>
|
|
|
|
diff --git a/src/ChangeLog b/src/ChangeLog
|
|
index e5b3b20..70d11f2 100644
|
|
--- a/src/ChangeLog
|
|
+++ b/src/ChangeLog
|
|
@@ -1,3 +1,8 @@
|
|
+2016-10-06 Mark Wielaard <mjw@redhat.com>
|
|
+
|
|
+ * strip.c (handle_elf): Don't remove real symbols from allocated
|
|
+ symbol tables.
|
|
+
|
|
2016-08-25 Mark Wielaard <mjw@redhat.com>
|
|
|
|
* strip.c (handle_elf): Recompress with ELF_CHF_FORCE.
|
|
diff --git a/src/strip.c b/src/strip.c
|
|
index da093e9..819b67e 100644
|
|
--- a/src/strip.c
|
|
+++ b/src/strip.c
|
|
@@ -1341,15 +1341,12 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
|
|
|
|
/* Get the full section index, if necessary from the
|
|
XINDEX table. */
|
|
- if (sym->st_shndx != SHN_XINDEX)
|
|
- sec = shdr_info[sym->st_shndx].idx;
|
|
- else
|
|
- {
|
|
- elf_assert (shndxdata != NULL
|
|
- && shndxdata->d_buf != NULL);
|
|
-
|
|
- sec = shdr_info[xshndx].idx;
|
|
- }
|
|
+ if (sym->st_shndx == SHN_XINDEX)
|
|
+ elf_assert (shndxdata != NULL
|
|
+ && shndxdata->d_buf != NULL);
|
|
+ size_t sidx = (sym->st_shndx != SHN_XINDEX
|
|
+ ? sym->st_shndx : xshndx);
|
|
+ sec = shdr_info[sidx].idx;
|
|
|
|
if (sec != 0)
|
|
{
|
|
@@ -1387,6 +1384,24 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
|
|
shdr_info[cnt].shdr.sh_info = destidx - 1;
|
|
}
|
|
}
|
|
+ else if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0
|
|
+ && GELF_ST_TYPE (sym->st_info) != STT_SECTION
|
|
+ && shdr_info[sidx].shdr.sh_type != SHT_GROUP)
|
|
+ {
|
|
+ /* Removing a real symbol from an allocated
|
|
+ symbol table is hard and probably a
|
|
+ mistake. Really removing it means
|
|
+ rewriting the dynamic segment and hash
|
|
+ sections. Just warn and set the symbol
|
|
+ section to UNDEF. */
|
|
+ error (0, 0,
|
|
+ gettext ("Cannot remove symbol [%zd] from allocated symbol table [%zd]"), inner, cnt);
|
|
+ sym->st_shndx = SHN_UNDEF;
|
|
+ if (gelf_update_sym (shdr_info[cnt].data, destidx,
|
|
+ sym) == 0)
|
|
+ INTERNAL_ERROR (fname);
|
|
+ shdr_info[cnt].newsymidx[inner] = destidx++;
|
|
+ }
|
|
else if (debug_fname != NULL
|
|
&& shdr_info[cnt].debug_data == NULL)
|
|
/* The symbol points to a section that is discarded
|
|
@@ -1394,8 +1409,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
|
|
this is a section or group signature symbol
|
|
for a section which has been removed. */
|
|
{
|
|
- size_t sidx = (sym->st_shndx != SHN_XINDEX
|
|
- ? sym->st_shndx : xshndx);
|
|
elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
|
|
|| ((shdr_info[sidx].shdr.sh_type
|
|
== SHT_GROUP)
|