On 10/06/2016 07:18 AM, Mark Wielaard wrote: > 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 Works for me. On the test from bugzilla, I get the expected warning: strip: Cannot remove symbol [1550] from allocated symbol table [3] but ldd is perfectly happy with the result. I also tried it with a manual "objcopy -R .rustc" beforehand, which I will probably do in the rpm to prevent that section from even being saved to debuginfo -- just discard it entirely. Strip still works with the same warning and a working result. > --- > src/ChangeLog | 5 +++++ > src/strip.c | 35 ++++++++++++++++++++++++----------- > 2 files changed, 29 insertions(+), 11 deletions(-) > > 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 > + > + * strip.c (handle_elf): Don't remove real symbols from allocated > + symbol tables. > + > 2016-08-25 Mark Wielaard > > * 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) >