Skip to content

Commit db741e7

Browse files
committedSep 7, 2016
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
1 parent f333de3 commit db741e7

File tree

3 files changed

+62
-30
lines changed

3 files changed

+62
-30
lines changed
 

Diff for: ‎lld/ELF/LinkerScript.cpp

+47-22
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
5656
Cmd->Sym = Sym->body();
5757
}
5858

59+
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
60+
if (Cmd->IsAbsolute)
61+
addRegular<ELFT>(Cmd);
62+
else
63+
addSynthetic<ELFT>(Cmd);
64+
}
5965
// If a symbol was in PROVIDE(), we need to define it only when
6066
// it is an undefined symbol.
6167
template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
@@ -184,7 +190,7 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
184190
for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
185191
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
186192
if (shouldDefine<ELFT>(OutCmd))
187-
addSynthetic<ELFT>(OutCmd);
193+
addSymbol<ELFT>(OutCmd);
188194
OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
189195
continue;
190196
}
@@ -267,6 +273,26 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
267273
}
268274
}
269275

276+
// Sets value of a section-defined symbol. Two kinds of
277+
// symbols are processed: synthetic symbols, whose value
278+
// is an offset from beginning of section and regular
279+
// symbols whose value is absolute.
280+
template <class ELFT>
281+
static void assignSectionSymbol(SymbolAssignment *Cmd,
282+
OutputSectionBase<ELFT> *Sec,
283+
typename ELFT::uint Off) {
284+
if (!Cmd->Sym)
285+
return;
286+
287+
if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
288+
Body->Section = Sec;
289+
Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
290+
return;
291+
}
292+
auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
293+
Body->Value = Cmd->Expression(Sec->getVA() + Off);
294+
}
295+
270296
// Linker script may define start and end symbols for special section types,
271297
// like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
272298
// of regular input input sections, therefore our way of defining symbols for
@@ -280,12 +306,7 @@ void addStartEndSymbols(OutputSectionCommand *Cmd,
280306

281307
for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
282308
if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
283-
if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
284-
Sym->Section = Sec;
285-
Sym->Value =
286-
AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
287-
Sec->getVA();
288-
}
309+
assignSectionSymbol<ELFT>(AssignCmd, Sec, Start ? 0 : Sec->getSize());
289310
} else {
290311
if (!Start && isa<SymbolAssignment>(PrevCmd))
291312
error("section '" + Sec->getName() +
@@ -322,19 +343,13 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) {
322343
if (D != AssignCmd->GoesAfter)
323344
break;
324345

325-
uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
326346
if (AssignCmd->Name == ".") {
327347
// Update to location counter means update to section size.
328-
Off = Value;
348+
Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
329349
Sec->setSize(Off);
330350
continue;
331351
}
332-
333-
if (DefinedSynthetic<ELFT> *Sym =
334-
cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
335-
Sym->Section = OutSec;
336-
Sym->Value = Value;
337-
}
352+
assignSectionSymbol<ELFT>(AssignCmd, Sec, Off);
338353
}
339354
};
340355

@@ -631,7 +646,7 @@ class elf::ScriptParser : public ScriptParserBase {
631646
unsigned readPhdrType();
632647
SortKind readSortKind();
633648
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
634-
SymbolAssignment *readProvideOrAssignment(StringRef Tok);
649+
SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
635650
void readSort();
636651
Expr readAssert();
637652

@@ -710,7 +725,7 @@ void ScriptParser::readLinkerScript() {
710725
readSections();
711726
} else if (Tok == "VERSION") {
712727
readVersion();
713-
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
728+
} else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) {
714729
if (Opt.HasContents)
715730
Opt.Commands.emplace_back(Cmd);
716731
else
@@ -872,7 +887,7 @@ void ScriptParser::readSections() {
872887
expect("{");
873888
while (!Error && !skip("}")) {
874889
StringRef Tok = next();
875-
BaseCommand *Cmd = readProvideOrAssignment(Tok);
890+
BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
876891
if (!Cmd) {
877892
if (Tok == "ASSERT")
878893
Cmd = new AssertCommand(readAssert());
@@ -1020,7 +1035,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) {
10201035

10211036
while (!Error && !skip("}")) {
10221037
StringRef Tok = next();
1023-
if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok))
1038+
if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok, false))
10241039
Cmd->Commands.emplace_back(Assignment);
10251040
else if (Tok == "FILL")
10261041
Cmd->Filler = readFill();
@@ -1063,7 +1078,8 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) {
10631078
return Cmd;
10641079
}
10651080

1066-
SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
1081+
SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
1082+
bool MakeAbsolute) {
10671083
SymbolAssignment *Cmd = nullptr;
10681084
if (peek() == "=" || peek() == "+=") {
10691085
Cmd = readAssignment(Tok);
@@ -1075,6 +1091,8 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
10751091
} else if (Tok == "PROVIDE_HIDDEN") {
10761092
Cmd = readProvideHidden(true, true);
10771093
}
1094+
if (Cmd && MakeAbsolute)
1095+
Cmd->IsAbsolute = true;
10781096
return Cmd;
10791097
}
10801098

