Move IsAbsolute from SymbolAssignment to Expr.

And as a token of the new feature, make ALIGNOF always absolute.

This is a step in making it possible to have non absolute symbols out
of output sections.

llvm-svn: 285608
This commit is contained in:
Rafael Espindola 2016-10-31 17:43:38 +00:00
parent 86a1ef388b
commit f661393ad6
3 changed files with 37 additions and 12 deletions

View File

@ -64,7 +64,7 @@ template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
}
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
if (Cmd->IsAbsolute)
if (Cmd->Expression.IsAbsolute)
addRegular<ELFT>(Cmd);
else
addSynthetic<ELFT>(Cmd);
@ -1424,7 +1424,7 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
Cmd = readProvideHidden(true, true);
}
if (Cmd && MakeAbsolute)
Cmd->IsAbsolute = true;
Cmd->Expression.IsAbsolute = true;
return Cmd;
}
@ -1436,20 +1436,19 @@ static uint64_t getSymbolValue(StringRef S, uint64_t Dot) {
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
StringRef Op = next();
bool IsAbsolute = false;
Expr E;
assert(Op == "=" || Op == "+=");
if (consume("ABSOLUTE")) {
// The RHS may be something like "ABSOLUTE(.) & 0xff".
// Call readExpr1 to read the whole expression.
E = readExpr1(readParenExpr(), 0);
IsAbsolute = true;
E.IsAbsolute = true;
} else {
E = readExpr();
}
if (Op == "+=")
E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
return new SymbolAssignment(Name, E, IsAbsolute);
return new SymbolAssignment(Name, E);
}
// This is an operator-precedence parser to parse a linker
@ -1671,8 +1670,9 @@ Expr ScriptParser::readPrimary() {
}
if (Tok == "ALIGNOF") {
StringRef Name = readParenLiteral();
return
[=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); };
return {
[=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); },
true};
}
if (Tok == "SIZEOF_HEADERS")
return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); };

View File

@ -37,7 +37,17 @@ class InputSectionData;
// ScriptParser::readExpr reads an expression and returns an Expr.
// Later, we evaluate the expression by calling the function
// with the value of special context variable ".".
typedef std::function<uint64_t(uint64_t)> Expr;
struct Expr {
std::function<uint64_t(uint64_t)> Val;
bool IsAbsolute;
uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
operator bool() const { return (bool)Val; }
template <typename T>
Expr(T Val, bool IsAbsolute) : Val(Val), IsAbsolute(IsAbsolute) {}
template <typename T> Expr(T V) : Expr(V, false) {}
Expr() : Expr(nullptr) {}
};
// Parses a linker script. Calling this function updates
// Config and ScriptConfig.
@ -64,9 +74,8 @@ struct BaseCommand {
// This represents ". = <expr>" or "<symbol> = <expr>".
struct SymbolAssignment : BaseCommand {
SymbolAssignment(StringRef Name, Expr E, bool IsAbsolute)
: BaseCommand(AssignmentKind), Name(Name), Expression(E),
IsAbsolute(IsAbsolute) {}
SymbolAssignment(StringRef Name, Expr E)
: BaseCommand(AssignmentKind), Name(Name), Expression(E) {}
static bool classof(const BaseCommand *C);
// The LHS of an expression. Name is either a symbol name or ".".
@ -79,7 +88,6 @@ struct SymbolAssignment : BaseCommand {
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
bool Provide = false;
bool Hidden = false;
bool IsAbsolute;
};
// Linker scripts allow additional constraints to be put on ouput sections.

View File

@ -0,0 +1,17 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: echo "SECTIONS { \
# RUN: .text : { bar = ALIGNOF(.text); *(.text) } \
# RUN: };" > %t.script
# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
# RUN: llvm-readobj -t %t.so | FileCheck %s
# CHECK: Symbol {
# CHECK: Name: bar
# CHECK-NEXT: Value: 0x4
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Binding: Global
# CHECK-NEXT: Type: None
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }