COFF: Add /alternatename option.
authorRui Ueyama <ruiu@google.com>
Sun, 31 May 2015 22:31:31 +0000 (22:31 +0000)
committerRui Ueyama <ruiu@google.com>
Sun, 31 May 2015 22:31:31 +0000 (22:31 +0000)
Previously, this feature was implemented using a special type of
undefined symbol, in addition to an intricate way to make the resolver
read a virtual file containing that renaming symbols.

Now the feature is directly handled by the symbol table.
The symbol table has a function, rename(), to rename symbols, whose
definition is 4 lines long. Symbol renaming is naturally modeled using
Symbol and SymbolBody.

llvm-svn: 238696

lld/COFF/Driver.cpp
lld/COFF/SymbolTable.cpp
lld/COFF/SymbolTable.h
lld/test/COFF/alternatename.test [new file with mode: 0644]

index 93b86bf..9e2c89c 100644 (file)
@@ -320,6 +320,27 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
     }
   }
 
+  // Add weak aliases. Weak aliases is a mechanism to give remaining
+  // undefined symbols final chance to be resolved successfully.
+  // This is symbol renaming.
+  for (auto *Arg : Args->filtered(OPT_alternatename)) {
+    StringRef From, To;
+    std::tie(From, To) = StringRef(Arg->getValue()).split('=');
+    if (From.empty() || To.empty()) {
+      llvm::errs() << "/alternatename: invalid argument: "
+                   << Arg->getValue() << "\n";
+      return false;
+    }
+    // If it's already resolved as some Defined type, do nothing.
+    // Otherwise, rename it to see if To can be resolved successfully.
+    if (Symtab.find(From))
+      continue;
+    if (auto EC = Symtab.rename(From, To)) {
+      llvm::errs() << EC.message() << "\n";
+      return false;
+    }
+  }
+
   // Windows specific -- If entry point name is not given, we need to
   // infer that from user-defined entry name. The symbol table takes
   // care of details.
index e0dfbc3..da1aa84 100644 (file)
@@ -187,6 +187,15 @@ std::error_code SymbolTable::addUndefined(StringRef Name) {
   return addSymbol(new Undefined(Name));
 }
 
+// Resolve To, and make From an alias to To.
+std::error_code SymbolTable::rename(StringRef From, StringRef To) {
+  SymbolBody *Body = new (Alloc) Undefined(To);
+  if (auto EC = resolve(Body))
+    return EC;
+  Symtab[From]->Body = Body->getReplacement();
+  return std::error_code();
+}
+
 std::error_code SymbolTable::addSymbol(SymbolBody *Body) {
   OwningSymbols.push_back(std::unique_ptr<SymbolBody>(Body));
   return resolve(Body);
index ed3969b..3be6e76 100644 (file)
@@ -68,6 +68,9 @@ public:
   // Creates an Undefined symbol for a given name.
   std::error_code addUndefined(StringRef Name);
 
+  // Rename From -> To in the symbol table.
+  std::error_code rename(StringRef From, StringRef To);
+
 private:
   std::error_code addObject(ObjectFile *File);
   std::error_code addArchive(ArchiveFile *File);
diff --git a/lld/test/COFF/alternatename.test b/lld/test/COFF/alternatename.test
new file mode 100644 (file)
index 0000000..0e8a604
--- /dev/null
@@ -0,0 +1,4 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld -flavor link2 /entry:foo /subsystem:console \
+# RUN:   /alternatename:foo=mainCRTStartup /out:%t.exe %t.obj