This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Assign sh_link field of SHT_GNU_versym section to DynSymTab section index
ClosedPublic

Authored by grimar on Jun 3 2016, 4:28 AM.

Details

Summary

.gnu.version should have sh_link field initialized with index of DynSymTab section.

GNU documentation looks misses that, but Sun docs mention it, according to
https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-54676/index.html
versym sh_link is indeed supposed to point to the .dynsym section.

Binutils readelf tool also relies on that:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=binutils/readelf.c;h=b6454d353279dc57745cd5a2d68b5f3f69f8e17c;hb=5522f910cb539905d6adfdceab208ddfa5e84557#l9988

Both gold/bfd do the same + after this patch I am able to see this section in readelf output, was unable before in my case.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 59528.Jun 3 2016, 4:28 AM
grimar retitled this revision from to [ELF] - Assign sh_link field of SHT_GNU_versym section to DynSymTab section index.
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: grimar, llvm-commits.
emaste accepted this revision.Jun 3 2016, 8:09 AM
emaste added a reviewer: emaste.
emaste added a subscriber: emaste.

I did not find anywhere in documentation that sh_link of this one should be set to something, but readelf using it:

ELF Tool Chain readelf collects the version strings from the verdef and verneed sections, without using the versym section sh_link. I think the GNU readelf source you linked to is actually a bug.

That said, from https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-54676/index.html versym sh_link is indeed supposed to point to the .dynsym section:

The number of elements of the array must equal the number of symbol table entries that are contained in the associated symbol table. This number is determined by the section's sh_link value.

I think it would be valid to have another string section (say, .verstr) and have the verdef/verneed sections reference it in sh_link. In that case versym sh_link still needs to be the dynsym section.

This revision is now accepted and ready to land.Jun 3 2016, 8:09 AM
rafael accepted this revision.Jun 3 2016, 10:50 AM
rafael edited edge metadata.

LGTM

ruiu accepted this revision.Jun 3 2016, 11:06 AM
ruiu edited edge metadata.

LGTM with a nit.

ELF/OutputSections.cpp
1421 ↗(On Diff #59528)

Please add a comment saying that setting sh_link is not required by any spec but we do since readelf assumes it.

ruiu added a comment.Jun 3 2016, 11:07 AM

"readelf as of June 2016" (so that we can remove this code in, say, 2026.)

emaste added inline comments.Jun 3 2016, 11:11 AM
ELF/OutputSections.cpp
1421 ↗(On Diff #59528)

It is actually required (in the link I posted above). I just think it's also a bug in readelf.

versym sh_link has to point to .dynsym per above, while I believe verdef and verneed do not have to (but in practice always do), while readelf relies on all three pointing to .dynsym.

The link I pasted is for the sun doc not a GNU one, but I believe much/all of the detail is the same. The section header types SHT_SUNW_version and SHT_GNU_version have the same value.

ruiu added a comment.Jun 3 2016, 11:57 AM

Ah, OK, then this should be fine. Thanks!

grimar added inline comments.Jun 3 2016, 2:25 PM
ELF/OutputSections.cpp
1421 ↗(On Diff #59528)

I think verdef and verneed should point to DynStrTab in sh_link field, when
versym points to DynSymTab. At least that how that stuff works in binutils now I believe.

emaste added a comment.Jun 3 2016, 2:39 PM

I think verdef and verneed should point to DynStrTab in sh_link field, when
versym points to DynSymTab. At least that how that stuff works in binutils now I believe.

Sorry for the confusion, you are correct. I dropped one level of indirection.

I believe these are true:

  • versym must point to dynsym (as fixed by this change)
  • dynsym must point to dynstr (already a given)
  • typically verdef, versym and dynsym all point to dynstr
  • no spec requires verdef and versym to point to dynstr
  • GNU readelf will not work correctly if verdef or versym do not point to dynstr because it accesses the string table for version strings via versym->sh_info->sh_info not verdef->sh_info and verneed->sh_info (the presumed bug)
grimar updated this object.Jun 6 2016, 1:10 AM
grimar edited edge metadata.
This revision was automatically updated to reflect the committed changes.