@@ -1153,11 +1171,18 @@ static uint64_t getHeaderSize() {
11531171

11541172
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
11551173
StringRef Op = next();
1174+
bool IsAbsolute = false;
1175+
Expr E;
11561176
assert(Op == "=" || Op == "+=");
1157-
Expr E = readExpr();
1177+
if (skip("ABSOLUTE")) {
1178+
E = readParenExpr();
1179+
IsAbsolute = true;
1180+
} else {
1181+
E = readExpr();
1182+
}
11581183
if (Op == "+=")
11591184
E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
1160-
return new SymbolAssignment(Name, E);
1185+
return new SymbolAssignment(Name, E, IsAbsolute);
11611186
}
11621187

11631188
// This is an operator-precedence parser to parse a linker

Diff for: ‎lld/ELF/LinkerScript.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ struct BaseCommand {
5454
};
5555

5656
struct SymbolAssignment : BaseCommand {
57-
SymbolAssignment(StringRef Name, Expr E)
58-
: BaseCommand(AssignmentKind), Name(Name), Expression(E) {}
57+
SymbolAssignment(StringRef Name, Expr E, bool IsAbsolute)
58+
: BaseCommand(AssignmentKind), Name(Name), Expression(E),
59+
IsAbsolute(IsAbsolute) {}
5960
static bool classof(const BaseCommand *C);
6061

6162
// The LHS of an expression. Name is either a symbol name or ".".
@@ -68,6 +69,7 @@ struct SymbolAssignment : BaseCommand {
6869
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
6970
bool Provide = false;
7071
bool Hidden = false;
72+
bool IsAbsolute;
7173
InputSectionData *GoesAfter = nullptr;
7274
};
7375

Diff for: ‎lld/test/ELF/linkerscript/symbols-synthetic.s

+11-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
# RUN: *(.foo) \
1111
# RUN: end_foo = .; \
1212
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
13+
# RUN: PROVIDE(_end_sec_abs = ABSOLUTE(.)); \
1314
# RUN: size_foo_1 = SIZEOF(.foo); \
15+
# RUN: size_foo_1_abs = ABSOLUTE(SIZEOF(.foo)); \
1416
# RUN: . = ALIGN(0x1000); \
1517
# RUN: begin_bar = .; \
1618
# RUN: *(.bar) \
@@ -19,10 +21,10 @@
1921
# RUN: size_foo_3 = SIZEOF(.foo); \
2022
# RUN: .eh_frame_hdr : { \
2123
# RUN: __eh_frame_hdr_start = .; \
22-
# RUN: __eh_frame_hdr_start2 = ALIGN(0x10); \
24+
# RUN: __eh_frame_hdr_start2 = ABSOLUTE(ALIGN(0x10)); \
2325
# RUN: *(.eh_frame_hdr) \
2426
# RUN: __eh_frame_hdr_end = .; \
25-
# RUN: __eh_frame_hdr_end2 = ALIGN(0x10); } \
27+
# RUN: __eh_frame_hdr_end2 = ABSOLUTE(ALIGN(0x10)); } \
2628
# RUN: }" > %t.script
2729
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
2830
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
@@ -34,7 +36,7 @@
3436
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
3537
# RUN: __eh_frame_hdr_start = .; \
3638
# RUN: *(.eh_frame_hdr) \
37-
# RUN: __eh_frame_hdr_end = .; \
39+
# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
3840
# RUN: *(.eh_frame_hdr) } \
3941
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
4042
# RUN: }" > %t.script
@@ -46,23 +48,26 @@
4648
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
4749
# RUN: *(.eh_frame_hdr) \
4850
# RUN: *(.eh_frame_hdr) \
51+
# RUN: PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
4952
# RUN: PROVIDE_HIDDEN(_end_sec = .); } \
5053
# RUN: }" > %t.script
5154
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
5255

5356
# SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec
5457
# SIMPLE: 0000000000000158 .foo 00000000 _begin_sec
58+
# SIMPLE-NEXT: 0000000000000160 *ABS* 00000000 _end_sec_abs
5559
# SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo
5660
# SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo
5761
# SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1
62+
# SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1_abs
5863
# SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar
5964
# SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar
6065
# SIMPLE-NEXT: 0000000000000eac .foo 00000000 size_foo_2
6166
# SIMPLE-NEXT: 0000000000000eac *ABS* 00000000 size_foo_3
6267
# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start
63-
# SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2
68+
# SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2
6469
# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end
65-
# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2
70+
# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2
6671
# ERROR: section '.eh_frame_hdr' supports only start and end symbols
6772

6873
.global _start
@@ -80,4 +85,4 @@ _start:
8085
nop
8186
.cfi_endproc
8287

83-
.global _begin_sec, _end_sec
88+
.global _begin_sec, _end_sec, _end_sec_abs

0 commit comments

Comments
 (0)
Please sign in to comment.