[ELF] - Implemented --defsym option.

gnu ld description of option is:

--defsym=symbol=expression
Create a global symbol in the output file, containing the absolute address given 
by expression. You may use this option as many times as necessary to define multiple
symbols in the command line. A limited form of arithmetic is supported for the 
expression in this context: you may give a hexadecimal constant or the name of an
existing symbol, or use "+" and "-" to add or subtract hexadecimal constants or 
symbols. If you need more elaborate expressions, consider using the linker command
language from a script. Note: there should be no white space between symbol, 
the equals sign ("="), and expression.

In compare with D32082, this patch does not support math expressions and absolute
symbols. It implemented via code similar to --wrap. That covers 1 of 3 possible
--defsym cases.

Differential revision: https://reviews.llvm.org/D32171

llvm-svn: 301391
This commit is contained in:
George Rimar 2017-04-26 10:40:02 +00:00
parent c3c6723ab5
commit 9703ad2221
5 changed files with 79 additions and 0 deletions

View File

@ -880,6 +880,21 @@ static uint64_t getImageBase(opt::InputArgList &Args) {
return V;
}
// Parses --defsym=alias option.
static std::vector<std::pair<StringRef, StringRef>>
getDefsym(opt::InputArgList &Args) {
std::vector<std::pair<StringRef, StringRef>> Ret;
for (auto *Arg : Args.filtered(OPT_defsym)) {
StringRef From;
StringRef To;
std::tie(From, To) = StringRef(Arg->getValue()).split('=');
if (!isValidCIdentifier(To))
error("--defsym: symbol name expected, but got " + To);
Ret.push_back({From, To});
}
return Ret;
}
// Do actual linking. Note that when this function is called,
// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
@ -945,6 +960,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_wrap))
Symtab.wrap(Arg->getValue());
// Handle --defsym=sym=alias option.
for (std::pair<StringRef, StringRef> &Def : getDefsym(Args))
Symtab.alias(Def.first, Def.second);
// Now that we have a complete list of input files.
// Beyond this point, no new files are added.
// Aggregate all input sections into one place.

View File

@ -25,6 +25,8 @@ def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">;
def compress_debug_sections : J<"compress-debug-sections=">,
HelpText<"Compress DWARF debug sections">;
def defsym: J<"defsym=">, HelpText<"Define a symbol alias">;
def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
HelpText<"Add a directory to the library search path">;

View File

@ -168,6 +168,19 @@ template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
}
// Creates alias for symbol. Used to implement --defsym=ALIAS=SYM.
template <class ELFT>
void SymbolTable<ELFT>::alias(StringRef Alias, StringRef Name) {
SymbolBody *B = find(Name);
if (!B) {
error("-defsym: undefined symbol: " + Name);
return;
}
Symbol *Sym = B->symbol();
Symbol *AliasSym = addUndefined(Alias);
memcpy(AliasSym->Body.buffer, Sym->Body.buffer, sizeof(AliasSym->Body));
}
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
if (VA == STV_DEFAULT)
return VB;

View File

@ -86,6 +86,7 @@ public:
void trace(StringRef Name);
void wrap(StringRef Name);
void alias(StringRef Alias, StringRef Name);
private:
std::vector<SymbolBody *> findByVersion(SymbolVersion Ver);

44
lld/test/ELF/defsym.s Normal file
View File

@ -0,0 +1,44 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: ld.lld -o %t %t.o --defsym=foo2=foo1
# RUN: llvm-readobj -t -s %t | FileCheck %s
# RUN: llvm-objdump -d -print-imm-hex %t | FileCheck %s --check-prefix=USE
## In compare with GNU linkers, symbol defined with --defsym does
## not get aliased name in symbol table:
# CHECK: Symbol {
# CHECK: Name: foo1
# CHECK-NEXT: Value: 0x123
# CHECK-NEXT: Size:
# CHECK-NEXT: Binding: Global
# CHECK-NEXT: Type:
# CHECK-NEXT: Other:
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: foo1
# CHECK-NEXT: Value: 0x123
# CHECK-NEXT: Size:
# CHECK-NEXT: Binding: Global
# CHECK-NEXT: Type:
# CHECK-NEXT: Other:
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }
## Check we can use foo2 and it that it is an alias for foo1.
# USE: Disassembly of section .text:
# USE-NEXT: _start:
# USE-NEXT: movl $0x123, %edx
# RUN: not ld.lld -o %t %t.o --defsym=foo2=1 2>&1 | FileCheck %s -check-prefix=ERR1
# ERR1: error: --defsym: symbol name expected, but got 1
# RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR2
# ERR2: error: -defsym: undefined symbol: und
.globl foo1
foo1 = 0x123
.global _start
_start:
movl $foo2, %edx