This is an archive of the discontinued LLVM Phabricator instance.

ELF: Create .gnu.version and .gnu.version_r sections when linking against versioned DSOs.
ClosedPublic

Authored by pcc on Apr 24 2016, 12:56 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

pcc updated this revision to Diff 54794.Apr 24 2016, 12:56 AM
pcc retitled this revision from to ELF: Create .gnu.version and .gnu.version_r sections when linking against versioned DSOs..
pcc updated this object.
pcc added reviewers: rafael, ruiu, davide, grimar, emaste.
pcc added a subscriber: llvm-commits.
grimar edited edge metadata.Apr 25 2016, 2:26 AM

I am good familar with this feature, so have just few minor comments

ELF/InputFiles.cpp
452 ↗(On Diff #54794)

VerdefCount + 1

ELF/InputFiles.h
278 ↗(On Diff #54794)

Excessive empty line, no dot at the end of comment.

ELF/OutputSections.cpp
1508 ↗(On Diff #54794)

I would write:

if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(B))
  Out<ELFT>::VerNeed->addSymbol(SS);
pcc updated this revision to Diff 54868.Apr 25 2016, 9:29 AM
pcc edited edge metadata.
  • Remove function VersionTableSection<ELFT>::addSymbol
  • Fix comment
  • Re-order members
ELF/InputFiles.cpp
452 ↗(On Diff #54794)

The comment was incorrect, it should have read VerdefCount. Updated.

ELF/InputFiles.h
278 ↗(On Diff #54794)

I wanted to delimit these members from the ones used for --as-needed. But I can probably do that by moving them above the --as-needed members instead.

ELF/OutputSections.cpp
1508 ↗(On Diff #54794)

Yes. Also moved this code to the caller and removed this function.

pcc added a comment.Apr 25 2016, 9:44 AM

I discovered a bad interaction between this feature and --as-needed --gc-sections. Sometimes we will create verneed entries for shared symbols referred to by un-needed DSOs, which can cause the glibc dynamic loader to reject the executable. Before landing this, I would like to fix this problem by changing the dead section stripping code to also filter the shared symbols in the dynsym.

davide edited edge metadata.Apr 25 2016, 10:14 AM

This looks fine to me if others are happy, and I agree the bad interaction should be fixed before this one lands.

ruiu added inline comments.Apr 25 2016, 11:10 AM
ELF/InputFiles.h
243 ↗(On Diff #54868)

It's maybe because I'm not familiar enough with ELF, but I'd use uint16_t instead of ELF "Half" type as I don't memorize the ELF integral types. (It is always 16 bit right?)

251–253 ↗(On Diff #54868)

A versioned symbol is identified only by its filename (soname) and version string, so I think it is better to add the version string field to this class, instead of adding raw VerdefSec and VerdefSec fields. It is I think easier to understand.

282 ↗(On Diff #54868)

Why don't you use DenseMap?

pcc updated this revision to Diff 54886.Apr 25 2016, 12:36 PM
pcc marked an inline comment as done.
pcc edited edge metadata.
  • Don't use Elf_Half
pcc added a comment.Apr 25 2016, 12:37 PM

D19490 fixes the issue I mentioned.

ELF/InputFiles.h
251–253 ↗(On Diff #54868)

A DSO may contain multiple version definitions, so we can't just store a single version string here. The version of each symbol is stored in a field of type const Elf_Verdef * that I added to SharedSymbol.

282 ↗(On Diff #54868)

I need to be able to enumerate the values in this map deterministically. See comment at OutputSections.cpp:1559.

ruiu added inline comments.Apr 25 2016, 12:40 PM
ELF/Symbols.h
350–356 ↗(On Diff #54886)

Ah, sorry, I intended to add comment here. Instead of adding uncooked Verdef, why don't you add the version string here?

ruiu edited edge metadata.Apr 25 2016, 1:07 PM

I'd like to rephrase that to say what I was thinking when I added this comment. So, if my understanding is correct, then users of a DSO don't need to understand the version hierarchy of the DSO. Each version is identified by version string, and that is a opaque token to the user. Therefore, SharedFile doesn't have to have any information as to versioned symbols. As long as each symbol has a version string, we can construct .gnu.version_r.

pcc added inline comments.Apr 25 2016, 1:16 PM
ELF/Symbols.h
350–356 ↗(On Diff #54886)

Two mostly minor reasons.

  1. We need to store an ELF hash in Elf_Vernaux (see OutputSections.cpp:1564). While we could compute it ourselves, there's no need to do that if we can use the hash from the input.
  1. It allows us to use a pointer as our map key in Verdefs rather than a string.
pcc added a comment.Apr 25 2016, 1:30 PM

Therefore, SharedFile doesn't have to have any information as to versioned symbols. As long as each symbol has a version string, we can construct .gnu.version_r.

Right. The fields I added to SharedFile store temporary data that I use (1) to retain information from parseSoName that I need in parseRest, and (2) to construct .gnu.version_r in the writer.

ruiu added inline comments.Apr 25 2016, 4:22 PM
ELF/InputFiles.cpp
438 ↗(On Diff #54886)

Does this hide this->Verdefs?

440 ↗(On Diff #54886)

Can you make this new code a new function that returns a std::vector<const Elf_Verdef *>?

458 ↗(On Diff #54886)

unsigned char -> uint8_t

ELF/OutputSections.cpp
1500 ↗(On Diff #54886)

Please add a link to https://www.akkadia.org/drepper/symbol-versioning. I'd probably write a brief description of the .gnu.version* section formats.

1517 ↗(On Diff #54886)

We should set 0, no?

1528 ↗(On Diff #54886)

Add a comment saying that this is for a non-versioned symbol and 1 is default value for that.

1549 ↗(On Diff #54886)

OK, so this loop basically copies .GNU.version_d sections from source DSOs. I'd appreciate if you write that in comment.

pcc updated this revision to Diff 54963.Apr 25 2016, 7:32 PM
pcc marked 5 inline comments as done.
pcc edited edge metadata.
  • Move verdef parser
  • Rename field
  • Add comments
ELF/InputFiles.cpp
438 ↗(On Diff #54886)

It does. I've renamed the field to VerdefMap.

ELF/OutputSections.cpp
1517 ↗(On Diff #54886)

I think it should be set to 1 because 0 is reserved for local symbols.

pcc added a comment.Apr 27 2016, 12:44 PM

Ping. This should be unblocked now.

ruiu accepted this revision.Apr 27 2016, 1:10 PM
ruiu edited edge metadata.

LGTM

This revision is now accepted and ready to land.Apr 27 2016, 1:10 PM
This revision was automatically updated to reflect the committed changes.