forked from OSchip/llvm-project
The expr '.' is not absolute.
With this patch we keep track of the fact that . is a position in the file and therefore not absolute. This allow us to compute relative relocations that involve symbol that are defined in linker scripts with '.'. This fixes https://llvm.org/bugs/show_bug.cgi?id=30406 There is still more work to track absoluteness over the various expressions, but this should unblock linking the EFI bootloader. llvm-svn: 285641
This commit is contained in:
parent
75f9d3ac7e
commit
b0de56b59d
|
@ -299,7 +299,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
const std::unique_ptr<BaseCommand> &Base1 = *Iter;
|
||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
|
||||
if (shouldDefine<ELFT>(Cmd))
|
||||
addRegular<ELFT>(Cmd);
|
||||
addSymbol<ELFT>(Cmd);
|
||||
continue;
|
||||
}
|
||||
if (auto *Cmd = dyn_cast<AssertCommand>(Base1.get())) {
|
||||
|
@ -621,7 +621,8 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
|
|||
if (Cmd->Name == ".") {
|
||||
Dot = Cmd->Expression(Dot);
|
||||
} else if (Cmd->Sym) {
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(Dot);
|
||||
assignSectionSymbol(Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0],
|
||||
Dot);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1186,7 +1187,7 @@ void ScriptParser::readSections() {
|
|||
expect("{");
|
||||
while (!Error && !consume("}")) {
|
||||
StringRef Tok = next();
|
||||
BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
|
||||
BaseCommand *Cmd = readProvideOrAssignment(Tok, false);
|
||||
if (!Cmd) {
|
||||
if (Tok == "ASSERT")
|
||||
Cmd = new AssertCommand(readAssert());
|
||||
|
@ -1636,7 +1637,7 @@ Expr ScriptParser::readPrimary() {
|
|||
}
|
||||
if (Tok == "CONSTANT") {
|
||||
StringRef Name = readParenLiteral();
|
||||
return {[=](uint64_t Dot) { return getConstant(Name); }, true};
|
||||
return [=](uint64_t Dot) { return getConstant(Name); };
|
||||
}
|
||||
if (Tok == "DEFINED") {
|
||||
expect("(");
|
||||
|
@ -1679,23 +1680,20 @@ Expr ScriptParser::readPrimary() {
|
|||
}
|
||||
if (Tok == "SIZEOF") {
|
||||
StringRef Name = readParenLiteral();
|
||||
return {
|
||||
[=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); },
|
||||
true};
|
||||
return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); };
|
||||
}
|
||||
if (Tok == "ALIGNOF") {
|
||||
StringRef Name = readParenLiteral();
|
||||
return {
|
||||
[=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); },
|
||||
true};
|
||||
return
|
||||
[=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); };
|
||||
}
|
||||
if (Tok == "SIZEOF_HEADERS")
|
||||
return {[=](uint64_t Dot) { return ScriptBase->getHeaderSize(); }, true};
|
||||
return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); };
|
||||
|
||||
// Tok is a literal number.
|
||||
uint64_t V;
|
||||
if (readInteger(Tok, V))
|
||||
return {[=](uint64_t Dot) { return V; }, true};
|
||||
return [=](uint64_t Dot) { return V; };
|
||||
|
||||
// Tok is a symbol name.
|
||||
if (Tok != "." && !isValidCIdentifier(Tok))
|
||||
|
|
|
@ -43,13 +43,9 @@ struct Expr {
|
|||
uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
|
||||
operator bool() const { return (bool)Val; }
|
||||
|
||||
template <typename T>
|
||||
Expr(T Val, std::function<bool()> IsAbsolute)
|
||||
Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute)
|
||||
: Val(Val), IsAbsolute(IsAbsolute) {}
|
||||
template <typename T> Expr(T Val, bool IsAbsolute) : Val(Val) {
|
||||
this->IsAbsolute = [=]() { return IsAbsolute; };
|
||||
}
|
||||
template <typename T> Expr(T V) : Expr(V, false) {}
|
||||
template <typename T> Expr(T V) : Expr(V, []() { return true; }) {}
|
||||
Expr() : Expr(nullptr) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
|
||||
# RUN: echo "SECTIONS { .text : { *(.text) } \
|
||||
# RUN: foo = .; \
|
||||
# RUN: .bar : { *(.bar) } }" > %t1.script
|
||||
# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared
|
||||
# RUN: llvm-readobj -t -s -section-data %t1 | FileCheck %s
|
||||
|
||||
.hidden foo
|
||||
.long foo - .
|
||||
|
||||
.section .bar, "a"
|
||||
.long 0
|
||||
|
||||
# The symbol foo is defined as a position in the file. This means that it is
|
||||
# not absolute and it is possible to compute the distance from foo to some other
|
||||
# position in the file. The symbol is not really in any output section, but
|
||||
# ELF has no magic constant for not absolute, but not in any section.
|
||||
# Fortunately the value of a symbol in a non relocatable file is a virtual
|
||||
# address, so the section can be arbitrary.
|
||||
|
||||
# CHECK: Section {
|
||||
# CHECK: Index:
|
||||
# CHECK: Name: .text
|
||||
# CHECK-NEXT: Type: SHT_PROGBITS
|
||||
# CHECK-NEXT: Flags [
|
||||
# CHECK-NEXT: SHF_ALLOC
|
||||
# CHECK-NEXT: SHF_EXECINSTR
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Address: 0x0
|
||||
# CHECK-NEXT: Offset:
|
||||
# CHECK-NEXT: Size: 4
|
||||
# CHECK-NEXT: Link:
|
||||
# CHECK-NEXT: Info:
|
||||
# CHECK-NEXT: AddressAlignment:
|
||||
# CHECK-NEXT: EntrySize:
|
||||
# CHECK-NEXT: SectionData (
|
||||
# CHECK-NEXT: 0000: 04000000 |
|
||||
# CHECK-NEXT: )
|
||||
# CHECK-NEXT: }
|
||||
|
||||
# CHECK: Symbol {
|
||||
# CHECK: Name: foo
|
||||
# CHECK-NEXT: Value: 0x4
|
||||
# CHECK-NEXT: Size: 0
|
||||
# CHECK-NEXT: Binding: Local
|
||||
# CHECK-NEXT: Type: None
|
||||
# CHECK-NEXT: Other [
|
||||
# CHECK-NEXT: STV_HIDDEN
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Section: .text
|
||||
# CHECK-NEXT: }
|
|
@ -4,7 +4,7 @@
|
|||
# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : {*(.text.*)} end = .;}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
|
||||
# CHECK: 00000000000000e9 *ABS* 00000000 end
|
||||
# CHECK: 00000000000000e9 .text 00000000 end
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
|
||||
# SIMPLE: *ABS* 00000000 text_end
|
||||
# SIMPLE: .text 00000000 text_end
|
||||
|
||||
# The symbol is not referenced. Don't provide it.
|
||||
# RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script
|
||||
|
|
Loading…
Reference in New Issue