forked from OSchip/llvm-project
[ELF] Support for symbol assignment in linker scripts within SECTIONS {} block
llvm-svn: 275158
This commit is contained in:
parent
425175934e
commit
eda81a1b86
|
@ -20,6 +20,7 @@
|
|||
#include "OutputSections.h"
|
||||
#include "ScriptParser.h"
|
||||
#include "Strings.h"
|
||||
#include "Symbols.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Target.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
@ -226,16 +227,25 @@ void LinkerScript<ELFT>::assignAddresses(
|
|||
uintX_t ThreadBssOffset = 0;
|
||||
|
||||
for (SectionsCommand &Cmd : Opt.Commands) {
|
||||
if (Cmd.Kind == ExprKind) {
|
||||
switch (Cmd.Kind) {
|
||||
case ExprKind:
|
||||
Dot = evalExpr(Cmd.Expr, Dot);
|
||||
continue;
|
||||
case SymbolAssignmentKind: {
|
||||
auto *D =
|
||||
cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd.Name));
|
||||
D->Value = evalExpr(Cmd.Expr, Dot);
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Find all the sections with required name. There can be more than
|
||||
// ont section with such name, if the alignment, flags or type
|
||||
// attribute differs.
|
||||
for (OutputSectionBase<ELFT> *Sec : Sections) {
|
||||
if (Sec->getName() != Cmd.SectionName)
|
||||
if (Sec->getName() != Cmd.Name)
|
||||
continue;
|
||||
|
||||
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
||||
|
@ -283,7 +293,7 @@ int LinkerScript<ELFT>::getSectionIndex(StringRef Name) {
|
|||
auto Begin = Opt.Commands.begin();
|
||||
auto End = Opt.Commands.end();
|
||||
auto I = std::find_if(Begin, End, [&](SectionsCommand &N) {
|
||||
return N.Kind == SectionKind && N.SectionName == Name;
|
||||
return N.Kind == SectionKind && N.Name == Name;
|
||||
});
|
||||
return I == End ? INT_MAX : (I - Begin);
|
||||
}
|
||||
|
@ -299,6 +309,13 @@ int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
|
|||
return I < J ? -1 : 1;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LinkerScript<ELFT>::addScriptedSymbols() {
|
||||
for (SectionsCommand &Cmd : Opt.Commands)
|
||||
if (Cmd.Kind == SymbolAssignmentKind)
|
||||
Symtab<ELFT>::X->addAbsolute(Cmd.Name, STV_DEFAULT);
|
||||
}
|
||||
|
||||
class elf::ScriptParser : public ScriptParserBase {
|
||||
typedef void (ScriptParser::*Handler)();
|
||||
|
||||
|
@ -323,7 +340,9 @@ private:
|
|||
void readSections();
|
||||
|
||||
void readLocationCounterValue();
|
||||
void readOutputSectionDescription();
|
||||
void readOutputSectionDescription(StringRef OutSec);
|
||||
void readSymbolAssignment(StringRef Name);
|
||||
std::vector<StringRef> readSectionsCommandExpr();
|
||||
|
||||
const static StringMap<Handler> Cmd;
|
||||
ScriptConfiguration &Opt = *ScriptConfig;
|
||||
|
@ -487,30 +506,29 @@ void ScriptParser::readSections() {
|
|||
expect("{");
|
||||
while (!Error && !skip("}")) {
|
||||
StringRef Tok = peek();
|
||||
if (Tok == ".")
|
||||
if (Tok == ".") {
|
||||
readLocationCounterValue();
|
||||
continue;
|
||||
}
|
||||
next();
|
||||
if (peek() == "=")
|
||||
readSymbolAssignment(Tok);
|
||||
else
|
||||
readOutputSectionDescription();
|
||||
readOutputSectionDescription(Tok);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptParser::readLocationCounterValue() {
|
||||
expect(".");
|
||||
expect("=");
|
||||
Opt.Commands.push_back({ExprKind, {}, ""});
|
||||
SectionsCommand &Cmd = Opt.Commands.back();
|
||||
while (!Error) {
|
||||
StringRef Tok = next();
|
||||
if (Tok == ";")
|
||||
break;
|
||||
Cmd.Expr.push_back(Tok);
|
||||
}
|
||||
if (Cmd.Expr.empty())
|
||||
std::vector<StringRef> Expr = readSectionsCommandExpr();
|
||||
if (Expr.empty())
|
||||
error("error in location counter expression");
|
||||
else
|
||||
Opt.Commands.push_back({ExprKind, std::move(Expr), ""});
|
||||
}
|
||||
|
||||
void ScriptParser::readOutputSectionDescription() {
|
||||
StringRef OutSec = next();
|
||||
void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||
Opt.Commands.push_back({SectionKind, {}, OutSec});
|
||||
expect(":");
|
||||
expect("{");
|
||||
|
@ -548,6 +566,26 @@ void ScriptParser::readOutputSectionDescription() {
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptParser::readSymbolAssignment(StringRef Name) {
|
||||
expect("=");
|
||||
std::vector<StringRef> Expr = readSectionsCommandExpr();
|
||||
if (Expr.empty())
|
||||
error("error in symbol assignment expression");
|
||||
else
|
||||
Opt.Commands.push_back({SymbolAssignmentKind, std::move(Expr), Name});
|
||||
}
|
||||
|
||||
std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
|
||||
std::vector<StringRef> Expr;
|
||||
while (!Error) {
|
||||
StringRef Tok = next();
|
||||
if (Tok == ";")
|
||||
break;
|
||||
Expr.push_back(Tok);
|
||||
}
|
||||
return Expr;
|
||||
}
|
||||
|
||||
static bool isUnderSysroot(StringRef Path) {
|
||||
if (Config->Sysroot == "")
|
||||
return false;
|
||||
|
|
|
@ -40,12 +40,12 @@ struct SectionRule {
|
|||
// This enum represents what we can observe in SECTIONS tag of script:
|
||||
// ExprKind is a location counter change, like ". = . + 0x1000"
|
||||
// SectionKind is a description of output section, like ".data :..."
|
||||
enum SectionsCommandKind { ExprKind, SectionKind };
|
||||
enum SectionsCommandKind { ExprKind, SectionKind, SymbolAssignmentKind };
|
||||
|
||||
struct SectionsCommand {
|
||||
SectionsCommandKind Kind;
|
||||
std::vector<StringRef> Expr;
|
||||
StringRef SectionName;
|
||||
StringRef Name;
|
||||
};
|
||||
|
||||
// ScriptConfiguration holds linker script parse results.
|
||||
|
@ -81,6 +81,7 @@ public:
|
|||
bool shouldKeep(InputSectionBase<ELFT> *S);
|
||||
void assignAddresses(ArrayRef<OutputSectionBase<ELFT> *> S);
|
||||
int compareSections(StringRef A, StringRef B);
|
||||
void addScriptedSymbols();
|
||||
|
||||
private:
|
||||
// "ScriptConfig" is a bit too long, so define a short name for it.
|
||||
|
|
|
@ -786,6 +786,10 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
|||
// Define __rel[a]_iplt_{start,end} symbols if needed.
|
||||
addRelIpltSymbols();
|
||||
|
||||
// Add scripted symbols with zero values now.
|
||||
// Real values will be assigned later
|
||||
Script<ELFT>::X->addScriptedSymbols();
|
||||
|
||||
if (!Out<ELFT>::EhFrame->empty()) {
|
||||
OutputSections.push_back(Out<ELFT>::EhFrame);
|
||||
Out<ELFT>::EhFrame->finalize();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
|
||||
# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
|
||||
# CHECK: 0000000000000121 *ABS* 00000000 text_end
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
nop
|
Loading…
Reference in New Issue