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) {
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.
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">;
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;
void trace(StringRef Name);
void wrap(StringRef Name);
+ void alias(StringRef Alias, StringRef Name);
private:
std::vector<SymbolBody *> findByVersion(SymbolVersion Ver);
--- /dev/null
+# 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