[ELF] Support expressions with -defsym option
authorPetr Hosek <phosek@chromium.org>
Sat, 4 Nov 2017 02:03:58 +0000 (02:03 +0000)
committerPetr Hosek <phosek@chromium.org>
Sat, 4 Nov 2017 02:03:58 +0000 (02:03 +0000)
Fixes PR34948.

Differential Revision: https://reviews.llvm.org/D39511

llvm-svn: 317396

lld/ELF/Driver.cpp
lld/ELF/ScriptParser.cpp
lld/ELF/ScriptParser.h
lld/test/ELF/defsym.s

index 23e4116..c4d3bf2 100644 (file)
@@ -946,21 +946,6 @@ static Optional<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;
-}
-
 // Parses `--exclude-libs=lib,lib,...`.
 // The library names may be delimited by commas or colons.
 static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {
@@ -1054,6 +1039,14 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
   for (InputFile *F : Files)
     Symtab->addFile<ELFT>(F);
 
+  // Process -defsym option.
+  for (auto *Arg : Args.filtered(OPT_defsym)) {
+    StringRef From;
+    StringRef To;
+    std::tie(From, To) = StringRef(Arg->getValue()).split('=');
+    readDefsym(From, MemoryBufferRef(To, "-defsym"));
+  }
+
   // Now that we have every file, we can decide if we will need a
   // dynamic symbol table.
   // We need one if we were asked to export dynamic symbols or if we are
@@ -1095,10 +1088,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
   for (auto *Arg : Args.filtered(OPT_wrap))
     Symtab->addSymbolWrap<ELFT>(Arg->getValue());
 
-  // Create alias symbols for -defsym option.
-  for (std::pair<StringRef, StringRef> &Def : getDefsym(Args))
-    Symtab->addSymbolAlias<ELFT>(Def.first, Def.second);
-
   Symtab->addCombinedLTOObject<ELFT>();
   if (errorCount())
     return;
index af9bf19..8dd2366 100644 (file)
@@ -53,6 +53,7 @@ public:
   void readLinkerScript();
   void readVersionScript();
   void readDynamicList();
+  void readDefsym(StringRef Name);
 
 private:
   void addFile(StringRef Path);
@@ -269,6 +270,14 @@ void ScriptParser::readLinkerScript() {
   }
 }
 
+void ScriptParser::readDefsym(StringRef Name) {
+  Expr E = readExpr();
+  if (!atEOF())
+    setError("EOF expected, but got " + next());
+  SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation());
+  Script->SectionCommands.push_back(Cmd);
+}
+
 void ScriptParser::addFile(StringRef S) {
   if (IsUnderSysroot && S.startswith("/")) {
     SmallString<128> PathData;
@@ -1326,3 +1335,7 @@ void elf::readVersionScript(MemoryBufferRef MB) {
 void elf::readDynamicList(MemoryBufferRef MB) {
   ScriptParser(MB).readDynamicList();
 }
+
+void elf::readDefsym(StringRef Name, MemoryBufferRef MB) {
+  ScriptParser(MB).readDefsym(Name);
+}
index f820044..d48d5aa 100644 (file)
@@ -25,6 +25,9 @@ void readVersionScript(MemoryBufferRef MB);
 
 void readDynamicList(MemoryBufferRef MB);
 
+// Parses the defsym expression.
+void readDefsym(StringRef Name, MemoryBufferRef MB);
+
 } // namespace elf
 } // namespace lld
 
index b821484..2abc08f 100644 (file)
@@ -19,7 +19,7 @@
 # CHECK-NEXT:   Section: Absolute
 # CHECK-NEXT: }
 # CHECK-NEXT: Symbol {
-# CHECK-NEXT:   Name: foo1
+# CHECK-NEXT:   Name: foo2
 # CHECK-NEXT:   Value: 0x123
 # CHECK-NEXT:   Size:
 # CHECK-NEXT:   Binding: Global
 # 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: ld.lld -o %t %t.o --defsym=foo2=1
+# RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=ABS
 
-# RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR2
-# ERR2: error: -defsym: undefined symbol: und
+# ABS:      Symbol {
+# ABS:        Name: foo2
+# ABS-NEXT:   Value: 0x1
+# ABS-NEXT:   Size:
+# ABS-NEXT:   Binding: Global
+# ABS-NEXT:   Type:
+# ABS-NEXT:   Other:
+# ABS-NEXT:   Section: Absolute
+# ABS-NEXT: }
+
+# RUN: ld.lld -o %t %t.o --defsym=foo2=foo1+5
+# RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=EXPR
+
+# EXPR:      Symbol {
+# EXPR:        Name: foo1
+# EXPR-NEXT:   Value: 0x123
+# EXPR-NEXT:   Size:
+# EXPR-NEXT:   Binding: Global
+# EXPR-NEXT:   Type:
+# EXPR-NEXT:   Other:
+# EXPR-NEXT:   Section: Absolute
+# EXPR-NEXT: }
+# EXPR-NEXT: Symbol {
+# EXPR-NEXT:   Name: foo2
+# EXPR-NEXT:   Value: 0x128
+# EXPR-NEXT:   Size:
+# EXPR-NEXT:   Binding: Global
+# EXPR-NEXT:   Type:
+# EXPR-NEXT:   Other:
+# EXPR-NEXT:   Section: Absolute
+# EXPR-NEXT: }
+
+# RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR
+# ERR: error: -defsym:1: symbol not found: und
 
 .globl foo1
  foo1 = 0x123