mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-12 10:52:38 +00:00
Improve handling ASSERT outside SECTIONS block
Differential revision: https://reviews.llvm.org/D24450 llvm-svn: 281740
This commit is contained in:
parent
85ef4a1c47
commit
20d031948e
@ -48,6 +48,11 @@ template <class ELFT> static void addRegular(SymbolAssignment *Cmd) {
|
||||
Symbol *Sym = Symtab<ELFT>::X->addRegular(Cmd->Name, STB_GLOBAL, STV_DEFAULT);
|
||||
Sym->Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
Cmd->Sym = Sym->body();
|
||||
|
||||
// If we have no SECTIONS then we don't have '.' and don't call
|
||||
// assignAddresses(). We calculate symbol value immediately in this case.
|
||||
if (!ScriptConfig->HasSections)
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(0);
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
|
||||
@ -215,15 +220,6 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT> void LinkerScript<ELFT>::createAssignments() {
|
||||
for (const std::unique_ptr<SymbolAssignment> &Cmd : Opt.Assignments) {
|
||||
if (shouldDefine<ELFT>(Cmd.get()))
|
||||
addRegular<ELFT>(Cmd.get());
|
||||
if (Cmd->Sym)
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(0);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName) {
|
||||
@ -256,15 +252,19 @@ static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
||||
auto AddSec = [&](InputSectionBase<ELFT> *Sec, StringRef Name) {
|
||||
OutputSectionBase<ELFT> *OutSec;
|
||||
bool IsNew;
|
||||
std::tie(OutSec, IsNew) = Factory.create(createKey(Sec, Name), Sec);
|
||||
if (IsNew)
|
||||
OutputSections->push_back(OutSec);
|
||||
return OutSec;
|
||||
};
|
||||
void LinkerScript<ELFT>::addSection(OutputSectionFactory<ELFT> &Factory,
|
||||
InputSectionBase<ELFT> *Sec,
|
||||
StringRef Name) {
|
||||
OutputSectionBase<ELFT> *OutSec;
|
||||
bool IsNew;
|
||||
std::tie(OutSec, IsNew) = Factory.create(createKey(Sec, Name), Sec);
|
||||
if (IsNew)
|
||||
OutputSections->push_back(OutSec);
|
||||
OutSec->addSection(Sec);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
||||
|
||||
for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands) {
|
||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
|
||||
@ -272,6 +272,14 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
||||
addRegular<ELFT>(Cmd);
|
||||
continue;
|
||||
}
|
||||
if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
|
||||
// If we don't have SECTIONS then output sections have already been
|
||||
// created by Writer<EFLT>. The LinkerScript<ELFT>::assignAddresses
|
||||
// will not be called, so ASSERT should be evaluated now.
|
||||
if (!Opt.HasSections)
|
||||
Cmd->Expression(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
|
||||
std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd);
|
||||
@ -285,25 +293,22 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
||||
continue;
|
||||
|
||||
for (InputSectionBase<ELFT> *Sec : V) {
|
||||
OutputSectionBase<ELFT> *OutSec = AddSec(Sec, Cmd->Name);
|
||||
uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0;
|
||||
|
||||
if (Subalign)
|
||||
addSection(Factory, Sec, Cmd->Name);
|
||||
if (uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0)
|
||||
Sec->Alignment = Subalign;
|
||||
OutSec->addSection(Sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
||||
processCommands(Factory);
|
||||
// Add orphan sections.
|
||||
for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
|
||||
for (InputSectionBase<ELFT> *S : F->getSections()) {
|
||||
if (isDiscarded(S) || S->OutSec)
|
||||
continue;
|
||||
OutputSectionBase<ELFT> *OutSec = AddSec(S, getOutputSectionName(S));
|
||||
OutSec->addSection(S);
|
||||
}
|
||||
}
|
||||
for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
|
||||
for (InputSectionBase<ELFT> *S : F->getSections())
|
||||
if (!isDiscarded(S) && !S->OutSec)
|
||||
addSection(Factory, S, getOutputSectionName(S));
|
||||
}
|
||||
|
||||
// Sets value of a section-defined symbol. Two kinds of
|
||||
@ -754,7 +759,9 @@ void ScriptParser::readLinkerScript() {
|
||||
if (Tok == ";")
|
||||
continue;
|
||||
|
||||
if (Tok == "ENTRY") {
|
||||
if (Tok == "ASSERT") {
|
||||
Opt.Commands.emplace_back(new AssertCommand(readAssert()));
|
||||
} else if (Tok == "ENTRY") {
|
||||
readEntry();
|
||||
} else if (Tok == "EXTERN") {
|
||||
readExtern();
|
||||
@ -777,10 +784,7 @@ void ScriptParser::readLinkerScript() {
|
||||
} else if (Tok == "VERSION") {
|
||||
readVersion();
|
||||
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) {
|
||||
if (Opt.HasSections)
|
||||
Opt.Commands.emplace_back(Cmd);
|
||||
else
|
||||
Opt.Assignments.emplace_back(Cmd);
|
||||
Opt.Commands.emplace_back(Cmd);
|
||||
} else {
|
||||
setError("unknown directive: " + Tok);
|
||||
}
|
||||
|
@ -140,8 +140,6 @@ public:
|
||||
|
||||
// ScriptConfiguration holds linker script parse results.
|
||||
struct ScriptConfiguration {
|
||||
// Used to create symbol assignments outside SECTIONS command.
|
||||
std::vector<std::unique_ptr<SymbolAssignment>> Assignments;
|
||||
// Used to assign addresses to sections.
|
||||
std::vector<std::unique_ptr<BaseCommand>> Commands;
|
||||
|
||||
@ -166,7 +164,7 @@ template <class ELFT> class LinkerScript final : public LinkerScriptBase {
|
||||
public:
|
||||
LinkerScript();
|
||||
~LinkerScript();
|
||||
void createAssignments();
|
||||
void processCommands(OutputSectionFactory<ELFT> &Factory);
|
||||
void createSections(OutputSectionFactory<ELFT> &Factory);
|
||||
|
||||
std::vector<PhdrEntry<ELFT>> createPhdrs();
|
||||
@ -191,6 +189,8 @@ private:
|
||||
void computeInputSections(InputSectionDescription *,
|
||||
ConstraintKind Constraint);
|
||||
|
||||
void addSection(OutputSectionFactory<ELFT> &Factory,
|
||||
InputSectionBase<ELFT> *Sec, StringRef Name);
|
||||
void discard(ArrayRef<InputSectionBase<ELFT> *> V);
|
||||
|
||||
std::vector<InputSectionBase<ELFT> *>
|
||||
|
@ -249,13 +249,13 @@ template <class ELFT> void Writer<ELFT>::run() {
|
||||
CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
|
||||
CommonInputSection<ELFT>::X = &Common;
|
||||
|
||||
Script<ELFT>::X->createAssignments();
|
||||
|
||||
Script<ELFT>::X->OutputSections = &OutputSections;
|
||||
if (ScriptConfig->HasSections)
|
||||
if (ScriptConfig->HasSections) {
|
||||
Script<ELFT>::X->createSections(Factory);
|
||||
else
|
||||
} else {
|
||||
createSections();
|
||||
Script<ELFT>::X->processCommands(Factory);
|
||||
}
|
||||
|
||||
finalizeSections();
|
||||
if (HasError)
|
||||
|
@ -25,3 +25,18 @@
|
||||
# RUN: }" > %t4.script
|
||||
# RUN: ld.lld -shared -o %t4 --script %t4.script %t1.o
|
||||
# RUN: llvm-readobj %t4 > /dev/null
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .foo : { *(.foo) } \
|
||||
# RUN: } \
|
||||
# RUN: ASSERT(SIZEOF(.foo) == 8, \"true\");" > %t5.script
|
||||
# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o
|
||||
# RUN: llvm-readobj %t5 > /dev/null
|
||||
|
||||
## Even without SECTIONS block we still use section names
|
||||
## in expressions
|
||||
# RUN: echo "ASSERT(SIZEOF(.foo) == 8, \"true\");" > %t5.script
|
||||
# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o
|
||||
# RUN: llvm-readobj %t5 > /dev/null
|
||||
.section .foo, "a"
|
||||
.quad 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user