[ELF] Support custom sections between DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END

We currently hard code RELRO sections. When a custom section is between
DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END, we may report a spurious
`error: section: ... is not contiguous with other relro sections`. GNU ld
makes such sections RELRO.

glibc recently switched to default --with-default-link=no. This configuration
places `__libc_atexit` and others between DATA_SEGMENT_ALIGN and
DATA_SEGMENT_RELRO_END. This patch allows such a ld.bfd --verbose
linker script to be fed into lld.

Reviewed By: peter.smith

Differential Revision: https://reviews.llvm.org/D124656
This commit is contained in:
Fangrui Song
2022-05-04 01:10:45 -07:00
parent 37a1473524
commit 5a44980f0a
4 changed files with 39 additions and 7 deletions

View File

@@ -135,6 +135,9 @@ private:
// True if a script being read is in the --sysroot directory.
bool isUnderSysroot = false;
bool seenDataAlign = false;
bool seenRelroEnd = false;
// A set to detect an INCLUDE() cycle.
StringSet<> seen;
};
@@ -583,6 +586,14 @@ void ScriptParser::readSections() {
else
v.push_back(readOutputSectionDescription(tok));
}
// If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
// the relro fields should be cleared.
if (!seenRelroEnd)
for (SectionCommand *cmd : v)
if (auto *osd = dyn_cast<OutputDesc>(cmd))
osd->osec.relro = false;
script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
v.end());
@@ -887,6 +898,8 @@ OutputDesc *ScriptParser::readOverlaySectionDescription() {
OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation());
OutputSection *osec = &cmd->osec;
// Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
osec->relro = seenDataAlign && !seenRelroEnd;
size_t symbolsReferenced = script->referencedSymbols.size();
@@ -1358,6 +1371,7 @@ Expr ScriptParser::readPrimary() {
expect(",");
readExpr();
expect(")");
seenDataAlign = true;
return [=] {
return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue()));
};
@@ -1377,6 +1391,7 @@ Expr ScriptParser::readPrimary() {
expect(",");
readExpr();
expect(")");
seenRelroEnd = true;
Expr e = getPageSize();
return [=] { return alignTo(script->getDot(), e().getValue()); };
}