From 6bf638e6887a2ae1aca34083808eb0b0e30e2c31 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 2 Jul 2015 00:04:14 +0000 Subject: [PATCH] COFF: Simplify and rename findMangle. NFC. Occasionally we have to resolve an undefined symbol to its mangled symbol. Previously, we did that on calling side of findMangle by explicitly updating SymbolBody. In this patch, mangled symbols are handled as weak aliases for undefined symbols. llvm-svn: 241213 --- lld/COFF/Config.h | 6 ++--- lld/COFF/DLL.cpp | 2 +- lld/COFF/Driver.cpp | 59 ++++++++++++++++-------------------------------- lld/COFF/Driver.h | 2 +- lld/COFF/SymbolTable.cpp | 44 ++++++++++++++++-------------------- lld/COFF/SymbolTable.h | 11 +++++---- lld/COFF/Writer.cpp | 2 +- 7 files changed, 51 insertions(+), 75 deletions(-) diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index c8554e1..0ce60b7 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -22,13 +22,13 @@ namespace coff { using llvm::COFF::WindowsSubsystem; using llvm::StringRef; -struct Symbol; +class Undefined; // Represents an /export option. struct Export { StringRef Name; StringRef ExtName; - Symbol *Sym = nullptr; + Undefined *Sym = nullptr; uint16_t Ordinal = 0; bool Noname = false; bool Data = false; @@ -42,7 +42,7 @@ struct Configuration { llvm::COFF::MachineTypes MachineType = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; bool Verbose = false; WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; - StringRef EntryName; + Undefined *Entry = nullptr; bool NoEntry = false; std::string OutputFile; bool DoGC = true; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 5dda972..479e643 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -420,7 +420,7 @@ public: void writeTo(uint8_t *Buf) override { for (Export &E : Config->Exports) { - auto *D = cast(E.Sym->Body); + auto *D = cast(E.Sym->getReplacement()); write32le(Buf + FileOff + E.Ordinal * 4, D->getRVA()); } } diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 66009a2..b0dbf8b 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -202,9 +202,10 @@ void LinkerDriver::addLibSearchPaths() { } } -void LinkerDriver::addUndefined(StringRef Sym) { - Symtab.addUndefined(Sym); - Config->GCRoots.insert(Sym); +Undefined *LinkerDriver::addUndefined(StringRef Name) { + Undefined *U = Symtab.addUndefined(Name); + Config->GCRoots.insert(Name); + return U; } // Windows specific -- find default entry point name. @@ -286,10 +287,8 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { Config->Force = true; // Handle /entry - if (auto *Arg = Args.getLastArg(OPT_entry)) { - Config->EntryName = Arg->getValue(); - addUndefined(Config->EntryName); - } + if (auto *Arg = Args.getLastArg(OPT_entry)) + Config->Entry = addUndefined(Arg->getValue()); // Handle /noentry if (Args.hasArg(OPT_noentry)) { @@ -304,10 +303,8 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { if (Args.hasArg(OPT_dll)) { Config->DLL = true; Config->ManifestID = 2; - if (Config->EntryName.empty() && !Config->NoEntry) { - Config->EntryName = "_DllMainCRTStartup"; - addUndefined("_DllMainCRTStartup"); - } + if (Config->Entry == nullptr && !Config->NoEntry) + Config->Entry = addUndefined("_DllMainCRTStartup"); } // Handle /fixed @@ -544,14 +541,13 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { // Windows specific -- If entry point name is not given, we need to // infer that from user-defined entry name. - if (Config->EntryName.empty() && !Config->NoEntry) { + if (Config->Entry == nullptr && !Config->NoEntry) { StringRef S = findDefaultEntry(); if (S.empty()) { llvm::errs() << "entry point must be defined\n"; return false; } - Config->EntryName = S; - addUndefined(S); + Config->Entry = addUndefined(S); } // Resolve auxiliary symbols until converge. @@ -561,9 +557,16 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { for (;;) { size_t Ver = Symtab.getVersion(); + // Windows specific -- if entry point is not found, + // search for its mangled names. + if (Config->Entry) + Symtab.mangleMaybe(Config->Entry); + // Windows specific -- Make sure we resolve all dllexported symbols. - for (Export &E : Config->Exports) - addUndefined(E.Name); + for (Export &E : Config->Exports) { + E.Sym = addUndefined(E.Name); + Symtab.mangleMaybe(E.Sym); + } // Add weak aliases. Weak aliases is a mechanism to give remaining // undefined symbols final chance to be resolved successfully. @@ -585,30 +588,6 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { break; } - // Windows specific -- if entry point is not found, - // search for its mangled names. - if (!Config->EntryName.empty() && !Symtab.find(Config->EntryName)) { - StringRef Name; - Symbol *Sym; - std::tie(Name, Sym) = Symtab.findMangled(Config->EntryName); - if (Sym) - Symtab.rename(Config->EntryName, Name); - } - - // Windows specific -- resolve dllexported symbols. - for (Export &E : Config->Exports) { - StringRef Name; - Symbol *Sym; - std::tie(Name, Sym) = Symtab.findMangled(E.Name); - if (!Sym) { - llvm::errs() << "exported symbol is not defined: " << E.Name << "\n"; - return false; - } - if (E.Name != Name) - Symtab.rename(E.Name, Name); - E.Sym = Sym; - } - // Make sure we have resolved all symbols. if (Symtab.reportRemainingUndefines()) return false; diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index c3e2186..3bb5682 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -92,7 +92,7 @@ private: std::vector SearchPaths; std::set VisitedFiles; - void addUndefined(StringRef Sym); + Undefined *addUndefined(StringRef Sym); // Windows specific -- "main" is not the only main function in Windows. // You can choose one from these four -- {w,}{WinMain,main}. diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 51cf3de..bc0d1e4 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -25,8 +25,6 @@ namespace coff { SymbolTable::SymbolTable() { addSymbol(new (Alloc) DefinedAbsolute("__ImageBase", Config->ImageBase)); - if (!Config->EntryName.empty()) - addSymbol(new (Alloc) Undefined(Config->EntryName)); } void SymbolTable::addFile(std::unique_ptr FileP) { @@ -123,9 +121,11 @@ bool SymbolTable::reportRemainingUndefines() { continue; StringRef Name = Undef->getName(); // The weak alias may have been resovled, so check for that. - if (auto *D = dyn_cast_or_null(Undef->WeakAlias)) { - Sym->Body = D; - continue; + if (SymbolBody *Alias = Undef->WeakAlias) { + if (auto *D = dyn_cast(Alias->getReplacement())) { + Sym->Body = D; + continue; + } } // If we can resolve a symbol by removing __imp_ prefix, do that. // This odd rule is for compatibility with MSVC linker. @@ -245,34 +245,30 @@ Symbol *SymbolTable::findSymbol(StringRef Name) { return It->second; } -// Find a given symbol or its mangled symbol. -std::pair SymbolTable::findMangled(StringRef S) { - auto It = Symtab.find(S); - if (It != Symtab.end()) { - Symbol *Sym = It->second; - if (isa(Sym->Body)) - return std::make_pair(S, Sym); - } +void SymbolTable::mangleMaybe(Undefined *U) { + if (U->WeakAlias) + return; + if (!isa(U->getReplacement())) + return; // In Microsoft ABI, a non-member function name is mangled this way. - std::string Prefix = ("?" + S + "@@Y").str(); + std::string Prefix = ("?" + U->getName() + "@@Y").str(); for (auto I : Symtab) { StringRef Name = I.first; - Symbol *Sym = I.second; + Symbol *New = I.second; if (!Name.startswith(Prefix)) continue; - if (auto *B = dyn_cast(Sym->Body)) { - addMemberFile(B); - run(); - } - if (isa(Sym->Body)) - return std::make_pair(Name, Sym); + U->WeakAlias = New->Body; + if (auto *L = dyn_cast(New->Body)) + addMemberFile(L); + return; } - return std::make_pair(S, nullptr); } -std::error_code SymbolTable::addUndefined(StringRef Name) { - return addSymbol(new (Alloc) Undefined(Name)); +Undefined *SymbolTable::addUndefined(StringRef Name) { + auto *U = new (Alloc) Undefined(Name); + addSymbol(U); + return U; } // Resolve To, and make From an alias to To. diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 8688e8e..b8f2fd8 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -61,10 +61,11 @@ public: Defined *find(StringRef Name); Symbol *findSymbol(StringRef Name); - // Find a symbol assuming that Name is a function name. - // Not only a given string but its mangled names (in MSVC C++ manner) - // will be searched. - std::pair findMangled(StringRef Name); + // Occasionally we have to resolve an undefined symbol to its + // mangled symbol. This function tries to find a mangled name + // for U from the symbol table, and if found, set the symbol as + // a weak alias for U. + void mangleMaybe(Undefined *U); // Print a layout map to OS. void printMap(llvm::raw_ostream &OS); @@ -82,7 +83,7 @@ public: std::vector ObjectFiles; // Creates an Undefined symbol for a given name. - std::error_code addUndefined(StringRef Name); + Undefined *addUndefined(StringRef Name); // Rename From -> To in the symbol table. std::error_code rename(StringRef From, StringRef To); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 7d85e534..0a1e051 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -348,7 +348,7 @@ void Writer::writeHeader() { PE->SizeOfImage = SizeOfImage; PE->SizeOfHeaders = SizeOfHeaders; if (!Config->NoEntry) { - Defined *Entry = cast(Symtab->find(Config->EntryName)); + Defined *Entry = cast(Config->Entry->getReplacement()); PE->AddressOfEntryPoint = Entry->getRVA(); } PE->SizeOfStackReserve = Config->StackReserve; -- 2.7.4