diff options
| -rw-r--r-- | lld/COFF/Config.h | 7 | ||||
| -rw-r--r-- | lld/COFF/DLL.cpp | 2 | ||||
| -rw-r--r-- | lld/COFF/Driver.cpp | 20 | ||||
| -rw-r--r-- | lld/COFF/DriverUtils.cpp | 86 | ||||
| -rw-r--r-- | lld/COFF/ModuleDef.cpp | 12 | ||||
| -rw-r--r-- | lld/test/COFF/dll.test | 12 | ||||
| -rw-r--r-- | lld/test/COFF/export32.test | 6 |
7 files changed, 89 insertions, 56 deletions
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 4fb02c50f8c..aa1c226ec50 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -36,14 +36,17 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386; struct Export { StringRef Name; // N in /export:N or /export:E=N StringRef ExtName; // E in /export:E=N - StringRef ExtDLLName; // Symbol name written to a DLL export table - StringRef ExtLibName; // Symbol name written to a import library Undefined *Sym = nullptr; uint16_t Ordinal = 0; bool Noname = false; bool Data = false; bool Private = false; + // True if this /export option was in .drectves section. + bool Directives = false; + StringRef SymbolName; + StringRef ExportName; // Name in DLL + bool operator==(const Export &E) { return (Name == E.Name && ExtName == E.ExtName && Ordinal == E.Ordinal && Noname == E.Noname && diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index f71801d97fc..5da0fca3c71 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -539,7 +539,7 @@ EdataContents::EdataContents() { std::vector<Chunk *> Names; for (Export &E : Config->Exports) if (!E.Noname) - Names.push_back(new StringChunk(E.ExtDLLName)); + Names.push_back(new StringChunk(E.ExportName)); auto *NameTab = new NamePointersChunk(Names); auto *OrdinalTab = new ExportOrdinalChunk(Names.size()); auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName, diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 6781ccf5f29..96139aa03a8 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -81,6 +81,10 @@ static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) { return std::unique_ptr<InputFile>(new ObjectFile(MB)); } +static bool isDecorated(StringRef Sym) { + return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?"); +} + // Parses .drectve section contents and returns a list of files // specified by /defaultlib. void LinkerDriver::parseDirectives(StringRef S) { @@ -99,8 +103,7 @@ void LinkerDriver::parseDirectives(StringRef S) { break; case OPT_export: { Export E = parseExport(Arg->getValue()); - if (Config->Machine == I386 && E.ExtName.startswith("_")) - E.ExtName = E.ExtName.substr(1); + E.Directives = true; Config->Exports.push_back(E); break; } @@ -520,8 +523,12 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) { // Handle /export for (auto *Arg : Args.filtered(OPT_export)) { Export E = parseExport(Arg->getValue()); - if (Config->Machine == I386 && !E.Name.startswith("_@?")) - E.Name = mangle(E.Name); + if (Config->Machine == I386) { + if (!isDecorated(E.Name)) + E.Name = Alloc.save("_" + E.Name); + if (!E.ExtName.empty() && !isDecorated(E.ExtName)) + E.ExtName = Alloc.save("_" + E.ExtName); + } Config->Exports.push_back(E); } @@ -574,7 +581,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) { // Windows specific -- Make sure we resolve all dllexported symbols. for (Export &E : Config->Exports) { E.Sym = addUndefined(E.Name); - Symtab.mangleMaybe(E.Sym); + if (!E.Directives) + Symtab.mangleMaybe(E.Sym); } // Add weak aliases. Weak aliases is a mechanism to give remaining @@ -626,7 +634,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) { // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. - if (!Config->Exports.empty()) { + if (Config->DLL) { fixupExports(); writeImportLibrary(); assignExportOrdinals(); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 6304e48a791..e6a4950c01f 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -370,6 +370,12 @@ err: error(Twine("invalid /export: ") + Arg); } +static StringRef undecorate(StringRef Sym) { + if (Config->Machine != I386) + return Sym; + return Sym.startswith("_") ? Sym.substr(1) : Sym; +} + // Performs error checking on all /export arguments. // It also sets ordinals. void fixupExports() { @@ -379,30 +385,25 @@ void fixupExports() { if (E.Ordinal == 0) continue; if (!Ords.insert(E.Ordinal).second) - error(Twine("duplicate export ordinal: ") + E.Name); + error("duplicate export ordinal: " + E.Name); } for (Export &E : Config->Exports) { - if (!E.ExtName.empty()) { - E.ExtDLLName = E.ExtName; - E.ExtLibName = E.ExtName; - continue; - } - StringRef S = E.Sym->repl()->getName(); - if (Config->Machine == I386 && S.startswith("_")) { - E.ExtDLLName = S.substr(1).split('@').first; - E.ExtLibName = S.substr(1); - continue; + if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) { + E.SymbolName = U->getName(); + } else { + E.SymbolName = E.Sym->getName(); } - E.ExtDLLName = S; - E.ExtLibName = S; } + for (Export &E : Config->Exports) + E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName); + // Uniquefy by name. std::map<StringRef, Export *> Map; std::vector<Export> V; for (Export &E : Config->Exports) { - auto Pair = Map.insert(std::make_pair(E.ExtLibName, &E)); + auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); bool Inserted = Pair.second; if (Inserted) { V.push_back(E); @@ -418,7 +419,7 @@ void fixupExports() { // Sort by name. std::sort(Config->Exports.begin(), Config->Exports.end(), [](const Export &A, const Export &B) { - return A.ExtDLLName < B.ExtDLLName; + return A.ExportName < B.ExportName; }); } @@ -535,12 +536,8 @@ class ShortImportCreator { public: ShortImportCreator(object::Archive *A, StringRef S) : Parent(A), DLLName(S) {} - NewArchiveIterator create(const Export &E) { - std::string Sym = E.ExtLibName; - bool Decorated = - E.ExtLibName.startswith("?") || E.ExtLibName.startswith("@"); - if (Config->Machine == I386 && !Decorated) - Sym = (Twine("_") + Sym).str(); + NewArchiveIterator create(StringRef Sym, uint16_t Ordinal, + ImportNameType NameType, bool isData) { size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs size_t Size = sizeof(object::ArchiveMemberHeader) + sizeof(coff_import_header) + ImpSize; @@ -564,22 +561,16 @@ public: Imp->Sig2 = 0xFFFF; Imp->Machine = Config->Machine; Imp->SizeOfData = ImpSize; - if (E.Ordinal > 0) - Imp->OrdinalHint = E.Ordinal; - Imp->TypeInfo = (E.Data ? IMPORT_DATA : IMPORT_CODE); + if (Ordinal > 0) + Imp->OrdinalHint = Ordinal; + Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE); Imp->TypeInfo = IMPORT_CODE; - if (E.Noname) { - Imp->TypeInfo |= IMPORT_ORDINAL << 2; - } else if (Decorated) { - Imp->TypeInfo |= IMPORT_NAME << 2; - } else { - Imp->TypeInfo |= IMPORT_NAME_NOPREFIX << 2; - } + Imp->TypeInfo |= NameType << 2; // Write symbol name and DLL name. - sprintf(P, Sym.data(), Sym.size()); + memcpy(P, Sym.data(), Sym.size()); P += Sym.size() + 1; - sprintf(P, DLLName.data(), DLLName.size()); + memcpy(P, DLLName.data(), DLLName.size()); object::Archive::Child C(Parent, Buf); return NewArchiveIterator(C, nextFilename()); @@ -598,6 +589,20 @@ private: int Idx = 1; }; +static ImportNameType getNameType(StringRef Sym, StringRef ExtName) { + if (Sym != ExtName) + return IMPORT_NAME_UNDECORATE; + if (Config->Machine == I386 && Sym.startswith("_")) + return IMPORT_NAME_NOPREFIX; + return IMPORT_NAME; +} + +static std::string replace(StringRef S, StringRef From, StringRef To) { + size_t Pos = S.find(From); + assert(Pos != StringRef::npos); + return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str(); +} + // Creates an import library for a DLL. In this function, we first // create an empty import library using lib.exe and then adds short // import files to that file. @@ -610,9 +615,18 @@ void writeImportLibrary() { std::string DLLName = llvm::sys::path::filename(Config->OutputFile); ShortImportCreator ShortImport(&Archive, DLLName); - for (Export &E : Config->Exports) - if (!E.Private) - Members.push_back(ShortImport.create(E)); + for (Export &E : Config->Exports) { + if (E.Private) + continue; + if (E.ExtName.empty()) { + Members.push_back(ShortImport.create( + E.SymbolName, E.Ordinal, getNameType(E.SymbolName, E.Name), E.Data)); + } else { + Members.push_back(ShortImport.create( + replace(E.SymbolName, E.Name, E.ExtName), E.Ordinal, + getNameType(E.SymbolName, E.Name), E.Data)); + } + } std::string Path = getImplibPath(); std::pair<StringRef, std::error_code> Result = diff --git a/lld/COFF/ModuleDef.cpp b/lld/COFF/ModuleDef.cpp index fab3e4a1852..1ccca01b899 100644 --- a/lld/COFF/ModuleDef.cpp +++ b/lld/COFF/ModuleDef.cpp @@ -54,6 +54,10 @@ struct Token { StringRef Value; }; +static bool isDecorated(StringRef Sym) { + return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?"); +} + class Lexer { public: explicit Lexer(StringRef S) : Buf(S) {} @@ -191,8 +195,12 @@ private: unget(); } - if (Config->Machine == I386 && !E.Name.startswith("_@?")) - E.Name = Alloc->save("_" + E.Name); + if (Config->Machine == I386) { + if (!isDecorated(E.Name)) + E.Name = Alloc->save("_" + E.Name); + if (!E.ExtName.empty() && !isDecorated(E.ExtName)) + E.ExtName = Alloc->save("_" + E.ExtName); + } for (;;) { read(); diff --git a/lld/test/COFF/dll.test b/lld/test/COFF/dll.test index b702f2e563a..bafd3c233c8 100644 --- a/lld/test/COFF/dll.test +++ b/lld/test/COFF/dll.test @@ -10,10 +10,10 @@ EXPORT: Export Table: EXPORT: DLL name: dll.test.tmp.dll EXPORT: Ordinal RVA Name EXPORT-NEXT: 0 0 -EXPORT-NEXT: 1 0x1010 ?mangled@@YAHXZ -EXPORT-NEXT: 2 0x1008 exportfn1 -EXPORT-NEXT: 3 0x1010 exportfn2 -EXPORT-NEXT: 4 0x1010 exportfn3 +EXPORT-NEXT: 1 0x1008 exportfn1 +EXPORT-NEXT: 2 0x1010 exportfn2 +EXPORT-NEXT: 3 0x1010 exportfn3 +EXPORT-NEXT: 4 0x1010 mangled # RUN: yaml2obj < %p/Inputs/export2.yaml > %t5.obj # RUN: rm -f %t5.lib @@ -25,8 +25,8 @@ EXPORT2: Export Table: EXPORT2: DLL name: dll.test.tmp5.dll EXPORT2: Ordinal RVA Name EXPORT2-NEXT: 0 0 -EXPORT2-NEXT: 1 0x101c ?mangled2@@YAHXZ -EXPORT2-NEXT: 2 0x1010 exportfn3 +EXPORT2-NEXT: 1 0x1010 exportfn3 +EXPORT2-NEXT: 2 0x101c mangled2 # RUN: llvm-as -o %t.lto.obj %p/Inputs/export.ll # RUN: lld-link /out:%t.lto.dll /dll %t.lto.obj /export:exportfn1 /export:exportfn2 diff --git a/lld/test/COFF/export32.test b/lld/test/COFF/export32.test index 5c1ddc91bd5..5d7b2708dcb 100644 --- a/lld/test/COFF/export32.test +++ b/lld/test/COFF/export32.test @@ -24,9 +24,9 @@ # CHECK2-NEXT: 3 0 # CHECK2-NEXT: 4 0 # CHECK2-NEXT: 5 0x1008 exportfn1 -# CHECK2-NEXT: 6 0x1010 ?mangled@@YAHXZ -# CHECK2-NEXT: 7 0x1010 exportfn2 -# CHECK2-NEXT: 8 0x1010 exportfn3 +# CHECK2-NEXT: 6 0x1010 exportfn2 +# CHECK2-NEXT: 7 0x1010 exportfn3 +# CHECK2-NEXT: 8 0x1010 mangled # RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5,noname /export:exportfn2 # RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s |

