[ELF] Don't use multiple inheritance for OutputSection. NFC
Add an OutputDesc class inheriting from SectionCommand. An OutputDesc wraps an OutputSection. This change allows InputSection::getParent to be inlined. Differential Revision: https://reviews.llvm.org/D120650
This commit is contained in:
parent
8321579b28
commit
6c814931bc
|
@ -2690,8 +2690,8 @@ void LinkerDriver::link(opt::InputArgList &args) {
|
||||||
// point onwards InputSectionDescription::sections should be used instead of
|
// point onwards InputSectionDescription::sections should be used instead of
|
||||||
// sectionBases.
|
// sectionBases.
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
sec->finalizeInputSections();
|
osd->osec.finalizeInputSections();
|
||||||
llvm::erase_if(inputSections, [](InputSectionBase *s) {
|
llvm::erase_if(inputSections, [](InputSectionBase *s) {
|
||||||
return isa<MergeInputSection>(s);
|
return isa<MergeInputSection>(s);
|
||||||
});
|
});
|
||||||
|
|
|
@ -568,8 +568,8 @@ template <class ELFT> void ICF<ELFT>::run() {
|
||||||
// InputSectionDescription::sections is populated by processSectionCommands().
|
// InputSectionDescription::sections is populated by processSectionCommands().
|
||||||
// ICF may fold some input sections assigned to output sections. Remove them.
|
// ICF may fold some input sections assigned to output sections. Remove them.
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
for (SectionCommand *subCmd : sec->commands)
|
for (SectionCommand *subCmd : osd->osec.commands)
|
||||||
if (auto *isd = dyn_cast<InputSectionDescription>(subCmd))
|
if (auto *isd = dyn_cast<InputSectionDescription>(subCmd))
|
||||||
llvm::erase_if(isd->sections,
|
llvm::erase_if(isd->sections,
|
||||||
[](InputSection *isec) { return !isec->isLive(); });
|
[](InputSection *isec) { return !isec->isLive(); });
|
||||||
|
|
|
@ -130,26 +130,26 @@ uint64_t ExprValue::getSectionOffset() const {
|
||||||
return getValue() - getSecAddr();
|
return getValue() - getSecAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection *LinkerScript::createOutputSection(StringRef name,
|
OutputDesc *LinkerScript::createOutputSection(StringRef name,
|
||||||
StringRef location) {
|
StringRef location) {
|
||||||
OutputSection *&secRef = nameToOutputSection[CachedHashStringRef(name)];
|
OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
|
||||||
OutputSection *sec;
|
OutputDesc *sec;
|
||||||
if (secRef && secRef->location.empty()) {
|
if (secRef && secRef->osec.location.empty()) {
|
||||||
// There was a forward reference.
|
// There was a forward reference.
|
||||||
sec = secRef;
|
sec = secRef;
|
||||||
} else {
|
} else {
|
||||||
sec = make<OutputSection>(name, SHT_PROGBITS, 0);
|
sec = make<OutputDesc>(name, SHT_PROGBITS, 0);
|
||||||
if (!secRef)
|
if (!secRef)
|
||||||
secRef = sec;
|
secRef = sec;
|
||||||
}
|
}
|
||||||
sec->location = std::string(location);
|
sec->osec.location = std::string(location);
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) {
|
OutputDesc *LinkerScript::getOrCreateOutputSection(StringRef name) {
|
||||||
OutputSection *&cmdRef = nameToOutputSection[CachedHashStringRef(name)];
|
OutputDesc *&cmdRef = nameToOutputSection[CachedHashStringRef(name)];
|
||||||
if (!cmdRef)
|
if (!cmdRef)
|
||||||
cmdRef = make<OutputSection>(name, SHT_PROGBITS, 0);
|
cmdRef = make<OutputDesc>(name, SHT_PROGBITS, 0);
|
||||||
return cmdRef;
|
return cmdRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ getSymbolAssignmentValues(ArrayRef<SectionCommand *> sectionCommands) {
|
||||||
assign->sym->value));
|
assign->sym->value));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
|
for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
|
||||||
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
|
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
|
||||||
if (assign->sym)
|
if (assign->sym)
|
||||||
ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
|
ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
|
||||||
|
@ -305,25 +305,25 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
|
||||||
// Process INSERT [AFTER|BEFORE] commands. For each command, we move the
|
// Process INSERT [AFTER|BEFORE] commands. For each command, we move the
|
||||||
// specified output section to the designated place.
|
// specified output section to the designated place.
|
||||||
void LinkerScript::processInsertCommands() {
|
void LinkerScript::processInsertCommands() {
|
||||||
SmallVector<OutputSection *, 0> moves;
|
SmallVector<OutputDesc *, 0> moves;
|
||||||
for (const InsertCommand &cmd : insertCommands) {
|
for (const InsertCommand &cmd : insertCommands) {
|
||||||
for (StringRef name : cmd.names) {
|
for (StringRef name : cmd.names) {
|
||||||
// If base is empty, it may have been discarded by
|
// If base is empty, it may have been discarded by
|
||||||
// adjustOutputSections(). We do not handle such output sections.
|
// adjustOutputSections(). We do not handle such output sections.
|
||||||
auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) {
|
auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) {
|
||||||
return isa<OutputSection>(subCmd) &&
|
return isa<OutputDesc>(subCmd) &&
|
||||||
cast<OutputSection>(subCmd)->name == name;
|
cast<OutputDesc>(subCmd)->osec.name == name;
|
||||||
});
|
});
|
||||||
if (from == sectionCommands.end())
|
if (from == sectionCommands.end())
|
||||||
continue;
|
continue;
|
||||||
moves.push_back(cast<OutputSection>(*from));
|
moves.push_back(cast<OutputDesc>(*from));
|
||||||
sectionCommands.erase(from);
|
sectionCommands.erase(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto insertPos =
|
auto insertPos =
|
||||||
llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) {
|
llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) {
|
||||||
auto *to = dyn_cast<OutputSection>(subCmd);
|
auto *to = dyn_cast<OutputDesc>(subCmd);
|
||||||
return to != nullptr && to->name == cmd.where;
|
return to != nullptr && to->osec.name == cmd.where;
|
||||||
});
|
});
|
||||||
if (insertPos == sectionCommands.end()) {
|
if (insertPos == sectionCommands.end()) {
|
||||||
error("unable to insert " + cmd.names[0] +
|
error("unable to insert " + cmd.names[0] +
|
||||||
|
@ -352,10 +352,10 @@ void LinkerScript::declareSymbols() {
|
||||||
// we can't say for sure if it is going to be included or not.
|
// we can't say for sure if it is going to be included or not.
|
||||||
// Skip such sections for now. Improve the checks if we ever
|
// Skip such sections for now. Improve the checks if we ever
|
||||||
// need symbols from that sections to be declared early.
|
// need symbols from that sections to be declared early.
|
||||||
auto *sec = cast<OutputSection>(cmd);
|
const OutputSection &sec = cast<OutputDesc>(cmd)->osec;
|
||||||
if (sec->constraint != ConstraintKind::NoConstraint)
|
if (sec.constraint != ConstraintKind::NoConstraint)
|
||||||
continue;
|
continue;
|
||||||
for (SectionCommand *cmd : sec->commands)
|
for (SectionCommand *cmd : sec.commands)
|
||||||
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
|
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
|
||||||
declareSymbol(assign);
|
declareSymbol(assign);
|
||||||
}
|
}
|
||||||
|
@ -645,18 +645,20 @@ void LinkerScript::processSectionCommands() {
|
||||||
|
|
||||||
// Process OVERWRITE_SECTIONS first so that it can overwrite the main script
|
// Process OVERWRITE_SECTIONS first so that it can overwrite the main script
|
||||||
// or orphans.
|
// or orphans.
|
||||||
DenseMap<CachedHashStringRef, OutputSection *> map;
|
DenseMap<CachedHashStringRef, OutputDesc *> map;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (OutputSection *osec : overwriteSections)
|
for (OutputDesc *osd : overwriteSections) {
|
||||||
|
OutputSection *osec = &osd->osec;
|
||||||
if (process(osec) &&
|
if (process(osec) &&
|
||||||
!map.try_emplace(CachedHashStringRef(osec->name), osec).second)
|
!map.try_emplace(CachedHashStringRef(osec->name), osd).second)
|
||||||
warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name);
|
warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name);
|
||||||
|
}
|
||||||
for (SectionCommand *&base : sectionCommands)
|
for (SectionCommand *&base : sectionCommands)
|
||||||
if (auto *osec = dyn_cast<OutputSection>(base)) {
|
if (auto *osd = dyn_cast<OutputDesc>(base)) {
|
||||||
if (OutputSection *overwrite =
|
OutputSection *osec = &osd->osec;
|
||||||
map.lookup(CachedHashStringRef(osec->name))) {
|
if (OutputDesc *overwrite = map.lookup(CachedHashStringRef(osec->name))) {
|
||||||
log(overwrite->location + " overwrites " + osec->name);
|
log(overwrite->osec.location + " overwrites " + osec->name);
|
||||||
overwrite->sectionIndex = i++;
|
overwrite->osec.sectionIndex = i++;
|
||||||
base = overwrite;
|
base = overwrite;
|
||||||
} else if (process(osec)) {
|
} else if (process(osec)) {
|
||||||
osec->sectionIndex = i++;
|
osec->sectionIndex = i++;
|
||||||
|
@ -666,9 +668,9 @@ void LinkerScript::processSectionCommands() {
|
||||||
// If an OVERWRITE_SECTIONS specified output section is not in
|
// If an OVERWRITE_SECTIONS specified output section is not in
|
||||||
// sectionCommands, append it to the end. The section will be inserted by
|
// sectionCommands, append it to the end. The section will be inserted by
|
||||||
// orphan placement.
|
// orphan placement.
|
||||||
for (OutputSection *osec : overwriteSections)
|
for (OutputDesc *osd : overwriteSections)
|
||||||
if (osec->partition == 1 && osec->sectionIndex == UINT32_MAX)
|
if (osd->osec.partition == 1 && osd->osec.sectionIndex == UINT32_MAX)
|
||||||
sectionCommands.push_back(osec);
|
sectionCommands.push_back(osd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerScript::processSymbolAssignments() {
|
void LinkerScript::processSymbolAssignments() {
|
||||||
|
@ -690,7 +692,7 @@ void LinkerScript::processSymbolAssignments() {
|
||||||
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
|
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
|
||||||
addSymbol(assign);
|
addSymbol(assign);
|
||||||
else
|
else
|
||||||
for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
|
for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
|
||||||
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
|
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
|
||||||
addSymbol(assign);
|
addSymbol(assign);
|
||||||
}
|
}
|
||||||
|
@ -701,22 +703,20 @@ void LinkerScript::processSymbolAssignments() {
|
||||||
static OutputSection *findByName(ArrayRef<SectionCommand *> vec,
|
static OutputSection *findByName(ArrayRef<SectionCommand *> vec,
|
||||||
StringRef name) {
|
StringRef name) {
|
||||||
for (SectionCommand *cmd : vec)
|
for (SectionCommand *cmd : vec)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
if (sec->name == name)
|
if (osd->osec.name == name)
|
||||||
return sec;
|
return &osd->osec;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static OutputSection *createSection(InputSectionBase *isec,
|
static OutputDesc *createSection(InputSectionBase *isec, StringRef outsecName) {
|
||||||
StringRef outsecName) {
|
OutputDesc *osd = script->createOutputSection(outsecName, "<internal>");
|
||||||
OutputSection *sec = script->createOutputSection(outsecName, "<internal>");
|
osd->osec.recordSection(isec);
|
||||||
sec->recordSection(isec);
|
return osd;
|
||||||
return sec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static OutputSection *
|
static OutputDesc *addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
|
||||||
addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
|
InputSectionBase *isec, StringRef outsecName) {
|
||||||
InputSectionBase *isec, StringRef outsecName) {
|
|
||||||
// Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
|
// Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
|
||||||
// option is given. A section with SHT_GROUP defines a "section group", and
|
// option is given. A section with SHT_GROUP defines a "section group", and
|
||||||
// its members have SHF_GROUP attribute. Usually these flags have already been
|
// its members have SHF_GROUP attribute. Usually these flags have already been
|
||||||
|
@ -743,8 +743,9 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->relocationSection = createSection(isec, outsecName);
|
OutputDesc *osd = createSection(isec, outsecName);
|
||||||
return out->relocationSection;
|
out->relocationSection = &osd->osec;
|
||||||
|
return osd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ELF spec just says
|
// The ELF spec just says
|
||||||
|
@ -813,15 +814,15 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection *sec = createSection(isec, outsecName);
|
OutputDesc *osd = createSection(isec, outsecName);
|
||||||
v.push_back(sec);
|
v.push_back(&osd->osec);
|
||||||
return sec;
|
return osd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sections that didn't match any sections command.
|
// Add sections that didn't match any sections command.
|
||||||
void LinkerScript::addOrphanSections() {
|
void LinkerScript::addOrphanSections() {
|
||||||
StringMap<TinyPtrVector<OutputSection *>> map;
|
StringMap<TinyPtrVector<OutputSection *>> map;
|
||||||
SmallVector<OutputSection *, 0> v;
|
SmallVector<OutputDesc *, 0> v;
|
||||||
|
|
||||||
auto add = [&](InputSectionBase *s) {
|
auto add = [&](InputSectionBase *s) {
|
||||||
if (s->isLive() && !s->parent) {
|
if (s->isLive() && !s->parent) {
|
||||||
|
@ -833,8 +834,8 @@ void LinkerScript::addOrphanSections() {
|
||||||
} else if (OutputSection *sec = findByName(sectionCommands, name)) {
|
} else if (OutputSection *sec = findByName(sectionCommands, name)) {
|
||||||
sec->recordSection(s);
|
sec->recordSection(s);
|
||||||
} else {
|
} else {
|
||||||
if (OutputSection *os = addInputSec(map, s, name))
|
if (OutputDesc *osd = addInputSec(map, s, name))
|
||||||
v.push_back(os);
|
v.push_back(osd);
|
||||||
assert(isa<MergeInputSection>(s) ||
|
assert(isa<MergeInputSection>(s) ||
|
||||||
s->getOutputSection()->sectionIndex == UINT32_MAX);
|
s->getOutputSection()->sectionIndex == UINT32_MAX);
|
||||||
}
|
}
|
||||||
|
@ -1138,9 +1139,9 @@ void LinkerScript::adjustOutputSections() {
|
||||||
|
|
||||||
SmallVector<StringRef, 0> defPhdrs;
|
SmallVector<StringRef, 0> defPhdrs;
|
||||||
for (SectionCommand *&cmd : sectionCommands) {
|
for (SectionCommand *&cmd : sectionCommands) {
|
||||||
auto *sec = dyn_cast<OutputSection>(cmd);
|
if (!isa<OutputDesc>(cmd))
|
||||||
if (!sec)
|
|
||||||
continue;
|
continue;
|
||||||
|
auto *sec = &cast<OutputDesc>(cmd)->osec;
|
||||||
|
|
||||||
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
|
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
|
||||||
if (sec->alignExpr)
|
if (sec->alignExpr)
|
||||||
|
@ -1192,7 +1193,8 @@ void LinkerScript::adjustSectionsAfterSorting() {
|
||||||
// Try and find an appropriate memory region to assign offsets in.
|
// Try and find an appropriate memory region to assign offsets in.
|
||||||
MemoryRegion *hint = nullptr;
|
MemoryRegion *hint = nullptr;
|
||||||
for (SectionCommand *cmd : sectionCommands) {
|
for (SectionCommand *cmd : sectionCommands) {
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd)) {
|
if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
|
||||||
|
OutputSection *sec = &osd->osec;
|
||||||
if (!sec->lmaRegionName.empty()) {
|
if (!sec->lmaRegionName.empty()) {
|
||||||
if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
|
if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
|
||||||
sec->lmaRegion = m;
|
sec->lmaRegion = m;
|
||||||
|
@ -1219,8 +1221,8 @@ void LinkerScript::adjustSectionsAfterSorting() {
|
||||||
// Walk the commands and propagate the program headers to commands that don't
|
// Walk the commands and propagate the program headers to commands that don't
|
||||||
// explicitly specify them.
|
// explicitly specify them.
|
||||||
for (SectionCommand *cmd : sectionCommands)
|
for (SectionCommand *cmd : sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
maybePropagatePhdrs(*sec, defPhdrs);
|
maybePropagatePhdrs(osd->osec, defPhdrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
|
static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
|
||||||
|
@ -1315,7 +1317,7 @@ const Defined *LinkerScript::assignAddresses() {
|
||||||
assign->size = dot - assign->addr;
|
assign->size = dot - assign->addr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assignOffsets(cast<OutputSection>(cmd));
|
assignOffsets(&cast<OutputDesc>(cmd)->osec);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = nullptr;
|
ctx = nullptr;
|
||||||
|
|
|
@ -32,6 +32,7 @@ class InputSectionBase;
|
||||||
class OutputSection;
|
class OutputSection;
|
||||||
class SectionBase;
|
class SectionBase;
|
||||||
class ThunkSection;
|
class ThunkSection;
|
||||||
|
struct OutputDesc;
|
||||||
|
|
||||||
// This represents an r-value in the linker script.
|
// This represents an r-value in the linker script.
|
||||||
struct ExprValue {
|
struct ExprValue {
|
||||||
|
@ -267,8 +268,7 @@ class LinkerScript final {
|
||||||
uint64_t tbssAddr = 0;
|
uint64_t tbssAddr = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm::DenseMap<llvm::CachedHashStringRef, OutputSection *>
|
llvm::DenseMap<llvm::CachedHashStringRef, OutputDesc *> nameToOutputSection;
|
||||||
nameToOutputSection;
|
|
||||||
|
|
||||||
void addSymbol(SymbolAssignment *cmd);
|
void addSymbol(SymbolAssignment *cmd);
|
||||||
void assignSymbol(SymbolAssignment *cmd, bool inSec);
|
void assignSymbol(SymbolAssignment *cmd, bool inSec);
|
||||||
|
@ -304,8 +304,8 @@ class LinkerScript final {
|
||||||
uint64_t dot;
|
uint64_t dot;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OutputSection *createOutputSection(StringRef name, StringRef location);
|
OutputDesc *createOutputSection(StringRef name, StringRef location);
|
||||||
OutputSection *getOrCreateOutputSection(StringRef name);
|
OutputDesc *getOrCreateOutputSection(StringRef name);
|
||||||
|
|
||||||
bool hasPhdrsCommands() { return !phdrsCommands.empty(); }
|
bool hasPhdrsCommands() { return !phdrsCommands.empty(); }
|
||||||
uint64_t getDot() { return dot; }
|
uint64_t getDot() { return dot; }
|
||||||
|
@ -357,7 +357,7 @@ public:
|
||||||
SmallVector<InsertCommand, 0> insertCommands;
|
SmallVector<InsertCommand, 0> insertCommands;
|
||||||
|
|
||||||
// OutputSections specified by OVERWRITE_SECTIONS.
|
// OutputSections specified by OVERWRITE_SECTIONS.
|
||||||
SmallVector<OutputSection *, 0> overwriteSections;
|
SmallVector<OutputDesc *, 0> overwriteSections;
|
||||||
|
|
||||||
// Sections that will be warned/errored by --orphan-handling.
|
// Sections that will be warned/errored by --orphan-handling.
|
||||||
SmallVector<const InputSectionBase *, 0> orphanSections;
|
SmallVector<const InputSectionBase *, 0> orphanSections;
|
||||||
|
|
|
@ -168,7 +168,7 @@ static void writeMapFile(raw_fd_ostream &os) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
osec = cast<OutputSection>(cmd);
|
osec = &cast<OutputDesc>(cmd)->osec;
|
||||||
writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
|
writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
|
||||||
os << osec->name << '\n';
|
os << osec->name << '\n';
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,7 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
|
OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
|
||||||
: SectionCommand(OutputSectionKind),
|
: SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
|
||||||
SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
|
|
||||||
/*Info*/ 0, /*Link*/ 0) {}
|
/*Info*/ 0, /*Link*/ 0) {}
|
||||||
|
|
||||||
// We allow sections of types listed below to merged into a
|
// We allow sections of types listed below to merged into a
|
||||||
|
@ -251,10 +250,6 @@ uint64_t elf::getHeaderSize() {
|
||||||
return Out::elfHeader->size + Out::programHeaders->size;
|
return Out::elfHeader->size + Out::programHeaders->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputSection::classof(const SectionCommand *c) {
|
|
||||||
return c->kind == OutputSectionKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
|
void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
|
||||||
assert(isLive());
|
assert(isLive());
|
||||||
for (SectionCommand *b : commands)
|
for (SectionCommand *b : commands)
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct CompressedData {
|
||||||
// It is composed of multiple InputSections.
|
// It is composed of multiple InputSections.
|
||||||
// The writer creates multiple OutputSections and assign them unique,
|
// The writer creates multiple OutputSections and assign them unique,
|
||||||
// non-overlapping file offsets and VAs.
|
// non-overlapping file offsets and VAs.
|
||||||
class OutputSection final : public SectionCommand, public SectionBase {
|
class OutputSection final : public SectionBase {
|
||||||
public:
|
public:
|
||||||
OutputSection(StringRef name, uint32_t type, uint64_t flags);
|
OutputSection(StringRef name, uint32_t type, uint64_t flags);
|
||||||
|
|
||||||
|
@ -39,8 +39,6 @@ public:
|
||||||
return s->kind() == SectionBase::Output;
|
return s->kind() == SectionBase::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const SectionCommand *c);
|
|
||||||
|
|
||||||
uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
|
uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
|
||||||
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
|
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
|
||||||
|
|
||||||
|
@ -119,6 +117,16 @@ private:
|
||||||
std::array<uint8_t, 4> getFiller();
|
std::array<uint8_t, 4> getFiller();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OutputDesc final : SectionCommand {
|
||||||
|
OutputSection osec;
|
||||||
|
OutputDesc(StringRef name, uint32_t type, uint64_t flags)
|
||||||
|
: SectionCommand(OutputSectionKind), osec(name, type, flags) {}
|
||||||
|
|
||||||
|
static bool classof(const SectionCommand *c) {
|
||||||
|
return c->kind == OutputSectionKind;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
int getPriority(StringRef s);
|
int getPriority(StringRef s);
|
||||||
|
|
||||||
InputSection *getFirstInputSection(const OutputSection *os);
|
InputSection *getFirstInputSection(const OutputSection *os);
|
||||||
|
|
|
@ -91,8 +91,8 @@ private:
|
||||||
std::array<uint8_t, 4> readFill();
|
std::array<uint8_t, 4> readFill();
|
||||||
bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
|
bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
|
||||||
void readSectionAddressType(OutputSection *cmd);
|
void readSectionAddressType(OutputSection *cmd);
|
||||||
OutputSection *readOverlaySectionDescription();
|
OutputDesc *readOverlaySectionDescription();
|
||||||
OutputSection *readOutputSectionDescription(StringRef outSec);
|
OutputDesc *readOutputSectionDescription(StringRef outSec);
|
||||||
SmallVector<SectionCommand *, 0> readOverlay();
|
SmallVector<SectionCommand *, 0> readOverlay();
|
||||||
SmallVector<StringRef, 0> readOutputSectionPhdrs();
|
SmallVector<StringRef, 0> readOutputSectionPhdrs();
|
||||||
std::pair<uint64_t, uint64_t> readInputSectionFlags();
|
std::pair<uint64_t, uint64_t> readInputSectionFlags();
|
||||||
|
@ -534,14 +534,14 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
|
||||||
while (!errorCount() && !consume("}")) {
|
while (!errorCount() && !consume("}")) {
|
||||||
// VA is the same for all sections. The LMAs are consecutive in memory
|
// VA is the same for all sections. The LMAs are consecutive in memory
|
||||||
// starting from the base load address specified.
|
// starting from the base load address specified.
|
||||||
OutputSection *os = readOverlaySectionDescription();
|
OutputDesc *osd = readOverlaySectionDescription();
|
||||||
os->addrExpr = addrExpr;
|
osd->osec.addrExpr = addrExpr;
|
||||||
if (prev)
|
if (prev)
|
||||||
os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
|
osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
|
||||||
else
|
else
|
||||||
os->lmaExpr = lmaExpr;
|
osd->osec.lmaExpr = lmaExpr;
|
||||||
v.push_back(os);
|
v.push_back(osd);
|
||||||
prev = os;
|
prev = &osd->osec;
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to the specification, at the end of the overlay, the location
|
// According to the specification, at the end of the overlay, the location
|
||||||
|
@ -551,7 +551,7 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
|
||||||
Expr moveDot = [=] {
|
Expr moveDot = [=] {
|
||||||
uint64_t max = 0;
|
uint64_t max = 0;
|
||||||
for (SectionCommand *cmd : v)
|
for (SectionCommand *cmd : v)
|
||||||
max = std::max(max, cast<OutputSection>(cmd)->size);
|
max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
|
||||||
return addrExpr().getValue() + max;
|
return addrExpr().getValue() + max;
|
||||||
};
|
};
|
||||||
v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
|
v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
|
||||||
|
@ -599,8 +599,8 @@ void ScriptParser::readSections() {
|
||||||
StringRef where = next();
|
StringRef where = next();
|
||||||
SmallVector<StringRef, 0> names;
|
SmallVector<StringRef, 0> names;
|
||||||
for (SectionCommand *cmd : v)
|
for (SectionCommand *cmd : v)
|
||||||
if (auto *os = dyn_cast<OutputSection>(cmd))
|
if (auto *os = dyn_cast<OutputDesc>(cmd))
|
||||||
names.push_back(os->name);
|
names.push_back(os->osec.name);
|
||||||
if (!names.empty())
|
if (!names.empty())
|
||||||
script->insertCommands.push_back({std::move(names), isAfter, where});
|
script->insertCommands.push_back({std::move(names), isAfter, where});
|
||||||
}
|
}
|
||||||
|
@ -869,45 +869,44 @@ static Expr checkAlignment(Expr e, std::string &loc) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection *ScriptParser::readOverlaySectionDescription() {
|
OutputDesc *ScriptParser::readOverlaySectionDescription() {
|
||||||
OutputSection *cmd =
|
OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
|
||||||
script->createOutputSection(next(), getCurrentLocation());
|
osd->osec.inOverlay = true;
|
||||||
cmd->inOverlay = true;
|
|
||||||
expect("{");
|
expect("{");
|
||||||
while (!errorCount() && !consume("}")) {
|
while (!errorCount() && !consume("}")) {
|
||||||
uint64_t withFlags = 0;
|
uint64_t withFlags = 0;
|
||||||
uint64_t withoutFlags = 0;
|
uint64_t withoutFlags = 0;
|
||||||
if (consume("INPUT_SECTION_FLAGS"))
|
if (consume("INPUT_SECTION_FLAGS"))
|
||||||
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
|
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
|
||||||
cmd->commands.push_back(
|
osd->osec.commands.push_back(
|
||||||
readInputSectionRules(next(), withFlags, withoutFlags));
|
readInputSectionRules(next(), withFlags, withoutFlags));
|
||||||
}
|
}
|
||||||
return cmd;
|
return osd;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||||
OutputSection *cmd =
|
OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation());
|
||||||
script->createOutputSection(outSec, getCurrentLocation());
|
OutputSection *osec = &cmd->osec;
|
||||||
|
|
||||||
size_t symbolsReferenced = script->referencedSymbols.size();
|
size_t symbolsReferenced = script->referencedSymbols.size();
|
||||||
|
|
||||||
if (peek() != ":")
|
if (peek() != ":")
|
||||||
readSectionAddressType(cmd);
|
readSectionAddressType(osec);
|
||||||
expect(":");
|
expect(":");
|
||||||
|
|
||||||
std::string location = getCurrentLocation();
|
std::string location = getCurrentLocation();
|
||||||
if (consume("AT"))
|
if (consume("AT"))
|
||||||
cmd->lmaExpr = readParenExpr();
|
osec->lmaExpr = readParenExpr();
|
||||||
if (consume("ALIGN"))
|
if (consume("ALIGN"))
|
||||||
cmd->alignExpr = checkAlignment(readParenExpr(), location);
|
osec->alignExpr = checkAlignment(readParenExpr(), location);
|
||||||
if (consume("SUBALIGN"))
|
if (consume("SUBALIGN"))
|
||||||
cmd->subalignExpr = checkAlignment(readParenExpr(), location);
|
osec->subalignExpr = checkAlignment(readParenExpr(), location);
|
||||||
|
|
||||||
// Parse constraints.
|
// Parse constraints.
|
||||||
if (consume("ONLY_IF_RO"))
|
if (consume("ONLY_IF_RO"))
|
||||||
cmd->constraint = ConstraintKind::ReadOnly;
|
osec->constraint = ConstraintKind::ReadOnly;
|
||||||
if (consume("ONLY_IF_RW"))
|
if (consume("ONLY_IF_RW"))
|
||||||
cmd->constraint = ConstraintKind::ReadWrite;
|
osec->constraint = ConstraintKind::ReadWrite;
|
||||||
expect("{");
|
expect("{");
|
||||||
|
|
||||||
while (!errorCount() && !consume("}")) {
|
while (!errorCount() && !consume("}")) {
|
||||||
|
@ -915,9 +914,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||||
if (tok == ";") {
|
if (tok == ";") {
|
||||||
// Empty commands are allowed. Do nothing here.
|
// Empty commands are allowed. Do nothing here.
|
||||||
} else if (SymbolAssignment *assign = readAssignment(tok)) {
|
} else if (SymbolAssignment *assign = readAssignment(tok)) {
|
||||||
cmd->commands.push_back(assign);
|
osec->commands.push_back(assign);
|
||||||
} else if (ByteCommand *data = readByteCommand(tok)) {
|
} else if (ByteCommand *data = readByteCommand(tok)) {
|
||||||
cmd->commands.push_back(data);
|
osec->commands.push_back(data);
|
||||||
} else if (tok == "CONSTRUCTORS") {
|
} else if (tok == "CONSTRUCTORS") {
|
||||||
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
|
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
|
||||||
// by name. This is for very old file formats such as ECOFF/XCOFF.
|
// by name. This is for very old file formats such as ECOFF/XCOFF.
|
||||||
|
@ -928,13 +927,13 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||||
// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
|
// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
|
||||||
if (peek() != "(")
|
if (peek() != "(")
|
||||||
setError("( expected, but got " + peek());
|
setError("( expected, but got " + peek());
|
||||||
cmd->filler = readFill();
|
osec->filler = readFill();
|
||||||
} else if (tok == "SORT") {
|
} else if (tok == "SORT") {
|
||||||
readSort();
|
readSort();
|
||||||
} else if (tok == "INCLUDE") {
|
} else if (tok == "INCLUDE") {
|
||||||
readInclude();
|
readInclude();
|
||||||
} else if (peek() == "(") {
|
} else if (peek() == "(") {
|
||||||
cmd->commands.push_back(readInputSectionDescription(tok));
|
osec->commands.push_back(readInputSectionDescription(tok));
|
||||||
} else {
|
} else {
|
||||||
// We have a file name and no input sections description. It is not a
|
// We have a file name and no input sections description. It is not a
|
||||||
// commonly used syntax, but still acceptable. In that case, all sections
|
// commonly used syntax, but still acceptable. In that case, all sections
|
||||||
|
@ -944,27 +943,27 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||||
// case above.
|
// case above.
|
||||||
auto *isd = make<InputSectionDescription>(tok);
|
auto *isd = make<InputSectionDescription>(tok);
|
||||||
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
|
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
|
||||||
cmd->commands.push_back(isd);
|
osec->commands.push_back(isd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume(">"))
|
if (consume(">"))
|
||||||
cmd->memoryRegionName = std::string(next());
|
osec->memoryRegionName = std::string(next());
|
||||||
|
|
||||||
if (consume("AT")) {
|
if (consume("AT")) {
|
||||||
expect(">");
|
expect(">");
|
||||||
cmd->lmaRegionName = std::string(next());
|
osec->lmaRegionName = std::string(next());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd->lmaExpr && !cmd->lmaRegionName.empty())
|
if (osec->lmaExpr && !osec->lmaRegionName.empty())
|
||||||
error("section can't have both LMA and a load region");
|
error("section can't have both LMA and a load region");
|
||||||
|
|
||||||
cmd->phdrs = readOutputSectionPhdrs();
|
osec->phdrs = readOutputSectionPhdrs();
|
||||||
|
|
||||||
if (peek() == "=" || peek().startswith("=")) {
|
if (peek() == "=" || peek().startswith("=")) {
|
||||||
inExpr = true;
|
inExpr = true;
|
||||||
consume("=");
|
consume("=");
|
||||||
cmd->filler = readFill();
|
osec->filler = readFill();
|
||||||
inExpr = false;
|
inExpr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,7 +971,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||||
consume(",");
|
consume(",");
|
||||||
|
|
||||||
if (script->referencedSymbols.size() > symbolsReferenced)
|
if (script->referencedSymbols.size() > symbolsReferenced)
|
||||||
cmd->expressionsUseSymbols = true;
|
osec->expressionsUseSymbols = true;
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1318,7 +1317,7 @@ Expr ScriptParser::readPrimary() {
|
||||||
}
|
}
|
||||||
if (tok == "ADDR") {
|
if (tok == "ADDR") {
|
||||||
StringRef name = readParenLiteral();
|
StringRef name = readParenLiteral();
|
||||||
OutputSection *osec = script->getOrCreateOutputSection(name);
|
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
|
||||||
osec->usedInExpression = true;
|
osec->usedInExpression = true;
|
||||||
return [=]() -> ExprValue {
|
return [=]() -> ExprValue {
|
||||||
checkIfExists(*osec, location);
|
checkIfExists(*osec, location);
|
||||||
|
@ -1343,7 +1342,7 @@ Expr ScriptParser::readPrimary() {
|
||||||
}
|
}
|
||||||
if (tok == "ALIGNOF") {
|
if (tok == "ALIGNOF") {
|
||||||
StringRef name = readParenLiteral();
|
StringRef name = readParenLiteral();
|
||||||
OutputSection *osec = script->getOrCreateOutputSection(name);
|
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
|
||||||
return [=] {
|
return [=] {
|
||||||
checkIfExists(*osec, location);
|
checkIfExists(*osec, location);
|
||||||
return osec->alignment;
|
return osec->alignment;
|
||||||
|
@ -1398,7 +1397,7 @@ Expr ScriptParser::readPrimary() {
|
||||||
}
|
}
|
||||||
if (tok == "LOADADDR") {
|
if (tok == "LOADADDR") {
|
||||||
StringRef name = readParenLiteral();
|
StringRef name = readParenLiteral();
|
||||||
OutputSection *osec = script->getOrCreateOutputSection(name);
|
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
|
||||||
osec->usedInExpression = true;
|
osec->usedInExpression = true;
|
||||||
return [=] {
|
return [=] {
|
||||||
checkIfExists(*osec, location);
|
checkIfExists(*osec, location);
|
||||||
|
@ -1442,7 +1441,7 @@ Expr ScriptParser::readPrimary() {
|
||||||
}
|
}
|
||||||
if (tok == "SIZEOF") {
|
if (tok == "SIZEOF") {
|
||||||
StringRef name = readParenLiteral();
|
StringRef name = readParenLiteral();
|
||||||
OutputSection *cmd = script->getOrCreateOutputSection(name);
|
OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
|
||||||
// Linker script does not create an output section if its content is empty.
|
// Linker script does not create an output section if its content is empty.
|
||||||
// We want to allow SIZEOF(.foo) where .foo is a section which happened to
|
// We want to allow SIZEOF(.foo) where .foo is a section which happened to
|
||||||
// be empty.
|
// be empty.
|
||||||
|
|
|
@ -2319,7 +2319,7 @@ bool SymtabShndxSection::isNeeded() const {
|
||||||
// a .symtab_shndx section when the amount of output sections is huge.
|
// a .symtab_shndx section when the amount of output sections is huge.
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (isa<OutputSection>(cmd))
|
if (isa<OutputDesc>(cmd))
|
||||||
++size;
|
++size;
|
||||||
return size >= SHN_LORESERVE;
|
return size >= SHN_LORESERVE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,9 +273,9 @@ void elf::addReservedSymbols() {
|
||||||
|
|
||||||
static OutputSection *findSection(StringRef name, unsigned partition = 1) {
|
static OutputSection *findSection(StringRef name, unsigned partition = 1) {
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
if (sec->name == name && sec->partition == partition)
|
if (osd->osec.name == name && osd->osec.partition == partition)
|
||||||
return sec;
|
return &osd->osec;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,9 +708,10 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
|
||||||
// don't create a section symbol for that section.
|
// don't create a section symbol for that section.
|
||||||
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
|
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
|
||||||
for (SectionCommand *cmd : script->sectionCommands) {
|
for (SectionCommand *cmd : script->sectionCommands) {
|
||||||
auto *sec = dyn_cast<OutputSection>(cmd);
|
auto *osd = dyn_cast<OutputDesc>(cmd);
|
||||||
if (!sec)
|
if (!osd)
|
||||||
continue;
|
continue;
|
||||||
|
OutputSection *sec = &osd->osec;
|
||||||
auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) {
|
auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) {
|
||||||
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
|
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
|
||||||
return !isd->sections.empty();
|
return !isd->sections.empty();
|
||||||
|
@ -974,8 +975,8 @@ static unsigned getSectionRank(const OutputSection &osec) {
|
||||||
|
|
||||||
static bool compareSections(const SectionCommand *aCmd,
|
static bool compareSections(const SectionCommand *aCmd,
|
||||||
const SectionCommand *bCmd) {
|
const SectionCommand *bCmd) {
|
||||||
const OutputSection *a = cast<OutputSection>(aCmd);
|
const OutputSection *a = &cast<OutputDesc>(aCmd)->osec;
|
||||||
const OutputSection *b = cast<OutputSection>(bCmd);
|
const OutputSection *b = &cast<OutputDesc>(bCmd)->osec;
|
||||||
|
|
||||||
if (a->sortRank != b->sortRank)
|
if (a->sortRank != b->sortRank)
|
||||||
return a->sortRank < b->sortRank;
|
return a->sortRank < b->sortRank;
|
||||||
|
@ -1106,13 +1107,15 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
|
||||||
// The more branches in getSectionRank that match, the more similar they are.
|
// The more branches in getSectionRank that match, the more similar they are.
|
||||||
// Since each branch corresponds to a bit flag, we can just use
|
// Since each branch corresponds to a bit flag, we can just use
|
||||||
// countLeadingZeros.
|
// countLeadingZeros.
|
||||||
static int getRankProximityAux(OutputSection *a, OutputSection *b) {
|
static int getRankProximityAux(const OutputSection &a, const OutputSection &b) {
|
||||||
return countLeadingZeros(a->sortRank ^ b->sortRank);
|
return countLeadingZeros(a.sortRank ^ b.sortRank);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getRankProximity(OutputSection *a, SectionCommand *b) {
|
static int getRankProximity(OutputSection *a, SectionCommand *b) {
|
||||||
auto *sec = dyn_cast<OutputSection>(b);
|
auto *osd = dyn_cast<OutputDesc>(b);
|
||||||
return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1;
|
return (osd && osd->osec.hasInputSections)
|
||||||
|
? getRankProximityAux(*a, osd->osec)
|
||||||
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When placing orphan sections, we want to place them after symbol assignments
|
// When placing orphan sections, we want to place them after symbol assignments
|
||||||
|
@ -1141,7 +1144,7 @@ static bool shouldSkip(SectionCommand *cmd) {
|
||||||
static SmallVectorImpl<SectionCommand *>::iterator
|
static SmallVectorImpl<SectionCommand *>::iterator
|
||||||
findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
|
findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
|
||||||
SmallVectorImpl<SectionCommand *>::iterator e) {
|
SmallVectorImpl<SectionCommand *>::iterator e) {
|
||||||
OutputSection *sec = cast<OutputSection>(*e);
|
OutputSection *sec = &cast<OutputDesc>(*e)->osec;
|
||||||
|
|
||||||
// Find the first element that has as close a rank as possible.
|
// Find the first element that has as close a rank as possible.
|
||||||
auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
|
auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
|
||||||
|
@ -1149,9 +1152,9 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
|
||||||
});
|
});
|
||||||
if (i == e)
|
if (i == e)
|
||||||
return e;
|
return e;
|
||||||
auto foundSec = dyn_cast<OutputSection>(*i);
|
if (!isa<OutputDesc>(*i))
|
||||||
if (!foundSec)
|
|
||||||
return e;
|
return e;
|
||||||
|
auto foundSec = &cast<OutputDesc>(*i)->osec;
|
||||||
|
|
||||||
// Consider all existing sections with the same proximity.
|
// Consider all existing sections with the same proximity.
|
||||||
int proximity = getRankProximity(sec, *i);
|
int proximity = getRankProximity(sec, *i);
|
||||||
|
@ -1165,17 +1168,17 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
|
||||||
// resemble the behavior of GNU ld.
|
// resemble the behavior of GNU ld.
|
||||||
sortRank = std::max(sortRank, foundSec->sortRank);
|
sortRank = std::max(sortRank, foundSec->sortRank);
|
||||||
for (; i != e; ++i) {
|
for (; i != e; ++i) {
|
||||||
auto *curSec = dyn_cast<OutputSection>(*i);
|
auto *curSecDesc = dyn_cast<OutputDesc>(*i);
|
||||||
if (!curSec || !curSec->hasInputSections)
|
if (!curSecDesc || !curSecDesc->osec.hasInputSections)
|
||||||
continue;
|
continue;
|
||||||
if (getRankProximity(sec, curSec) != proximity ||
|
if (getRankProximity(sec, curSecDesc) != proximity ||
|
||||||
sortRank < curSec->sortRank)
|
sortRank < curSecDesc->osec.sortRank)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
|
auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
|
||||||
auto *os = dyn_cast<OutputSection>(cmd);
|
auto *osd = dyn_cast<OutputDesc>(cmd);
|
||||||
return os && os->hasInputSections;
|
return osd && osd->osec.hasInputSections;
|
||||||
};
|
};
|
||||||
auto j =
|
auto j =
|
||||||
std::find_if(std::make_reverse_iterator(i), std::make_reverse_iterator(b),
|
std::find_if(std::make_reverse_iterator(i), std::make_reverse_iterator(b),
|
||||||
|
@ -1412,8 +1415,8 @@ template <class ELFT> void Writer<ELFT>::sortInputSections() {
|
||||||
DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
|
DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
|
||||||
maybeShuffle(order);
|
maybeShuffle(order);
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
sortSection(*sec, order);
|
sortSection(osd->osec, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void Writer<ELFT>::sortSections() {
|
template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
|
@ -1429,13 +1432,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
sortInputSections();
|
sortInputSections();
|
||||||
|
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *osec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
osec->sortRank = getSectionRank(*osec);
|
osd->osec.sortRank = getSectionRank(osd->osec);
|
||||||
if (!script->hasSectionsCommand) {
|
if (!script->hasSectionsCommand) {
|
||||||
// We know that all the OutputSections are contiguous in this case.
|
// We know that all the OutputSections are contiguous in this case.
|
||||||
auto isSection = [](SectionCommand *cmd) {
|
auto isSection = [](SectionCommand *cmd) { return isa<OutputDesc>(cmd); };
|
||||||
return isa<OutputSection>(cmd);
|
|
||||||
};
|
|
||||||
std::stable_sort(
|
std::stable_sort(
|
||||||
llvm::find_if(script->sectionCommands, isSection),
|
llvm::find_if(script->sectionCommands, isSection),
|
||||||
llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
|
llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
|
||||||
|
@ -1492,8 +1493,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
auto i = script->sectionCommands.begin();
|
auto i = script->sectionCommands.begin();
|
||||||
auto e = script->sectionCommands.end();
|
auto e = script->sectionCommands.end();
|
||||||
auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) {
|
auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) {
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
return sec->sectionIndex == UINT32_MAX;
|
return osd->osec.sectionIndex == UINT32_MAX;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1513,13 +1514,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
|
|
||||||
while (nonScriptI != e) {
|
while (nonScriptI != e) {
|
||||||
auto pos = findOrphanPos(i, nonScriptI);
|
auto pos = findOrphanPos(i, nonScriptI);
|
||||||
OutputSection *orphan = cast<OutputSection>(*nonScriptI);
|
OutputSection *orphan = &cast<OutputDesc>(*nonScriptI)->osec;
|
||||||
|
|
||||||
// As an optimization, find all sections with the same sort rank
|
// As an optimization, find all sections with the same sort rank
|
||||||
// and insert them with one rotate.
|
// and insert them with one rotate.
|
||||||
unsigned rank = orphan->sortRank;
|
unsigned rank = orphan->sortRank;
|
||||||
auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) {
|
auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) {
|
||||||
return cast<OutputSection>(cmd)->sortRank != rank;
|
return cast<OutputDesc>(cmd)->osec.sortRank != rank;
|
||||||
});
|
});
|
||||||
std::rotate(pos, nonScriptI, end);
|
std::rotate(pos, nonScriptI, end);
|
||||||
nonScriptI = end;
|
nonScriptI = end;
|
||||||
|
@ -1668,11 +1669,13 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
|
||||||
// If addrExpr is set, the address may not be a multiple of the alignment.
|
// If addrExpr is set, the address may not be a multiple of the alignment.
|
||||||
// Warn because this is error-prone.
|
// Warn because this is error-prone.
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *os = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
|
||||||
if (os->addr % os->alignment != 0)
|
OutputSection *osec = &osd->osec;
|
||||||
warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " +
|
if (osec->addr % osec->alignment != 0)
|
||||||
os->name + " is not a multiple of alignment (" +
|
warn("address (0x" + Twine::utohexstr(osec->addr) + ") of section " +
|
||||||
Twine(os->alignment) + ")");
|
osec->name + " is not a multiple of alignment (" +
|
||||||
|
Twine(osec->alignment) + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Input Sections have been shrunk (basic block sections) then
|
// If Input Sections have been shrunk (basic block sections) then
|
||||||
|
@ -1819,8 +1822,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||||
if (!config->relocatable) {
|
if (!config->relocatable) {
|
||||||
addStartEndSymbols();
|
addStartEndSymbols();
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *sec = dyn_cast<OutputSection>(cmd))
|
if (auto *osd = dyn_cast<OutputDesc>(cmd))
|
||||||
addStartStopSymbols(*sec);
|
addStartStopSymbols(osd->osec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
|
// Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
|
||||||
|
@ -1988,7 +1991,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||||
// Create a list of OutputSections, assign sectionIndex, and populate
|
// Create a list of OutputSections, assign sectionIndex, and populate
|
||||||
// in.shStrTab.
|
// in.shStrTab.
|
||||||
for (SectionCommand *cmd : script->sectionCommands)
|
for (SectionCommand *cmd : script->sectionCommands)
|
||||||
if (auto *osec = dyn_cast<OutputSection>(cmd)) {
|
if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
|
||||||
|
OutputSection *osec = &osd->osec;
|
||||||
outputSections.push_back(osec);
|
outputSections.push_back(osec);
|
||||||
osec->sectionIndex = outputSections.size();
|
osec->sectionIndex = outputSections.size();
|
||||||
osec->shName = in.shStrTab->addString(osec->name);
|
osec->shName = in.shStrTab->addString(osec->name);
|
||||||
|
|
Loading…
Reference in New Issue