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) {
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;
}
}
}
+// 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
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() +
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);
}
};
unsigned readPhdrType();
SortKind readSortKind();
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
- SymbolAssignment *readProvideOrAssignment(StringRef Tok);
+ SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
void readSort();
Expr readAssert();
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
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());
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();
return Cmd;
}
-SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
+SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
+ bool MakeAbsolute) {
SymbolAssignment *Cmd = nullptr;
if (peek() == "=" || peek() == "+=") {
Cmd = readAssignment(Tok);
} else if (Tok == "PROVIDE_HIDDEN") {
Cmd = readProvideHidden(true, true);
}
+ if (Cmd && MakeAbsolute)
+ Cmd->IsAbsolute = true;
return Cmd;
}
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
# 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) \
# 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
# 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
# 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
nop
.cfi_endproc
-.global _begin_sec, _end_sec
+.global _begin_sec, _end_sec, _end_sec_abs