From 360bace8ebd028efaed8655a00642063895f873f Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sun, 31 May 2015 22:31:31 +0000 Subject: [PATCH] COFF: Add /alternatename option. 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 | 21 +++++++++++++++++++++ lld/COFF/SymbolTable.cpp | 9 +++++++++ lld/COFF/SymbolTable.h | 3 +++ lld/test/COFF/alternatename.test | 4 ++++ 4 files changed, 37 insertions(+) create mode 100644 lld/test/COFF/alternatename.test diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 93b86bf..9e2c89c 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -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. diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index e0dfbc3..da1aa84 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -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(Body)); return resolve(Body); diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index ed3969b..3be6e76 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -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 index 0000000..0e8a604 --- /dev/null +++ b/lld/test/COFF/alternatename.test @@ -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 -- 2.7.4