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:
Rui Ueyama 2016-04-22 00:03:13 +00:00
parent 04e7fb778d
commit c998a8c044
2 changed files with 30 additions and 22 deletions

View File

@ -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;
} }
} }

View File

@ -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