forked from OSchip/llvm-project
[ELF] Allow defined symbols to be assigned from linker script
This patch allows for linker scripts to assign a new value to a symbol that is already defined (either in an object file or the linker script itself). llvm-svn: 291459
This commit is contained in:
parent
fad02411e0
commit
8f1f3c40f6
|
@ -56,29 +56,30 @@ using namespace lld::elf;
|
|||
LinkerScriptBase *elf::ScriptBase;
|
||||
ScriptConfiguration *elf::ScriptConfig;
|
||||
|
||||
template <class ELFT> static void addRegular(SymbolAssignment *Cmd) {
|
||||
template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) {
|
||||
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
Symbol *Sym = Symtab<ELFT>::X->addRegular(Cmd->Name, Visibility, STT_NOTYPE,
|
||||
0, 0, STB_GLOBAL, nullptr, nullptr);
|
||||
Cmd->Sym = Sym->body();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addUndefined(
|
||||
Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
|
||||
/*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
|
||||
// If we have no SECTIONS then we don't have '.' and don't call
|
||||
// assignAddresses(). We calculate symbol value immediately in this case.
|
||||
if (!ScriptConfig->HasSections)
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(0);
|
||||
replaceBody<DefinedRegular<ELFT>>(Sym, Cmd->Name, /*IsLocal=*/false,
|
||||
Visibility, STT_NOTYPE, 0, 0, nullptr,
|
||||
nullptr);
|
||||
return Sym->body();
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
|
||||
// If we have SECTIONS block then output sections haven't been created yet.
|
||||
template <class ELFT> static SymbolBody *addSynthetic(SymbolAssignment *Cmd) {
|
||||
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
const OutputSectionBase *Sec =
|
||||
ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addSynthetic(
|
||||
Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
|
||||
Cmd->Sym = Sym->body();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addUndefined(
|
||||
Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
|
||||
/*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
|
||||
// If we already know section then we can calculate symbol value immediately.
|
||||
if (Sec)
|
||||
cast<DefinedSynthetic>(Cmd->Sym)->Value = Cmd->Expression(0) - Sec->Addr;
|
||||
replaceBody<DefinedSynthetic>(Sym, Cmd->Name, 0, Sec);
|
||||
return Sym->body();
|
||||
}
|
||||
|
||||
static bool isUnderSysroot(StringRef Path) {
|
||||
|
@ -90,21 +91,39 @@ static bool isUnderSysroot(StringRef Path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
|
||||
if (Cmd->Expression.IsAbsolute())
|
||||
addRegular<ELFT>(Cmd);
|
||||
else
|
||||
addSynthetic<ELFT>(Cmd);
|
||||
template <class ELFT> static void assignSymbol(SymbolAssignment *Cmd) {
|
||||
// If there are sections, then let the value be assigned later in
|
||||
// `assignAddresses`.
|
||||
if (ScriptConfig->HasSections)
|
||||
return;
|
||||
|
||||
uint64_t Value = Cmd->Expression(0);
|
||||
if (Cmd->Expression.IsAbsolute()) {
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Value;
|
||||
} else {
|
||||
const OutputSectionBase *Sec = Cmd->Expression.Section();
|
||||
if (Sec)
|
||||
cast<DefinedSynthetic>(Cmd->Sym)->Value = Value - Sec->Addr;
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
|
||||
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
|
||||
if (Cmd->Name == ".")
|
||||
return false;
|
||||
if (!Cmd->Provide)
|
||||
return true;
|
||||
return;
|
||||
|
||||
// If a symbol was in PROVIDE(), we need to define it only when
|
||||
// it is a referenced undefined symbol.
|
||||
SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
|
||||
return B && B->isUndefined();
|
||||
if (Cmd->Provide && (!B || B->isDefined()))
|
||||
return;
|
||||
|
||||
// Otherwise, create a new symbol if one does not exist or an
|
||||
// undefined one does exist.
|
||||
if (Cmd->Expression.IsAbsolute())
|
||||
Cmd->Sym = addRegular<ELFT>(Cmd);
|
||||
else
|
||||
Cmd->Sym = addSynthetic<ELFT>(Cmd);
|
||||
assignSymbol<ELFT>(Cmd);
|
||||
}
|
||||
|
||||
bool SymbolAssignment::classof(const BaseCommand *C) {
|
||||
|
@ -283,8 +302,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
|
||||
// Handle symbol assignments outside of any output section.
|
||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
|
||||
if (shouldDefine<ELFT>(Cmd))
|
||||
addSymbol<ELFT>(Cmd);
|
||||
addSymbol<ELFT>(Cmd);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -326,8 +344,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
|||
// ".foo : { ...; bar = .; }". Handle them.
|
||||
for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
|
||||
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
|
||||
if (shouldDefine<ELFT>(OutCmd))
|
||||
addSymbol<ELFT>(OutCmd);
|
||||
addSymbol<ELFT>(OutCmd);
|
||||
|
||||
// Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
|
||||
// is given, input sections are aligned to that value, whether the
|
||||
|
|
|
@ -13,14 +13,20 @@
|
|||
# RUN: symbol9 = - 4; \
|
||||
# RUN: symbol10 = 0xfedcba9876543210; \
|
||||
# RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \
|
||||
# RUN: symbol12 = 0x1234; \
|
||||
# RUN: symbol12 += 1; \
|
||||
# RUN: bar = 0x5678; \
|
||||
# RUN: baz = 0x9abc; \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
|
||||
|
||||
# CHECK: SYMBOL TABLE:
|
||||
# CHECK-NEXT: 0000000000000000 *UND* 00000000
|
||||
# CHECK-NEXT: .text 00000000 _start
|
||||
# CHECK-NEXT: .text 00000000 foo
|
||||
# CHECK-NEXT: 0000000000000000 .text 00000000 _start
|
||||
# CHECK-NEXT: 0000000000005678 *ABS* 00000000 bar
|
||||
# CHECK-NEXT: 0000000000009abc *ABS* 00000000 baz
|
||||
# CHECK-NEXT: 0000000000000001 .text 00000000 foo
|
||||
# CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol
|
||||
# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2
|
||||
# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3
|
||||
|
@ -32,6 +38,7 @@
|
|||
# CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9
|
||||
# CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10
|
||||
# CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11
|
||||
# CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: symbol2 = symbol; \
|
||||
|
@ -46,3 +53,9 @@ _start:
|
|||
|
||||
.global foo
|
||||
foo:
|
||||
nop
|
||||
|
||||
.global bar
|
||||
bar = 0x1234
|
||||
|
||||
.comm baz,8,8
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# Check that the linker use a value of _gp symbol defined
|
||||
# in a linker script to calculate GOT relocations.
|
||||
|
||||
# FIXME: This test is xfailed because it depends on D27276 patch
|
||||
# that enables absolute symbols redefinition by a linker's script.
|
||||
# FIXME: This test is xfailed because there is currently a bug
|
||||
# that causes symbols defined by linker scripts to be put in the
|
||||
# wrong sections. In particular, `_gp = . + 0x100` ends up in
|
||||
# `.text` when it should be in `*ABS*`.
|
||||
# XFAIL: *
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
|
||||
|
|
Loading…
Reference in New Issue