forked from OSchip/llvm-project
ELF: Make the special variable "." as a LinkerScript class member.
I will eventually make `evaluate` function a usual parse function rather than a function that works on a separate token list. This is the first step toward that. llvm-svn: 267083
This commit is contained in:
parent
04e7fb778d
commit
c998a8c044
|
|
@ -80,17 +80,16 @@ static bool expect(ArrayRef<StringRef> &Tokens, StringRef S) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t parseExpr(ArrayRef<StringRef> &Tokens, uint64_t Dot);
|
|
||||||
|
|
||||||
// This is a part of the operator-precedence parser to evaluate
|
// This is a part of the operator-precedence parser to evaluate
|
||||||
// arithmetic expressions in SECTIONS command. This function evaluates an
|
// arithmetic expressions in SECTIONS command. This function evaluates an
|
||||||
// integer literal, a parenthesized expression or the special variable ".".
|
// integer literal, a parenthesized expression or the special variable ".".
|
||||||
static uint64_t parsePrimary(ArrayRef<StringRef> &Tokens, uint64_t Dot) {
|
template <class ELFT>
|
||||||
|
uint64_t LinkerScript<ELFT>::parsePrimary(ArrayRef<StringRef> &Tokens) {
|
||||||
StringRef Tok = next(Tokens);
|
StringRef Tok = next(Tokens);
|
||||||
if (Tok == ".")
|
if (Tok == ".")
|
||||||
return Dot;
|
return Dot;
|
||||||
if (Tok == "(") {
|
if (Tok == "(") {
|
||||||
uint64_t V = parseExpr(Tokens, Dot);
|
uint64_t V = parseExpr(Tokens);
|
||||||
if (!expect(Tokens, ")"))
|
if (!expect(Tokens, ")"))
|
||||||
return 0;
|
return 0;
|
||||||
return V;
|
return V;
|
||||||
|
|
@ -121,15 +120,16 @@ static uint64_t apply(StringRef Op, uint64_t L, uint64_t R) {
|
||||||
// This is an operator-precedence parser to evaluate
|
// This is an operator-precedence parser to evaluate
|
||||||
// arithmetic expressions in SECTIONS command.
|
// arithmetic expressions in SECTIONS command.
|
||||||
// Tokens should start with an operator.
|
// Tokens should start with an operator.
|
||||||
static uint64_t parseExpr1(uint64_t Lhs, int MinPrec,
|
template <class ELFT>
|
||||||
ArrayRef<StringRef> &Tokens, uint64_t Dot) {
|
uint64_t LinkerScript<ELFT>::parseExpr1(ArrayRef<StringRef> &Tokens,
|
||||||
|
uint64_t Lhs, int MinPrec) {
|
||||||
while (!Tokens.empty()) {
|
while (!Tokens.empty()) {
|
||||||
// Read an operator and an expression.
|
// Read an operator and an expression.
|
||||||
StringRef Op1 = Tokens.front();
|
StringRef Op1 = Tokens.front();
|
||||||
if (precedence(Op1) < MinPrec)
|
if (precedence(Op1) < MinPrec)
|
||||||
return Lhs;
|
return Lhs;
|
||||||
next(Tokens);
|
next(Tokens);
|
||||||
uint64_t Rhs = parsePrimary(Tokens, Dot);
|
uint64_t Rhs = parsePrimary(Tokens);
|
||||||
|
|
||||||
// Evaluate the remaining part of the expression first if the
|
// Evaluate the remaining part of the expression first if the
|
||||||
// next operator has greater precedence than the previous one.
|
// next operator has greater precedence than the previous one.
|
||||||
|
|
@ -139,7 +139,7 @@ static uint64_t parseExpr1(uint64_t Lhs, int MinPrec,
|
||||||
StringRef Op2 = Tokens.front();
|
StringRef Op2 = Tokens.front();
|
||||||
if (precedence(Op2) <= precedence(Op1))
|
if (precedence(Op2) <= precedence(Op1))
|
||||||
break;
|
break;
|
||||||
Rhs = parseExpr1(Rhs, precedence(Op2), Tokens, Dot);
|
Rhs = parseExpr1(Tokens, Rhs, precedence(Op2));
|
||||||
}
|
}
|
||||||
|
|
||||||
Lhs = apply(Op1, Lhs, Rhs);
|
Lhs = apply(Op1, Lhs, Rhs);
|
||||||
|
|
@ -147,14 +147,16 @@ static uint64_t parseExpr1(uint64_t Lhs, int MinPrec,
|
||||||
return Lhs;
|
return Lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t parseExpr(ArrayRef<StringRef> &Tokens, uint64_t Dot) {
|
template <class ELFT>
|
||||||
uint64_t V = parsePrimary(Tokens, Dot);
|
uint64_t LinkerScript<ELFT>::parseExpr(ArrayRef<StringRef> &Tokens) {
|
||||||
return parseExpr1(V, 0, Tokens, Dot);
|
uint64_t V = parsePrimary(Tokens);
|
||||||
|
return parseExpr1(Tokens, V, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluates the expression given by list of tokens.
|
// Evaluates the expression given by list of tokens.
|
||||||
static uint64_t evaluate(ArrayRef<StringRef> Tokens, uint64_t Dot) {
|
template <class ELFT>
|
||||||
uint64_t V = parseExpr(Tokens, Dot);
|
uint64_t LinkerScript<ELFT>::evaluate(ArrayRef<StringRef> Tokens) {
|
||||||
|
uint64_t V = parseExpr(Tokens);
|
||||||
if (!Tokens.empty())
|
if (!Tokens.empty())
|
||||||
error("stray token: " + Tokens[0]);
|
error("stray token: " + Tokens[0]);
|
||||||
return V;
|
return V;
|
||||||
|
|
@ -207,13 +209,12 @@ void LinkerScript<ELFT>::assignAddresses(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
||||||
|
Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
|
||||||
uintX_t ThreadBssOffset = 0;
|
uintX_t ThreadBssOffset = 0;
|
||||||
uintX_t VA =
|
|
||||||
Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
|
|
||||||
|
|
||||||
for (SectionsCommand &Cmd : Opt.Commands) {
|
for (SectionsCommand &Cmd : Opt.Commands) {
|
||||||
if (Cmd.Kind == ExprKind) {
|
if (Cmd.Kind == ExprKind) {
|
||||||
VA = evaluate(Cmd.Expr, VA);
|
Dot = evaluate(Cmd.Expr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,17 +223,17 @@ void LinkerScript<ELFT>::assignAddresses(
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
||||||
uintX_t TVA = VA + ThreadBssOffset;
|
uintX_t TVA = Dot + ThreadBssOffset;
|
||||||
TVA = alignTo(TVA, Sec->getAlign());
|
TVA = alignTo(TVA, Sec->getAlign());
|
||||||
Sec->setVA(TVA);
|
Sec->setVA(TVA);
|
||||||
ThreadBssOffset = TVA - VA + Sec->getSize();
|
ThreadBssOffset = TVA - Dot + Sec->getSize();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sec->getFlags() & SHF_ALLOC) {
|
if (Sec->getFlags() & SHF_ALLOC) {
|
||||||
VA = alignTo(VA, Sec->getAlign());
|
Dot = alignTo(Dot, Sec->getAlign());
|
||||||
Sec->setVA(VA);
|
Sec->setVA(Dot);
|
||||||
VA += Sec->getSize();
|
Dot += Sec->getSize();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,10 +86,17 @@ public:
|
||||||
int compareSections(StringRef A, StringRef B);
|
int compareSections(StringRef A, StringRef B);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// "ScriptConfig" is a bit too long, so define a short name for it.
|
||||||
|
ScriptConfiguration &Opt = *ScriptConfig;
|
||||||
|
|
||||||
int getSectionIndex(StringRef Name);
|
int getSectionIndex(StringRef Name);
|
||||||
SectionRule *find(InputSectionBase<ELFT> *S);
|
SectionRule *find(InputSectionBase<ELFT> *S);
|
||||||
|
|
||||||
ScriptConfiguration &Opt = *ScriptConfig;
|
uint64_t evaluate(ArrayRef<StringRef> Tokens);
|
||||||
|
uint64_t parseExpr(ArrayRef<StringRef> &Tokens);
|
||||||
|
uint64_t parsePrimary(ArrayRef<StringRef> &Tokens);
|
||||||
|
uint64_t parseExpr1(ArrayRef<StringRef> &Tokens, uint64_t Lhs, int MinPrec);
|
||||||
|
typename ELFT::uint Dot;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variable template is a C++14 feature, so we can't template
|
// Variable template is a C++14 feature, so we can't template
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue