diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:26:01 +0000 |
commit | 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch) | |
tree | 6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp | |
parent | 6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff) | |
parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp | 214 |
1 files changed, 152 insertions, 62 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp index d3b5cf2d9f7b..e67b02405a3a 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp @@ -12,6 +12,8 @@ #include "llvm/Object/COFFImportFile.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" @@ -52,18 +54,12 @@ StringRef COFFImportFile::getFileFormatName() const { } } -StringRef COFFImportFile::getExportName() const { - const coff_import_header *hdr = getCOFFImportHeader(); - StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first; - +static StringRef applyNameType(ImportNameType Type, StringRef name) { auto ltrim1 = [](StringRef s, StringRef chars) { return !s.empty() && chars.contains(s[0]) ? s.substr(1) : s; }; - switch (hdr->getNameType()) { - case IMPORT_ORDINAL: - name = ""; - break; + switch (Type) { case IMPORT_NAME_NOPREFIX: name = ltrim1(name, "?@_"); break; @@ -71,6 +67,24 @@ StringRef COFFImportFile::getExportName() const { name = ltrim1(name, "?@_"); name = name.substr(0, name.find('@')); break; + default: + break; + } + return name; +} + +StringRef COFFImportFile::getExportName() const { + const coff_import_header *hdr = getCOFFImportHeader(); + StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first; + + switch (hdr->getNameType()) { + case IMPORT_ORDINAL: + name = ""; + break; + case IMPORT_NAME_NOPREFIX: + case IMPORT_NAME_UNDECORATE: + name = applyNameType(static_cast<ImportNameType>(hdr->getNameType()), name); + break; case IMPORT_NAME_EXPORTAS: { // Skip DLL name name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1); @@ -84,6 +98,27 @@ StringRef COFFImportFile::getExportName() const { return name; } +Error COFFImportFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { + switch (Symb.p) { + case ImpSymbol: + OS << "__imp_"; + break; + case ECAuxSymbol: + OS << "__imp_aux_"; + break; + } + const char *Name = Data.getBufferStart() + sizeof(coff_import_header); + if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) { + if (std::optional<std::string> DemangledName = + getArm64ECDemangledFunctionName(Name)) { + OS << StringRef(*DemangledName); + return Error::success(); + } + } + OS << StringRef(Name); + return Error::success(); +} + static uint16_t getImgRelRelocation(MachineTypes Machine) { switch (Machine) { default: @@ -623,10 +658,14 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym, Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef<COFFShortExport> Exports, - MachineTypes Machine, bool MinGW) { + MachineTypes Machine, bool MinGW, + ArrayRef<COFFShortExport> NativeExports) { - MachineTypes NativeMachine = - isArm64EC(Machine) ? IMAGE_FILE_MACHINE_ARM64 : Machine; + MachineTypes NativeMachine = Machine; + if (isArm64EC(Machine)) { + NativeMachine = IMAGE_FILE_MACHINE_ARM64; + Machine = IMAGE_FILE_MACHINE_ARM64EC; + } std::vector<NewArchiveMember> Members; ObjectFactory OF(llvm::sys::path::filename(ImportName), NativeMachine); @@ -640,66 +679,117 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, std::vector<uint8_t> NullThunk; Members.push_back(OF.createNullThunk(NullThunk)); - for (const COFFShortExport &E : Exports) { - if (E.Private) - continue; - - ImportType ImportType = IMPORT_CODE; - if (E.Data) - ImportType = IMPORT_DATA; - if (E.Constant) - ImportType = IMPORT_CONST; - - StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName; - std::string Name; - - if (E.ExtName.empty()) { - Name = std::string(SymbolName); - } else { - Expected<std::string> ReplacedName = - replace(SymbolName, E.Name, E.ExtName); - if (!ReplacedName) - return ReplacedName.takeError(); - Name.swap(*ReplacedName); - } - - if (!E.AliasTarget.empty() && Name != E.AliasTarget) { - Members.push_back( - OF.createWeakExternal(E.AliasTarget, Name, false, Machine)); - Members.push_back( - OF.createWeakExternal(E.AliasTarget, Name, true, Machine)); - continue; - } + auto addExports = [&](ArrayRef<COFFShortExport> Exp, + MachineTypes M) -> Error { + StringMap<std::string> RegularImports; + struct Deferred { + std::string Name; + ImportType ImpType; + const COFFShortExport *Export; + }; + SmallVector<Deferred, 0> Renames; + for (const COFFShortExport &E : Exp) { + if (E.Private) + continue; + + ImportType ImportType = IMPORT_CODE; + if (E.Data) + ImportType = IMPORT_DATA; + if (E.Constant) + ImportType = IMPORT_CONST; + + StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName; + std::string Name; + + if (E.ExtName.empty()) { + Name = std::string(SymbolName); + } else { + Expected<std::string> ReplacedName = + replace(SymbolName, E.Name, E.ExtName); + if (!ReplacedName) + return ReplacedName.takeError(); + Name.swap(*ReplacedName); + } - ImportNameType NameType; - std::string ExportName; - if (E.Noname) { - NameType = IMPORT_ORDINAL; - } else { - NameType = getNameType(SymbolName, E.Name, Machine, MinGW); - } + ImportNameType NameType; + std::string ExportName; + if (E.Noname) { + NameType = IMPORT_ORDINAL; + } else if (!E.ExportAs.empty()) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName = E.ExportAs; + } else if (!E.ImportName.empty()) { + // If we need to import from a specific ImportName, we may need to use + // a weak alias (which needs another import to point at). But if we can + // express ImportName based on the symbol name and a specific NameType, + // prefer that over an alias. + if (Machine == IMAGE_FILE_MACHINE_I386 && + applyNameType(IMPORT_NAME_UNDECORATE, Name) == E.ImportName) + NameType = IMPORT_NAME_UNDECORATE; + else if (Machine == IMAGE_FILE_MACHINE_I386 && + applyNameType(IMPORT_NAME_NOPREFIX, Name) == E.ImportName) + NameType = IMPORT_NAME_NOPREFIX; + else if (isArm64EC(M)) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName = E.ImportName; + } else if (Name == E.ImportName) + NameType = IMPORT_NAME; + else { + Deferred D; + D.Name = Name; + D.ImpType = ImportType; + D.Export = &E; + Renames.push_back(D); + continue; + } + } else { + NameType = getNameType(SymbolName, E.Name, M, MinGW); + } - // On ARM64EC, use EXPORTAS to import demangled name for mangled symbols. - if (ImportType == IMPORT_CODE && isArm64EC(Machine)) { - if (std::optional<std::string> MangledName = - getArm64ECMangledFunctionName(Name)) { - if (ExportName.empty()) { + // On ARM64EC, use EXPORTAS to import demangled name for mangled symbols. + if (ImportType == IMPORT_CODE && isArm64EC(M)) { + if (std::optional<std::string> MangledName = + getArm64ECMangledFunctionName(Name)) { + if (!E.Noname && ExportName.empty()) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName.swap(Name); + } + Name = std::move(*MangledName); + } else if (!E.Noname && ExportName.empty()) { NameType = IMPORT_NAME_EXPORTAS; - ExportName.swap(Name); + ExportName = std::move(*getArm64ECDemangledFunctionName(Name)); } - Name = std::move(*MangledName); - } else if (ExportName.empty()) { - NameType = IMPORT_NAME_EXPORTAS; - ExportName = std::move(*getArm64ECDemangledFunctionName(Name)); + } + + RegularImports[applyNameType(NameType, Name)] = Name; + Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType, + NameType, ExportName, M)); + } + for (const auto &D : Renames) { + auto It = RegularImports.find(D.Export->ImportName); + if (It != RegularImports.end()) { + // We have a regular import entry for a symbol with the name we + // want to reference; produce an alias pointing at that. + StringRef Symbol = It->second; + if (D.ImpType == IMPORT_CODE) + Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M)); + Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M)); + } else { + Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal, + D.ImpType, IMPORT_NAME_EXPORTAS, + D.Export->ImportName, M)); } } + return Error::success(); + }; - Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType, - NameType, ExportName, Machine)); - } + if (Error e = addExports(Exports, Machine)) + return e; + if (Error e = addExports(NativeExports, NativeMachine)) + return e; return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab, - MinGW ? object::Archive::K_GNU : object::Archive::K_COFF, + object::Archive::K_COFF, /*Deterministic*/ true, /*Thin*/ false, /*OldArchiveBuf*/ nullptr, isArm64EC(Machine)); } |