https://github.com/dpaoliello created https://github.com/llvm/llvm-project/pull/84590
Backports fixes to be able to generate import libraries for ARM64EC: * <https://github.com/llvm/llvm-project/pull/78769> * <https://github.com/llvm/llvm-project/pull/81059> * <https://github.com/llvm/llvm-project/pull/78772> >From 8f5a8fc5340687eb6ea943ec8460de56d141ede9 Mon Sep 17 00:00:00 2001 From: Jacek Caban <ja...@codeweavers.com> Date: Tue, 6 Feb 2024 13:47:58 +0100 Subject: [PATCH 1/3] [llvm-readobj][Object][COFF] Print COFF import library symbol export name. (#78769) getExportName implementation is based on lld-link. In its current form, it's mostly about convenience, but it will be more useful for EXPORTAS support, for which export name is not possible to deduce from other printed properties. --- lld/test/COFF/def-export-cpp.s | 1 + lld/test/COFF/def-export-stdcall.s | 13 ++++++++++ lld/test/COFF/dllexport.s | 4 +++ llvm/include/llvm/Object/COFFImportFile.h | 1 + llvm/lib/Object/COFFImportFile.cpp | 26 +++++++++++++++++++ .../tools/llvm-dlltool/coff-decorated.def | 7 +++++ llvm/test/tools/llvm-dlltool/coff-exports.def | 3 +++ llvm/test/tools/llvm-dlltool/coff-noname.def | 1 + .../llvm-dlltool/no-leading-underscore.def | 2 ++ llvm/test/tools/llvm-lib/arm64ec-implib.test | 2 ++ .../tools/llvm-readobj/COFF/file-headers.test | 1 + llvm/tools/llvm-readobj/COFFImportDumper.cpp | 3 +++ 12 files changed, 64 insertions(+) diff --git a/lld/test/COFF/def-export-cpp.s b/lld/test/COFF/def-export-cpp.s index e00b35b1c5b39b..370b8ddba4104b 100644 --- a/lld/test/COFF/def-export-cpp.s +++ b/lld/test/COFF/def-export-cpp.s @@ -10,6 +10,7 @@ # IMPLIB: File: foo.dll # IMPLIB: Name type: undecorate +# IMPLIB-NEXT: Export name: GetPathOnDisk # IMPLIB-NEXT: Symbol: __imp_?GetPathOnDisk@@YA_NPEA_W@Z # IMPLIB-NEXT: Symbol: ?GetPathOnDisk@@YA_NPEA_W@Z diff --git a/lld/test/COFF/def-export-stdcall.s b/lld/test/COFF/def-export-stdcall.s index f015e205c74a33..7e4e04c77cbe7a 100644 --- a/lld/test/COFF/def-export-stdcall.s +++ b/lld/test/COFF/def-export-stdcall.s @@ -6,15 +6,19 @@ # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix UNDECORATED-EXPORTS %s # UNDECORATED-IMPLIB: Name type: noprefix +# UNDECORATED-IMPLIB-NEXT: Export name: _underscored # UNDECORATED-IMPLIB-NEXT: __imp___underscored # UNDECORATED-IMPLIB-NEXT: __underscored # UNDECORATED-IMPLIB: Name type: undecorate +# UNDECORATED-IMPLIB-NEXT: Export name: fastcall # UNDECORATED-IMPLIB-NEXT: __imp_@fastcall@8 # UNDECORATED-IMPLIB-NEXT: fastcall@8 # UNDECORATED-IMPLIB: Name type: undecorate +# UNDECORATED-IMPLIB-NEXT: Export name: stdcall # UNDECORATED-IMPLIB-NEXT: __imp__stdcall@8 # UNDECORATED-IMPLIB-NEXT: _stdcall@8 # UNDECORATED-IMPLIB: Name type: undecorate +# UNDECORATED-IMPLIB-NEXT: Export name: vectorcall # UNDECORATED-IMPLIB-NEXT: __imp_vectorcall@@8 # UNDECORATED-IMPLIB-NEXT: vectorcall@@8 @@ -30,12 +34,15 @@ # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: @fastcall@8 # DECORATED-IMPLIB-NEXT: __imp_@fastcall@8 # DECORATED-IMPLIB-NEXT: @fastcall@8 # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: _stdcall@8 # DECORATED-IMPLIB-NEXT: __imp__stdcall@8 # DECORATED-IMPLIB-NEXT: _stdcall@8 # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: vectorcall@@8 # DECORATED-IMPLIB-NEXT: __imp_vectorcall@@8 # DECORATED-IMPLIB-NEXT: vectorcall@@8 @@ -51,14 +58,17 @@ # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s # DECORATED-MINGW-IMPLIB: Name type: name +# DECORATED-MINGW-IMPLIB-NEXT: Export name: @fastcall@8 # DECORATED-MINGW-IMPLIB-NEXT: __imp_@fastcall@8 # DECORATED-MINGW-IMPLIB-NEXT: fastcall@8 # DECORATED-MINGW-IMPLIB: Name type: noprefix +# DECORATED-MINGW-IMPLIB-NEXT: Export name: stdcall@8 # DECORATED-MINGW-IMPLIB-NEXT: __imp__stdcall@8 # DECORATED-MINGW-IMPLIB-NEXT: _stdcall@8 # GNU tools don't support vectorcall, but this test is just to track that # lld's behaviour remains consistent over time. # DECORATED-MINGW-IMPLIB: Name type: name +# DECORATED-MINGW-IMPLIB-NEXT: Export name: vectorcall@@8 # DECORATED-MINGW-IMPLIB-NEXT: __imp_vectorcall@@8 # DECORATED-MINGW-IMPLIB-NEXT: vectorcall@@8 @@ -75,14 +85,17 @@ # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s # MINGW-KILL-AT-IMPLIB: Name type: noprefix +# MINGW-KILL-AT-IMPLIB: Export name: fastcall # MINGW-KILL-AT-IMPLIB: __imp__fastcall # MINGW-KILL-AT-IMPLIB-NEXT: _fastcall # MINGW-KILL-AT-IMPLIB: Name type: noprefix +# MINGW-KILL-AT-IMPLIB-NEXT: Export name: stdcall # MINGW-KILL-AT-IMPLIB-NEXT: __imp__stdcall # MINGW-KILL-AT-IMPLIB-NEXT: _stdcall # GNU tools don't support vectorcall, but this test is just to track that # lld's behaviour remains consistent over time. # MINGW-KILL-AT-IMPLIB: Name type: noprefix +# MINGW-KILL-AT-IMPLIB-NEXT: Export name: vectorcall # MINGW-KILL-AT-IMPLIB-NEXT: __imp__vectorcall # MINGW-KILL-AT-IMPLIB-NEXT: _vectorcall diff --git a/lld/test/COFF/dllexport.s b/lld/test/COFF/dllexport.s index a238b70ce1b4f6..b04ebc3a33c3e2 100644 --- a/lld/test/COFF/dllexport.s +++ b/lld/test/COFF/dllexport.s @@ -6,15 +6,19 @@ # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: @fastcall@8 # DECORATED-IMPLIB-NEXT: __imp_@fastcall@8 # DECORATED-IMPLIB-NEXT: @fastcall@8 # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: _stdcall@8 # DECORATED-IMPLIB-NEXT: __imp__stdcall@8 # DECORATED-IMPLIB-NEXT: _stdcall@8 # DECORATED-IMPLIB: Name type: noprefix +# DECORATED-IMPLIB-NEXT: Export name: _underscored # DECORATED-IMPLIB-NEXT: __imp___underscored # DECORATED-IMPLIB-NEXT: __underscored # DECORATED-IMPLIB: Name type: name +# DECORATED-IMPLIB-NEXT: Export name: vectorcall@@8 # DECORATED-IMPLIB-NEXT: __imp_vectorcall@@8 # DECORATED-IMPLIB-NEXT: vectorcall@@8 diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index edc836ff0348cb..45a4a795fd1903 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -66,6 +66,7 @@ class COFFImportFile : public SymbolicFile { uint16_t getMachine() const { return getCOFFImportHeader()->Machine; } StringRef getFileFormatName() const; + StringRef getExportName() const; private: bool isData() const { diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 60556c149bf735..d7d26f4f4180c3 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -52,6 +52,32 @@ StringRef COFFImportFile::getFileFormatName() const { } } +StringRef COFFImportFile::getExportName() const { + const coff_import_header *hdr = getCOFFImportHeader(); + StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first; + + 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; + case IMPORT_NAME_NOPREFIX: + name = ltrim1(name, "?@_"); + break; + case IMPORT_NAME_UNDECORATE: + name = ltrim1(name, "?@_"); + name = name.substr(0, name.find('@')); + break; + default: + break; + } + + return name; +} + static uint16_t getImgRelRelocation(MachineTypes Machine) { switch (Machine) { default: diff --git a/llvm/test/tools/llvm-dlltool/coff-decorated.def b/llvm/test/tools/llvm-dlltool/coff-decorated.def index 856804686168b1..fc81f23d09d6c4 100644 --- a/llvm/test/tools/llvm-dlltool/coff-decorated.def +++ b/llvm/test/tools/llvm-dlltool/coff-decorated.def @@ -14,25 +14,32 @@ OtherStdcallExportName@4=CdeclInternalFunction CdeclExportName=StdcallInternalFunction@4 ; CHECK: Name type: noprefix +; CHECK-NEXT: Export name: CdeclFunction ; CHECK-NEXT: Symbol: __imp__CdeclFunction ; CHECK-NEXT: Symbol: _CdeclFunction ; CHECK: Name type: undecorate +; CHECK-NEXT: Export name: StdcallFunction ; CHECK-NEXT: Symbol: __imp__StdcallFunction@4 ; CHECK-NEXT: Symbol: _StdcallFunction@4 ; CHECK: Name type: undecorate +; CHECK-NEXT: Export name: FastcallFunction ; CHECK-NEXT: Symbol: __imp_@FastcallFunction@4 ; CHECK-NEXT: Symbol: @FastcallFunction@4 ; CHECK: Name type: name +; CHECK-NEXT: Export name: ??_7exception@@6B@ ; CHECK-NEXT: Symbol: __imp_??_7exception@@6B@ ; CHECK-NEXT: Symbol: ??_7exception@@6B@ ; CHECK-NM: W _StdcallAlias@4 ; CHECK-NM: U _StdcallFunction@4 ; CHECK: Name type: undecorate +; CHECK-NEXT: Export name: StdcallExportName ; CHECK-NEXT: Symbol: __imp__StdcallExportName@4{{$}} ; CHECK-NEXT: Symbol: _StdcallExportName@4{{$}} ; CHECK: Name type: undecorate +; CHECK-NEXT: Export name: OtherStdcallExportName ; CHECK-NEXT: Symbol: __imp__OtherStdcallExportName@4{{$}} ; CHECK-NEXT: Symbol: _OtherStdcallExportName@4{{$}} ; CHECK: Name type: noprefix +; CHECK-NEXT: Export name: CdeclExportName ; CHECK-NEXT: Symbol: __imp__CdeclExportName ; CHECK-NEXT: Symbol: _CdeclExportName diff --git a/llvm/test/tools/llvm-dlltool/coff-exports.def b/llvm/test/tools/llvm-dlltool/coff-exports.def index 57c55744602156..267424db1b8c1d 100644 --- a/llvm/test/tools/llvm-dlltool/coff-exports.def +++ b/llvm/test/tools/llvm-dlltool/coff-exports.def @@ -17,12 +17,15 @@ AnotherFunction ; CHECK-ARM64: Format: COFF-import-file-ARM64 ; CHECK: Type: code ; CHECK: Name type: name +; CHECK-NEXT: Export name: TestFunction1 ; CHECK-NEXT: Symbol: __imp_TestFunction1 ; CHECK-NEXT: Symbol: TestFunction1 ; CHECK: Name type: name +; CHECK-NEXT: Export name: TestFunction2 ; CHECK-NEXT: Symbol: __imp_TestFunction2{{$}} ; CHECK-NEXT: Symbol: TestFunction2{{$}} ; CHECK: Name type: name +; CHECK-NEXT: Export name: TestFunction3 ; CHECK-NEXT: Symbol: __imp_TestFunction3{{$}} ; CHECK-NEXT: Symbol: TestFunction3{{$}} diff --git a/llvm/test/tools/llvm-dlltool/coff-noname.def b/llvm/test/tools/llvm-dlltool/coff-noname.def index 27e60efbd2d802..7cb05846ce28a2 100644 --- a/llvm/test/tools/llvm-dlltool/coff-noname.def +++ b/llvm/test/tools/llvm-dlltool/coff-noname.def @@ -12,5 +12,6 @@ ByNameFunction ; CHECK-NEXT: Symbol: __imp__ByOrdinalFunction ; CHECK-NEXT: Symbol: _ByOrdinalFunction ; CHECK: Name type: noprefix +; CHECK-NEXT: Export name: ByNameFunction ; CHECK-NEXT: Symbol: __imp__ByNameFunction ; CHECK-NEXT: Symbol: _ByNameFunction diff --git a/llvm/test/tools/llvm-dlltool/no-leading-underscore.def b/llvm/test/tools/llvm-dlltool/no-leading-underscore.def index 6b78e15d2b5f69..9c5e77ca29a821 100644 --- a/llvm/test/tools/llvm-dlltool/no-leading-underscore.def +++ b/llvm/test/tools/llvm-dlltool/no-leading-underscore.def @@ -9,9 +9,11 @@ alias == func DecoratedFunction@4 ; CHECK: Name type: name +; CHECK-NEXT: Export name: func ; CHECK-NEXT: Symbol: __imp_func ; CHECK-NEXT: Symbol: func ; CHECK: Name type: undecorate +; CHECK-NEXT: Export name: DecoratedFunction ; CHECK-NEXT: Symbol: __imp_DecoratedFunction@4 ; CHECK-NEXT: Symbol: DecoratedFunction@4 diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 2672f8d38b7f70..4250c775daa601 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -36,6 +36,7 @@ READOBJ-NEXT: File: test.dll READOBJ-NEXT: Format: COFF-import-file-ARM64EC READOBJ-NEXT: Type: code READOBJ-NEXT: Name type: name +READOBJ-NEXT: Export name: funcexp READOBJ-NEXT: Symbol: __imp_funcexp READOBJ-NEXT: Symbol: funcexp READOBJ-EMPTY: @@ -43,6 +44,7 @@ READOBJ-NEXT: File: test.dll READOBJ-NEXT: Format: COFF-import-file-ARM64EC READOBJ-NEXT: Type: data READOBJ-NEXT: Name type: name +READOBJ-NEXT: Export name: dataexp READOBJ-NEXT: Symbol: __imp_dataexp Creating a new lib containing the existing lib: diff --git a/llvm/test/tools/llvm-readobj/COFF/file-headers.test b/llvm/test/tools/llvm-readobj/COFF/file-headers.test index b83a6cf5b972b3..32f39e196b0001 100644 --- a/llvm/test/tools/llvm-readobj/COFF/file-headers.test +++ b/llvm/test/tools/llvm-readobj/COFF/file-headers.test @@ -323,6 +323,7 @@ symbols: # IMPORTLIB:Format: COFF-import-file-i386 # IMPORTLIB-NEXT:Type: code # IMPORTLIB-NEXT:Name type: noprefix +# IMPORTLIB-NEXT:Export name: func # IMPORTLIB-NEXT:Symbol: __imp__func # IMPORTLIB-NEXT:Symbol: _func # IMPORTLIB-NOT:{{.}} diff --git a/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/llvm/tools/llvm-readobj/COFFImportDumper.cpp index 8aedc310ae3a9f..656ca32f03a77d 100644 --- a/llvm/tools/llvm-readobj/COFFImportDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFImportDumper.cpp @@ -47,6 +47,9 @@ void dumpCOFFImportFile(const COFFImportFile *File, ScopedPrinter &Writer) { break; } + if (H->getNameType() != COFF::IMPORT_ORDINAL) + Writer.printString("Export name", File->getExportName()); + for (const object::BasicSymbolRef &Sym : File->symbols()) { raw_ostream &OS = Writer.startLine(); OS << "Symbol: "; >From c8193dc5aaace9ea818e139bb2366a9870682065 Mon Sep 17 00:00:00 2001 From: Jacek Caban <ja...@codeweavers.com> Date: Sat, 10 Feb 2024 01:00:14 +0100 Subject: [PATCH 2/3] [llvm-lib][llvm-dlltool][Object] Add support for EXPORTAS name types. (#78772) EXPORTAS is a new name type in import libraries. It's used by default on ARM64EC, but it's allowed on other platforms as well. --- llvm/include/llvm/BinaryFormat/COFF.h | 5 +- llvm/include/llvm/Object/COFFImportFile.h | 4 + llvm/lib/Object/COFFImportFile.cpp | 66 +++++++++----- llvm/lib/Object/COFFModuleDefinition.cpp | 13 ++- llvm/test/tools/llvm-lib/exportas.test | 94 ++++++++++++++++++++ llvm/tools/llvm-readobj/COFFImportDumper.cpp | 3 + 6 files changed, 162 insertions(+), 23 deletions(-) create mode 100644 llvm/test/tools/llvm-lib/exportas.test diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h index 522ee37da6e830..72461d0d9c316a 100644 --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -716,7 +716,10 @@ enum ImportNameType : unsigned { IMPORT_NAME_NOPREFIX = 2, /// The import name is the public symbol name, but skipping the leading ?, /// @, or optionally _, and truncating at the first @. - IMPORT_NAME_UNDECORATE = 3 + IMPORT_NAME_UNDECORATE = 3, + /// The import name is specified as a separate string in the import library + /// object file. + IMPORT_NAME_EXPORTAS = 4 }; enum class GuardFlags : uint32_t { diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 45a4a795fd1903..7c5846e9c044e3 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -92,6 +92,10 @@ struct COFFShortExport { /// file, this is "baz" in "EXPORTS\nfoo = bar == baz". std::string AliasTarget; + /// Specifies EXPORTAS name. In a .def file, this is "bar" in + /// "EXPORTS\nfoo EXPORTAS bar". + std::string ExportAs; + uint16_t Ordinal = 0; bool Noname = false; bool Data = false; diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index d7d26f4f4180c3..51e6274dcf235c 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -71,6 +71,12 @@ StringRef COFFImportFile::getExportName() const { name = ltrim1(name, "?@_"); name = name.substr(0, name.find('@')); break; + case IMPORT_NAME_EXPORTAS: { + // Skip DLL name + name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1); + name = name.split('\0').second.split('\0').first; + break; + } default: break; } @@ -209,6 +215,7 @@ class ObjectFactory { // Library Format. NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal, ImportType Type, ImportNameType NameType, + StringRef ExportName, MachineTypes Machine); // Create a weak external file which is described in PE/COFF Aux Format 3. @@ -500,12 +507,13 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) { return {MemoryBufferRef{F, ImportName}}; } -NewArchiveMember ObjectFactory::createShortImport(StringRef Sym, - uint16_t Ordinal, - ImportType ImportType, - ImportNameType NameType, - MachineTypes Machine) { +NewArchiveMember +ObjectFactory::createShortImport(StringRef Sym, uint16_t Ordinal, + ImportType ImportType, ImportNameType NameType, + StringRef ExportName, MachineTypes Machine) { size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs + if (!ExportName.empty()) + ImpSize += ExportName.size() + 1; size_t Size = sizeof(coff_import_header) + ImpSize; char *Buf = Alloc.Allocate<char>(Size); memset(Buf, 0, Size); @@ -525,6 +533,10 @@ NewArchiveMember ObjectFactory::createShortImport(StringRef Sym, memcpy(P, Sym.data(), Sym.size()); P += Sym.size() + 1; memcpy(P, ImportName.data(), ImportName.size()); + if (!ExportName.empty()) { + P += ImportName.size() + 1; + memcpy(P, ExportName.data(), ExportName.size()); + } return {MemoryBufferRef(StringRef(Buf, Size), ImportName)}; } @@ -641,27 +653,39 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, ImportType = IMPORT_CONST; StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName; - ImportNameType NameType = E.Noname - ? IMPORT_ORDINAL - : getNameType(SymbolName, E.Name, - Machine, MinGW); - Expected<std::string> Name = E.ExtName.empty() - ? std::string(SymbolName) - : replace(SymbolName, E.Name, E.ExtName); - - if (!Name) - return Name.takeError(); - - if (!E.AliasTarget.empty() && *Name != E.AliasTarget) { + 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)); + OF.createWeakExternal(E.AliasTarget, Name, false, Machine)); Members.push_back( - OF.createWeakExternal(E.AliasTarget, *Name, true, Machine)); + OF.createWeakExternal(E.AliasTarget, Name, true, Machine)); continue; } - Members.push_back( - OF.createShortImport(*Name, E.Ordinal, ImportType, NameType, Machine)); + ImportNameType NameType; + std::string ExportName; + if (E.Noname) { + NameType = IMPORT_ORDINAL; + } else if (!E.ExportAs.empty()) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName = E.ExportAs; + } else { + NameType = getNameType(SymbolName, E.Name, Machine, MinGW); + } + + Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType, + NameType, ExportName, Machine)); } return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab, diff --git a/llvm/lib/Object/COFFModuleDefinition.cpp b/llvm/lib/Object/COFFModuleDefinition.cpp index 648f01f823d007..f60dd49793685f 100644 --- a/llvm/lib/Object/COFFModuleDefinition.cpp +++ b/llvm/lib/Object/COFFModuleDefinition.cpp @@ -39,6 +39,7 @@ enum Kind { KwConstant, KwData, KwExports, + KwExportAs, KwHeapsize, KwLibrary, KwName, @@ -118,6 +119,7 @@ class Lexer { .Case("CONSTANT", KwConstant) .Case("DATA", KwData) .Case("EXPORTS", KwExports) + .Case("EXPORTAS", KwExportAs) .Case("HEAPSIZE", KwHeapsize) .Case("LIBRARY", KwLibrary) .Case("NAME", KwName) @@ -286,7 +288,16 @@ class Parser { E.AliasTarget = std::string("_").append(E.AliasTarget); continue; } - unget(); + // EXPORTAS must be at the end of export definition + if (Tok.K == KwExportAs) { + read(); + if (Tok.K == Eof) + return createError( + "unexpected end of file, EXPORTAS identifier expected"); + E.ExportAs = std::string(Tok.Value); + } else { + unget(); + } Info.Exports.push_back(E); return Error::success(); } diff --git a/llvm/test/tools/llvm-lib/exportas.test b/llvm/test/tools/llvm-lib/exportas.test new file mode 100644 index 00000000000000..f6e845ca174664 --- /dev/null +++ b/llvm/test/tools/llvm-lib/exportas.test @@ -0,0 +1,94 @@ +Test EXPORTAS in importlibs. + +RUN: split-file %s %t.dir && cd %t.dir +RUN: llvm-lib -machine:amd64 -def:test.def -out:test.lib + +RUN: llvm-nm --print-armap test.lib | FileCheck --check-prefix=ARMAP %s + +ARMAP: Archive map +ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll +ARMAP-NEXT: __imp_func in test.dll +ARMAP-NEXT: __imp_func2 in test.dll +ARMAP-NEXT: __imp_func3 in test.dll +ARMAP-NEXT: __imp_mydata in test.dll +ARMAP-NEXT: func in test.dll +ARMAP-NEXT: func2 in test.dll +ARMAP-NEXT: func3 in test.dll +ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll + +RUN: llvm-readobj test.lib | FileCheck --check-prefix=READOBJ %s + +READOBJ: File: test.lib(test.dll) +READOBJ-NEXT: Format: COFF-x86-64 +READOBJ-NEXT: Arch: x86_64 +READOBJ-NEXT: AddressSize: 64bit +READOBJ-EMPTY: +READOBJ-NEXT: File: test.lib(test.dll) +READOBJ-NEXT: Format: COFF-x86-64 +READOBJ-NEXT: Arch: x86_64 +READOBJ-NEXT: AddressSize: 64bit +READOBJ-EMPTY: +READOBJ-NEXT: File: test.lib(test.dll) +READOBJ-NEXT: Format: COFF-x86-64 +READOBJ-NEXT: Arch: x86_64 +READOBJ-NEXT: AddressSize: 64bit +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-x86-64 +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: expfunc +READOBJ-NEXT: Symbol: __imp_func +READOBJ-NEXT: Symbol: func +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-x86-64 +READOBJ-NEXT: Type: data +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: expdata +READOBJ-NEXT: Symbol: __imp_mydata +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-x86-64 +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: expfunc2 +READOBJ-NEXT: Symbol: __imp_func2 +READOBJ-NEXT: Symbol: func2 +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-x86-64 +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: expfunc3 +READOBJ-NEXT: Symbol: __imp_func3 +READOBJ-NEXT: Symbol: func3 + + +EXPORTAS must be at the end of entry declaration. +RUN: not llvm-lib -machine:amd64 -def:test2.def -out:test2.lib 2>&1 \ +RUN: | FileCheck --check-prefix=ERROR %s +RUN: not llvm-lib -machine:amd64 -def:test3.def -out:test3.lib 2>&1 \ +RUN: | FileCheck --check-prefix=ERROR %s +ERROR: Invalid data was encountered while parsing the file + + +#--- test.def +LIBRARY test.dll +EXPORTS + func EXPORTAS expfunc + mydata DATA EXPORTAS expdata + func2 = myfunc2 EXPORTAS expfunc2 + func3 = otherdll.otherfunc3 EXPORTAS expfunc3 + +#--- test2.def +LIBRARY test.dll +EXPORTS + func EXPORTAS expfunc + mydata EXPORTAS expdata DATA + +#--- test3.def +LIBRARY test.dll +EXPORTS + mydata EXPORTAS diff --git a/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/llvm/tools/llvm-readobj/COFFImportDumper.cpp index 656ca32f03a77d..0ab2a17655653e 100644 --- a/llvm/tools/llvm-readobj/COFFImportDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFImportDumper.cpp @@ -45,6 +45,9 @@ void dumpCOFFImportFile(const COFFImportFile *File, ScopedPrinter &Writer) { case COFF::IMPORT_NAME_UNDECORATE: Writer.printString("Name type", "undecorate"); break; + case COFF::IMPORT_NAME_EXPORTAS: + Writer.printString("Name type", "export as"); + break; } if (H->getNameType() != COFF::IMPORT_ORDINAL) >From 8b6bc35aa8eddc9ace4d27ef0fc8420351bd79b2 Mon Sep 17 00:00:00 2001 From: Jacek Caban <ja...@codeweavers.com> Date: Sat, 10 Feb 2024 12:46:42 +0100 Subject: [PATCH 3/3] [llvm-lib][Object] Add support for EC importlib symbols. (#81059) ARM64EC import libraries expose two additional symbols: mangled thunk symbol (like `#func`) and auxiliary import symbol (like`__imp_aux_func`). The main functional change with this patch is that those symbols are properly added to static library ECSYMBOLS. --- llvm/include/llvm/Object/COFF.h | 41 +++++ llvm/include/llvm/Object/COFFImportFile.h | 28 +++- llvm/lib/Object/COFFImportFile.cpp | 15 ++ .../AArch64/AArch64Arm64ECCallLowering.cpp | 2 + .../lib/Target/AArch64/AArch64MCInstLower.cpp | 2 + .../Target/AArch64/Utils/AArch64BaseInfo.h | 28 ---- llvm/test/tools/llvm-lib/arm64ec-implib.test | 141 +++++++++++++++++- 7 files changed, 225 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index a548b2c15c5fdc..2a5c3d8913b15c 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -1362,6 +1362,47 @@ class SectionStrippedError SectionStrippedError() { setErrorCode(object_error::section_stripped); } }; +inline std::optional<std::string> +getArm64ECMangledFunctionName(StringRef Name) { + bool IsCppFn = Name[0] == '?'; + if (IsCppFn && Name.find("$$h") != std::string::npos) + return std::nullopt; + if (!IsCppFn && Name[0] == '#') + return std::nullopt; + + StringRef Prefix = "$$h"; + size_t InsertIdx = 0; + if (IsCppFn) { + InsertIdx = Name.find("@@"); + size_t ThreeAtSignsIdx = Name.find("@@@"); + if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) { + InsertIdx += 2; + } else { + InsertIdx = Name.find("@"); + if (InsertIdx != std::string::npos) + InsertIdx++; + } + } else { + Prefix = "#"; + } + + return std::optional<std::string>( + (Name.substr(0, InsertIdx) + Prefix + Name.substr(InsertIdx)).str()); +} + +inline std::optional<std::string> +getArm64ECDemangledFunctionName(StringRef Name) { + if (Name[0] == '#') + return std::string(Name.substr(1)); + if (Name[0] != '?') + return std::nullopt; + + std::pair<StringRef, StringRef> Pair = Name.split("$$h"); + if (Pair.second.empty()) + return std::nullopt; + return (Pair.first + Pair.second).str(); +} + } // end namespace object } // end namespace llvm diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 7c5846e9c044e3..46a982ddb7eee6 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -27,6 +27,9 @@ namespace llvm { namespace object { class COFFImportFile : public SymbolicFile { +private: + enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol }; + public: COFFImportFile(MemoryBufferRef Source) : SymbolicFile(ID_COFFImportFile, Source) {} @@ -36,9 +39,23 @@ class COFFImportFile : public SymbolicFile { void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override { - if (Symb.p == 0) + switch (Symb.p) { + case ImpSymbol: OS << "__imp_"; - OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header)); + 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(); } @@ -52,7 +69,12 @@ class COFFImportFile : public SymbolicFile { basic_symbol_iterator symbol_end() const override { DataRefImpl Symb; - Symb.p = isData() ? 1 : 2; + if (isData()) + Symb.p = ImpSymbol + 1; + else if (COFF::isArm64EC(getMachine())) + Symb.p = ECThunkSymbol + 1; + else + Symb.p = ThunkSymbol + 1; return BasicSymbolRef(Symb, this); } diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 51e6274dcf235c..a3e5e78952c16a 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -684,6 +684,21 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, NameType = getNameType(SymbolName, E.Name, Machine, 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()) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName.swap(Name); + } + Name = std::move(*MangledName); + } else if (ExportName.empty()) { + NameType = IMPORT_NAME_EXPORTAS; + ExportName = std::move(*getArm64ECDemangledFunctionName(Name)); + } + } + Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType, NameType, ExportName, Machine)); } diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp index 11248bb7aef31f..e4449ff9a6aaf9 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -24,11 +24,13 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/InitializePasses.h" +#include "llvm/Object/COFF.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/TargetParser/Triple.h" using namespace llvm; +using namespace llvm::object; using OperandBundleDef = OperandBundleDefT<Value *>; diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp index 1e12cf545fa777..37d621cd2f6580 100644 --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -23,11 +23,13 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" using namespace llvm; +using namespace llvm::object; extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h index 10e69655f77e10..8b32d593d2a812 100644 --- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -248,34 +248,6 @@ static inline bool atomicBarrierDroppedOnZero(unsigned Opcode) { return false; } -static inline std::optional<std::string> -getArm64ECMangledFunctionName(std::string Name) { - bool IsCppFn = Name[0] == '?'; - if (IsCppFn && Name.find("$$h") != std::string::npos) - return std::nullopt; - if (!IsCppFn && Name[0] == '#') - return std::nullopt; - - StringRef Prefix = "$$h"; - size_t InsertIdx = 0; - if (IsCppFn) { - InsertIdx = Name.find("@@"); - size_t ThreeAtSignsIdx = Name.find("@@@"); - if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) { - InsertIdx += 2; - } else { - InsertIdx = Name.find("@"); - if (InsertIdx != std::string::npos) - InsertIdx++; - } - } else { - Prefix = "#"; - } - - Name.insert(Name.begin() + InsertIdx, Prefix.begin(), Prefix.end()); - return std::optional<std::string>(Name); -} - namespace AArch64CC { // The CondCodes constants map directly to the 4-bit encoding of the condition diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 4250c775daa601..c583ef75b2b0aa 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -11,9 +11,23 @@ ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll ARMAP-EMPTY: ARMAP-NEXT: Archive EC map +ARMAP-NEXT: #expname in test.dll +ARMAP-NEXT: #funcexp in test.dll +ARMAP-NEXT: #mangledfunc in test.dll +ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll +ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll +ARMAP-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll +ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll +ARMAP-NEXT: __imp_aux_expname in test.dll +ARMAP-NEXT: __imp_aux_funcexp in test.dll +ARMAP-NEXT: __imp_aux_mangledfunc in test.dll ARMAP-NEXT: __imp_dataexp in test.dll +ARMAP-NEXT: __imp_expname in test.dll ARMAP-NEXT: __imp_funcexp in test.dll +ARMAP-NEXT: __imp_mangledfunc in test.dll +ARMAP-NEXT: expname in test.dll ARMAP-NEXT: funcexp in test.dll +ARMAP-NEXT: mangledfunc in test.dll RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s @@ -35,10 +49,42 @@ READOBJ-EMPTY: READOBJ-NEXT: File: test.dll READOBJ-NEXT: Format: COFF-import-file-ARM64EC READOBJ-NEXT: Type: code -READOBJ-NEXT: Name type: name +READOBJ-NEXT: Name type: export as READOBJ-NEXT: Export name: funcexp READOBJ-NEXT: Symbol: __imp_funcexp READOBJ-NEXT: Symbol: funcexp +READOBJ-NEXT: Symbol: __imp_aux_funcexp +READOBJ-NEXT: Symbol: #funcexp +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: mangledfunc +READOBJ-NEXT: Symbol: __imp_mangledfunc +READOBJ-NEXT: Symbol: mangledfunc +READOBJ-NEXT: Symbol: __imp_aux_mangledfunc +READOBJ-NEXT: Symbol: #mangledfunc +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: ?test_cpp_func@@YAHPEAX@Z +READOBJ-NEXT: Symbol: __imp_?test_cpp_func@@YAHPEAX@Z +READOBJ-NEXT: Symbol: ?test_cpp_func@@YAHPEAX@Z +READOBJ-NEXT: Symbol: __imp_aux_?test_cpp_func@@YAHPEAX@Z +READOBJ-NEXT: Symbol: ?test_cpp_func@@$$hYAHPEAX@Z +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: export as +READOBJ-NEXT: Export name: expname +READOBJ-NEXT: Symbol: __imp_expname +READOBJ-NEXT: Symbol: expname +READOBJ-NEXT: Symbol: __imp_aux_expname +READOBJ-NEXT: Symbol: #expname READOBJ-EMPTY: READOBJ-NEXT: File: test.dll READOBJ-NEXT: Format: COFF-import-file-ARM64EC @@ -51,8 +97,101 @@ Creating a new lib containing the existing lib: RUN: llvm-lib -machine:arm64ec test.lib -out:test2.lib RUN: llvm-nm --print-armap test2.lib | FileCheck -check-prefix=ARMAP %s + +RUN: llvm-lib -machine:arm64ec -def:exportas.def -out:exportas.lib +RUN: llvm-nm --print-armap exportas.lib | FileCheck -check-prefix=EXPAS-ARMAP %s +RUN: llvm-readobj exportas.lib | FileCheck -check-prefix=EXPAS-READOBJ %s + +EXPAS-ARMAP: Archive EC map +EXPAS-ARMAP-NEXT: #func1 in test.dll +EXPAS-ARMAP-NEXT: #func2 in test.dll +EXPAS-ARMAP-NEXT: #func3 in test.dll +EXPAS-ARMAP-NEXT: #func4 in test.dll +EXPAS-ARMAP-NEXT: __imp_aux_func1 in test.dll +EXPAS-ARMAP-NEXT: __imp_aux_func2 in test.dll +EXPAS-ARMAP-NEXT: __imp_aux_func3 in test.dll +EXPAS-ARMAP-NEXT: __imp_aux_func4 in test.dll +EXPAS-ARMAP-NEXT: __imp_data1 in test.dll +EXPAS-ARMAP-NEXT: __imp_data2 in test.dll +EXPAS-ARMAP-NEXT: __imp_func1 in test.dll +EXPAS-ARMAP-NEXT: __imp_func2 in test.dll +EXPAS-ARMAP-NEXT: __imp_func3 in test.dll +EXPAS-ARMAP-NEXT: __imp_func4 in test.dll +EXPAS-ARMAP-NEXT: func1 in test.dll +EXPAS-ARMAP-NEXT: func2 in test.dll +EXPAS-ARMAP-NEXT: func3 in test.dll +EXPAS-ARMAP-NEXT: func4 in test.dll + +EXPAS-READOBJ: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: code +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: func1 +EXPAS-READOBJ-NEXT: Symbol: __imp_func1 +EXPAS-READOBJ-NEXT: Symbol: func1 +EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func1 +EXPAS-READOBJ-NEXT: Symbol: #func1 +EXPAS-READOBJ-EMPTY: +EXPAS-READOBJ-NEXT: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: code +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: func2 +EXPAS-READOBJ-NEXT: Symbol: __imp_func2 +EXPAS-READOBJ-NEXT: Symbol: func2 +EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func2 +EXPAS-READOBJ-NEXT: Symbol: #func2 +EXPAS-READOBJ-EMPTY: +EXPAS-READOBJ-NEXT: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: code +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: #func3 +EXPAS-READOBJ-NEXT: Symbol: __imp_func3 +EXPAS-READOBJ-NEXT: Symbol: func3 +EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func3 +EXPAS-READOBJ-NEXT: Symbol: #func3 +EXPAS-READOBJ-EMPTY: +EXPAS-READOBJ-NEXT: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: code +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: #func4 +EXPAS-READOBJ-NEXT: Symbol: __imp_func4 +EXPAS-READOBJ-NEXT: Symbol: func4 +EXPAS-READOBJ-NEXT: Symbol: __imp_aux_func4 +EXPAS-READOBJ-NEXT: Symbol: #func4 +EXPAS-READOBJ-EMPTY: +EXPAS-READOBJ-NEXT: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: data +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: #data1 +EXPAS-READOBJ-NEXT: Symbol: __imp_data1 +EXPAS-READOBJ-EMPTY: +EXPAS-READOBJ-NEXT: File: test.dll +EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC +EXPAS-READOBJ-NEXT: Type: data +EXPAS-READOBJ-NEXT: Name type: export as +EXPAS-READOBJ-NEXT: Export name: data2 +EXPAS-READOBJ-NEXT: Symbol: __imp_data2 + + #--- test.def LIBRARY test.dll EXPORTS funcexp + #mangledfunc + ?test_cpp_func@@YAHPEAX@Z + expname=impname dataexp DATA + +#--- exportas.def +LIBRARY test.dll +EXPORTS + #func1 EXPORTAS func1 + func2 EXPORTAS func2 + func3 EXPORTAS #func3 + #func4 EXPORTAS #func4 + data1 DATA EXPORTAS #data1 + #data2 DATA EXPORTAS data2 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits