[lld] r301391 - [ELF] - Implemented --defsym option.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 26 03:40:02 PDT 2017


Author: grimar
Date: Wed Apr 26 05:40:02 2017
New Revision: 301391

URL: http://llvm.org/viewvc/llvm-project?rev=301391&view=rev
Log:
[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

Added:
    lld/trunk/test/ELF/defsym.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=301391&r1=301390&r2=301391&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Apr 26 05:40:02 2017
@@ -880,6 +880,21 @@ static uint64_t getImageBase(opt::InputA
   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:
   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.

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=301391&r1=301390&r2=301391&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Apr 26 05:40:02 2017
@@ -25,6 +25,8 @@ def build_id_eq: J<"build-id=">, HelpTex
 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">;
 

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=301391&r1=301390&r2=301391&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Apr 26 05:40:02 2017
@@ -168,6 +168,19 @@ template <class ELFT> void SymbolTable<E
   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;

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=301391&r1=301390&r2=301391&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Wed Apr 26 05:40:02 2017
@@ -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);

Added: lld/trunk/test/ELF/defsym.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/defsym.s?rev=301391&view=auto
==============================================================================
--- lld/trunk/test/ELF/defsym.s (added)
+++ lld/trunk/test/ELF/defsym.s Wed Apr 26 05:40:02 2017
@@ -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




More information about the llvm-commits mailing list