Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -877,6 +877,37 @@ return V; } +// Function used to handle --defsym= option. It can be one of 3: +// 1) --defsym=name=alias +// 2) --defsym=name=integer +// 3) --defsym=name=expression +// We support first two. Alias implemented very similar to --wrap option, +// second form simply creates an absolute symbol. We do not support +// expressions with math for simplicity. +template static void handleDefsym(opt::InputArgList &Args) { + std::vector> Ret; + for (auto *Arg : Args.filtered(OPT_defsym)) { + StringRef Name; + StringRef Expr; + std::tie(Name, Expr) = StringRef(Arg->getValue()).split('='); + + if (isValidCIdentifier(Expr)) { + Symtab::X->alias(Name, Expr); + continue; + } + + uint64_t Val; + if (!Expr.getAsInteger(0, Val)) { + DefinedRegular *DR = + Symtab::X->addAbsolute(Name, STV_DEFAULT, STB_GLOBAL); + DR->Value = Val; + continue; + } + + error("--defsym=: number expected, but got " + Expr); + } +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template void LinkerDriver::link(opt::InputArgList &Args) { @@ -942,6 +973,9 @@ for (auto *Arg : Args.filtered(OPT_wrap)) Symtab.wrap(Arg->getValue()); + // Handle --defsym=sym=expr option. + handleDefsym(Args); + // 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. Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -25,6 +25,8 @@ def compress_debug_sections : J<"compress-debug-sections=">, HelpText<"Compress DWARF debug sections">; +def defsym: J<"defsym=">, HelpText<"Create a global symbol alias or absolute symbol">; + def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"">, HelpText<"Add a directory to the library search path">; Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -86,6 +86,7 @@ void trace(StringRef Name); void wrap(StringRef Name); + void alias(StringRef Alias, StringRef Name); private: std::vector findByVersion(SymbolVersion Ver); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -168,6 +168,19 @@ memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); } +// Creates alias for symbol. Used to implement --defsym=SYM=ALIAS +template +void SymbolTable::alias(StringRef Alias, StringRef Name) { + SymbolBody *B = find(Name); + if (!B) { + error("undefined symbol '" + Name + "' used in --defsym= expression"); + 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; Index: test/ELF/defsym.s =================================================================== --- test/ELF/defsym.s +++ test/ELF/defsym.s @@ -0,0 +1,41 @@ +# 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 --defsym=foo3=0x456 +# RUN: llvm-readobj -t -s %t | FileCheck %s + +# CHECK: Symbol { +# CHECK: Name: foo1 +# CHECK-NEXT: Value: [[ADDR:.*]] +# 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: [[ADDR]] +# 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: foo3 +# CHECK-NEXT: Value: 0x456 +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: +# CHECK-NEXT: Other: +# CHECK-NEXT: Section: Absolute +# CHECK-NEXT: } + +# RUN: not ld.lld -o %t %t.o --defsym=foo2=foo1+1 2>&1 | FileCheck %s -check-prefix=ERR1 +# ERR1: error: --defsym=: number expected, but got foo1+1 + +# RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR2 +# ERR2: error: undefined symbol 'und' used in --defsym= expression + +.globl foo1 + foo1 = 0x123