forked from OSchip/llvm-project
Support ABSOLUE keyword in symbol assignments
This patch allows making section defined symbols absolute: .foo : { begin_foo = ABSOLUTE(.); *(.foo) } Differential revision: https://reviews.llvm.org/D24135 llvm-svn: 280788
This commit is contained in:
parent
f333de3752
commit
db741e7203
|
@ -56,6 +56,12 @@ template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
|
|||
Cmd->Sym = Sym->body();
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
|
||||
if (Cmd->IsAbsolute)
|
||||
addRegular<ELFT>(Cmd);
|
||||
else
|
||||
addSynthetic<ELFT>(Cmd);
|
||||
}
|
||||
// If a symbol was in PROVIDE(), we need to define it only when
|
||||
// it is an undefined symbol.
|
||||
template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
|
||||
|
@ -184,7 +190,7 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
|
|||
for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
|
||||
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
||||
if (shouldDefine<ELFT>(OutCmd))
|
||||
addSynthetic<ELFT>(OutCmd);
|
||||
addSymbol<ELFT>(OutCmd);
|
||||
OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
|
||||
continue;
|
||||
}
|
||||
|
@ -267,6 +273,26 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
|||
}
|
||||
}
|
||||
|
||||
// Sets value of a section-defined symbol. Two kinds of
|
||||
// symbols are processed: synthetic symbols, whose value
|
||||
// is an offset from beginning of section and regular
|
||||
// symbols whose value is absolute.
|
||||
template <class ELFT>
|
||||
static void assignSectionSymbol(SymbolAssignment *Cmd,
|
||||
OutputSectionBase<ELFT> *Sec,
|
||||
typename ELFT::uint Off) {
|
||||
if (!Cmd->Sym)
|
||||
return;
|
||||
|
||||
if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
|
||||
Body->Section = Sec;
|
||||
Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
|
||||
return;
|
||||
}
|
||||
auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
|
||||
Body->Value = Cmd->Expression(Sec->getVA() + Off);
|
||||
}
|
||||
|
||||
// Linker script may define start and end symbols for special section types,
|
||||
// like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
|
||||
// of regular input input sections, therefore our way of defining symbols for
|
||||
|
@ -280,12 +306,7 @@ void addStartEndSymbols(OutputSectionCommand *Cmd,
|
|||
|
||||
for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
|
||||
if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
||||
if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
|
||||
Sym->Section = Sec;
|
||||
Sym->Value =
|
||||
AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
|
||||
Sec->getVA();
|
||||
}
|
||||
assignSectionSymbol<ELFT>(AssignCmd, Sec, Start ? 0 : Sec->getSize());
|
||||
} else {
|
||||
if (!Start && isa<SymbolAssignment>(PrevCmd))
|
||||
error("section '" + Sec->getName() +
|
||||
|
@ -322,19 +343,13 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) {
|
|||
if (D != AssignCmd->GoesAfter)
|
||||
break;
|
||||
|
||||
uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
|
||||
if (AssignCmd->Name == ".") {
|
||||
// Update to location counter means update to section size.
|
||||
Off = Value;
|
||||
Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
|
||||
Sec->setSize(Off);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DefinedSynthetic<ELFT> *Sym =
|
||||
cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
|
||||
Sym->Section = OutSec;
|
||||
Sym->Value = Value;
|
||||
}
|
||||
assignSectionSymbol<ELFT>(AssignCmd, Sec, Off);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -631,7 +646,7 @@ private:
|
|||
unsigned readPhdrType();
|
||||
SortKind readSortKind();
|
||||
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
|
||||
SymbolAssignment *readProvideOrAssignment(StringRef Tok);
|
||||
SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
|
||||
void readSort();
|
||||
Expr readAssert();
|
||||
|
||||
|
@ -710,7 +725,7 @@ void ScriptParser::readLinkerScript() {
|
|||
readSections();
|
||||
} else if (Tok == "VERSION") {
|
||||
readVersion();
|
||||
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
|
||||
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) {
|
||||
if (Opt.HasContents)
|
||||
Opt.Commands.emplace_back(Cmd);
|
||||
else
|
||||
|
@ -872,7 +887,7 @@ void ScriptParser::readSections() {
|
|||
expect("{");
|
||||
while (!Error && !skip("}")) {
|
||||
StringRef Tok = next();
|
||||
BaseCommand *Cmd = readProvideOrAssignment(Tok);
|
||||
BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
|
||||
if (!Cmd) {
|
||||
if (Tok == "ASSERT")
|
||||
Cmd = new AssertCommand(readAssert());
|
||||
|
@ -1020,7 +1035,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
|||
|
||||
while (!Error && !skip("}")) {
|
||||
StringRef Tok = next();
|
||||
if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok))
|
||||
if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok, false))
|
||||
Cmd->Commands.emplace_back(Assignment);
|
||||
else if (Tok == "FILL")
|
||||
Cmd->Filler = readFill();
|
||||
|
@ -1063,7 +1078,8 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) {
|
|||
return Cmd;
|
||||
}
|
||||
|
||||
SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
|
||||
SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
|
||||
bool MakeAbsolute) {
|
||||
SymbolAssignment *Cmd = nullptr;
|
||||
if (peek() == "=" || peek() == "+=") {
|
||||
Cmd = readAssignment(Tok);
|
||||
|
@ -1075,6 +1091,8 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
|
|||
} else if (Tok == "PROVIDE_HIDDEN") {
|
||||
Cmd = readProvideHidden(true, true);
|
||||
}
|
||||
if (Cmd && MakeAbsolute)
|
||||
Cmd->IsAbsolute = true;
|
||||
return Cmd;
|
||||
}
|
||||
|
||||
|
@ -1153,11 +1171,18 @@ static uint64_t getHeaderSize() {
|
|||
|
||||
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
|
||||
StringRef Op = next();
|
||||
bool IsAbsolute = false;
|
||||
Expr E;
|
||||
assert(Op == "=" || Op == "+=");
|
||||
Expr E = readExpr();
|
||||
if (skip("ABSOLUTE")) {
|
||||
E = readParenExpr();
|
||||
IsAbsolute = true;
|
||||
} else {
|
||||
E = readExpr();
|
||||
}
|
||||
if (Op == "+=")
|
||||
E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
|
||||
return new SymbolAssignment(Name, E);
|
||||
return new SymbolAssignment(Name, E, IsAbsolute);
|
||||
}
|
||||
|
||||
// This is an operator-precedence parser to parse a linker
|
||||
|
|
|
@ -54,8 +54,9 @@ struct BaseCommand {
|
|||
};
|
||||
|
||||
struct SymbolAssignment : BaseCommand {
|
||||
SymbolAssignment(StringRef Name, Expr E)
|
||||
: BaseCommand(AssignmentKind), Name(Name), Expression(E) {}
|
||||
SymbolAssignment(StringRef Name, Expr E, bool IsAbsolute)
|
||||
: BaseCommand(AssignmentKind), Name(Name), Expression(E),
|
||||
IsAbsolute(IsAbsolute) {}
|
||||
static bool classof(const BaseCommand *C);
|
||||
|
||||
// The LHS of an expression. Name is either a symbol name or ".".
|
||||
|
@ -68,6 +69,7 @@ struct SymbolAssignment : BaseCommand {
|
|||
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
|
||||
bool Provide = false;
|
||||
bool Hidden = false;
|
||||
bool IsAbsolute;
|
||||
InputSectionData *GoesAfter = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
# RUN: *(.foo) \
|
||||
# RUN: end_foo = .; \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
|
||||
# RUN: PROVIDE(_end_sec_abs = ABSOLUTE(.)); \
|
||||
# RUN: size_foo_1 = SIZEOF(.foo); \
|
||||
# RUN: size_foo_1_abs = ABSOLUTE(SIZEOF(.foo)); \
|
||||
# RUN: . = ALIGN(0x1000); \
|
||||
# RUN: begin_bar = .; \
|
||||
# RUN: *(.bar) \
|
||||
|
@ -19,10 +21,10 @@
|
|||
# RUN: size_foo_3 = SIZEOF(.foo); \
|
||||
# RUN: .eh_frame_hdr : { \
|
||||
# RUN: __eh_frame_hdr_start = .; \
|
||||
# RUN: __eh_frame_hdr_start2 = ALIGN(0x10); \
|
||||
# RUN: __eh_frame_hdr_start2 = ABSOLUTE(ALIGN(0x10)); \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: __eh_frame_hdr_end = .; \
|
||||
# RUN: __eh_frame_hdr_end2 = ALIGN(0x10); } \
|
||||
# RUN: __eh_frame_hdr_end2 = ABSOLUTE(ALIGN(0x10)); } \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
|
||||
|
@ -34,7 +36,7 @@
|
|||
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
|
||||
# RUN: __eh_frame_hdr_start = .; \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: __eh_frame_hdr_end = .; \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
|
||||
# RUN: *(.eh_frame_hdr) } \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
|
||||
# RUN: }" > %t.script
|
||||
|
@ -46,23 +48,26 @@
|
|||
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); } \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
|
||||
|
||||
# SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec
|
||||
# SIMPLE: 0000000000000158 .foo 00000000 _begin_sec
|
||||
# SIMPLE-NEXT: 0000000000000160 *ABS* 00000000 _end_sec_abs
|
||||
# SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo
|
||||
# SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo
|
||||
# SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1
|
||||
# SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1_abs
|
||||
# SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar
|
||||
# SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar
|
||||
# SIMPLE-NEXT: 0000000000000eac .foo 00000000 size_foo_2
|
||||
# SIMPLE-NEXT: 0000000000000eac *ABS* 00000000 size_foo_3
|
||||
# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start
|
||||
# SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2
|
||||
# SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2
|
||||
# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end
|
||||
# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2
|
||||
# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2
|
||||
# ERROR: section '.eh_frame_hdr' supports only start and end symbols
|
||||
|
||||
.global _start
|
||||
|
@ -80,4 +85,4 @@ _start:
|
|||
nop
|
||||
.cfi_endproc
|
||||
|
||||
.global _begin_sec, _end_sec
|
||||
.global _begin_sec, _end_sec, _end_sec_abs
|
||||
|
|
Loading…
Reference in New Issue