This is an archive of the discontinued LLVM Phabricator instance.

[LLD][ELF] Revert r318924 Skip over empty sections when checking for contiguous relro
ClosedPublic

Authored by peter.smith on Dec 1 2017, 3:29 AM.

Details

Summary

PR35478 https://bugs.llvm.org/show_bug.cgi?id=35478 points out a flaw in the implementation of r318924 from D40364. The implementation depends on the Size field being set or the SyntheticSection::empty() being accurate. These functions are not reliable as some linker script commands that have yet to be processed may affect the results, causing some non-zero size sections to be reported as zero size.

I think the first step is to revert r318924 and come up with a better solution for the underlying problem rather than trying to layer more heuristics onto the zero sized output section.

Chances are I'll be out of office by the time anyone sees this so feel free to commit the revert if you agree with me.

Fixes PR35478

Current thoughts on the underlying problem:
Revisiting the motivation for adding the zero size check in the first place; it was to prevent 0 sized SyntheticSections that a user does not have full control over from needlessly breaking the PT_GNU_RELRO, rather than trying to accommodate arbitrarily complex linker scripts. Looking at the code, it looks like removeUnusedSyntheticSections() should remove zero sized synthetic sections. It does, but it doesn't set the Parent to nullptr, this has the side effect that Sec == InX::BssRelRo->getParent() will make the parent OutputSection of InX::BssRelRo RelRo even if there is no InX::BssRelRo.

I tried a quick experiment with setting the Parent to nullptr and this flushed out a few interesting test failures, it feels like playing Jenga with every change:

  • In the isRelroSection() we have to consider the case where there is no .plt and .plt.got but there is a ifunc plt with accompanying (ifunc .got or .plt.got)
  • The PPC64 has PltHeaderSize == 0. Unfortunately HeaderSize == 0 is used to choose between the ifunc plt or normal plt. We seem to get away with this at the moment, but tests start to fail when Parent is set to nullptr for the .got.plt.
  • The InX::BssRelRo and InX::Bss never get their sizes set and they are always removed by removeUnusedSyntheticSections(), their purpose seems to be as some kind of proxy for add .bss or .bss.relro InputSections into their parent OutputSections, they therefore don't behave like other SyntheticSections anyway.

My thinking is that some work is needed to make sure that the Sec == SyntheticSection->getParent() does a bit more checking before returning true, particularly for InX::BssRelRo as that has special behaviour. I'll hope to post something for review as soon as possible.

Diff Detail

Event Timeline

peter.smith created this revision.Dec 1 2017, 3:29 AM
jhenderson accepted this revision.Dec 1 2017, 3:59 AM

LGTM, at least from my point of view. I verified that with both this and D38361 all the tests pass.

This revision is now accepted and ready to land.Dec 1 2017, 3:59 AM

Thanks, if there are no objections from the US timezone, I'll commit on Monday.

rafael closed this revision.Dec 1 2017, 10:14 AM
ELF/Writer.cpp