diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index ac3ac57bd17f4..b848e0d81dfa7 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -954,20 +954,31 @@ std::string LinkerDriver::getImportName(bool asLib) { void LinkerDriver::createImportLibrary(bool asLib) { llvm::TimeTraceScope timeScope("Create import library"); - std::vector exports; - for (Export &e1 : ctx.symtab.exports) { - COFFShortExport e2; - e2.Name = std::string(e1.name); - e2.SymbolName = std::string(e1.symbolName); - e2.ExtName = std::string(e1.extName); - e2.ExportAs = std::string(e1.exportAs); - e2.ImportName = std::string(e1.importName); - e2.Ordinal = e1.ordinal; - e2.Noname = e1.noname; - e2.Data = e1.data; - e2.Private = e1.isPrivate; - e2.Constant = e1.constant; - exports.push_back(e2); + std::vector exports, nativeExports; + + auto getExports = [](SymbolTable &symtab, + std::vector &exports) { + for (Export &e1 : symtab.exports) { + COFFShortExport e2; + e2.Name = std::string(e1.name); + e2.SymbolName = std::string(e1.symbolName); + e2.ExtName = std::string(e1.extName); + e2.ExportAs = std::string(e1.exportAs); + e2.ImportName = std::string(e1.importName); + e2.Ordinal = e1.ordinal; + e2.Noname = e1.noname; + e2.Data = e1.data; + e2.Private = e1.isPrivate; + e2.Constant = e1.constant; + exports.push_back(e2); + } + }; + + if (ctx.hybridSymtab) { + getExports(ctx.symtab, nativeExports); + getExports(*ctx.hybridSymtab, exports); + } else { + getExports(ctx.symtab, exports); } std::string libName = getImportName(asLib); @@ -975,7 +986,7 @@ void LinkerDriver::createImportLibrary(bool asLib) { if (!ctx.config.incremental) { checkError(writeImportLibrary(libName, path, exports, ctx.config.machine, - ctx.config.mingw)); + ctx.config.mingw, nativeExports)); return; } @@ -985,7 +996,7 @@ void LinkerDriver::createImportLibrary(bool asLib) { path, /*IsText=*/false, /*RequiresNullTerminator=*/false); if (!oldBuf) { checkError(writeImportLibrary(libName, path, exports, ctx.config.machine, - ctx.config.mingw)); + ctx.config.mingw, nativeExports)); return; } @@ -995,8 +1006,9 @@ void LinkerDriver::createImportLibrary(bool asLib) { Fatal(ctx) << "cannot create temporary file for import library " << path << ": " << ec.message(); - if (Error e = writeImportLibrary(libName, tmpName, exports, - ctx.config.machine, ctx.config.mingw)) { + if (Error e = + writeImportLibrary(libName, tmpName, exports, ctx.config.machine, + ctx.config.mingw, nativeExports)) { checkError(std::move(e)); return; } @@ -2668,7 +2680,8 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. In MinGW mode, we only do that when the // -implib option is given explicitly, for compatibility with GNU ld. - if (!ctx.symtab.exports.empty() || config->dll) { + if (config->dll || !ctx.symtab.exports.empty() || + (ctx.hybridSymtab && !ctx.hybridSymtab->exports.empty())) { llvm::TimeTraceScope timeScope("Create .lib exports"); ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); }); if (!config->noimplib && (!config->mingw || !config->implib.empty())) diff --git a/lld/test/COFF/arm64x-export.test b/lld/test/COFF/arm64x-export.test index 3ae0725a67089..bae40af4585ae 100644 --- a/lld/test/COFF/arm64x-export.test +++ b/lld/test/COFF/arm64x-export.test @@ -48,12 +48,40 @@ EXPORTS-EC-NEXT: RVA: 0x2000 EXPORTS-EC-NEXT: } EXPORTS-EC-NEXT: } +RUN: llvm-readobj out-cmd.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s +IMPLIB-HEADER: File: out-{{.*}}.lib(out{{.*}}.dll) +IMPLIB-HEADER-NEXT: Format: COFF-ARM64 +IMPLIB-HEADER-NEXT: Arch: aarch64 +IMPLIB-HEADER-NEXT: AddressSize: 64bit +IMPLIB-HEADER-EMPTY: +IMPLIB-HEADER-NEXT: File: out-{{.*}}.lib(out{{.*}}.dll) +IMPLIB-HEADER-NEXT: Format: COFF-ARM64 +IMPLIB-HEADER-NEXT: Arch: aarch64 +IMPLIB-HEADER-NEXT: AddressSize: 64bit +IMPLIB-HEADER-EMPTY: +IMPLIB-HEADER-NEXT: File: out-{{.*}}.lib(out{{.*}}.dll) +IMPLIB-HEADER-NEXT: Format: COFF-ARM64 +IMPLIB-HEADER-NEXT: Arch: aarch64 +IMPLIB-HEADER-NEXT: AddressSize: 64bit +IMPLIB-HEADER-EMPTY: +IMPLIB-EC: File: out{{.*}}.dll +IMPLIB-EC-NEXT: Format: COFF-import-file-ARM64EC +IMPLIB-EC-NEXT: Type: code +IMPLIB-EC-NEXT: Name type: export as +IMPLIB-EC-NEXT: Export name: func +IMPLIB-EC-NEXT: Symbol: __imp_func +IMPLIB-EC-NEXT: Symbol: func +IMPLIB-EC-NEXT: Symbol: __imp_aux_func +IMPLIB-EC-NEXT: Symbol: #func + + # Export using the EC .drectve section. RUN: lld-link -machine:arm64x -dll -out:out-drectve-ec.dll arm64ec-func.obj arm64-func.obj \ RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj arm64ec-drectve.obj -noentry RUN: llvm-objdump -d out-drectve-ec.dll | FileCheck --check-prefix=DISASM-EC %s RUN: llvm-readobj --headers --coff-exports out-drectve-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s +RUN: llvm-readobj out-drectve-ec.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s # A command-line def file applies only to EC exports. @@ -61,6 +89,7 @@ RUN: lld-link -machine:arm64x -dll -out:out-def-ec.dll arm64ec-func.obj arm64-fu RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -def:func.def -noentry RUN: llvm-objdump -d out-def-ec.dll | FileCheck --check-prefix=DISASM-EC %s RUN: llvm-readobj --headers --coff-exports out-def-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s +RUN: llvm-readobj out-def-ec.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s # Export using the EC .edata section. @@ -111,6 +140,15 @@ EXPORTS-NATIVE: ExportTableRVA: 0x0 EXPORTS-NATIVE-NEXT: ExportTableSize: 0x0 EXPORTS-NATIVE-NOT: Name: func +RUN: llvm-readobj out-drectve-native.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-NATIVE %s +IMPLIB-NATIVE: File: out{{.*}}.dll +IMPLIB-NATIVE-NEXT: Format: COFF-import-file-ARM64 +IMPLIB-NATIVE-NEXT: Type: code +IMPLIB-NATIVE-NEXT: Name type: name +IMPLIB-NATIVE-NEXT: Export name: func +IMPLIB-NATIVE-NEXT: Symbol: __imp_func +IMPLIB-NATIVE-NEXT: Symbol: func + # Export using the native .edata section. RUN: lld-link -machine:arm64x -dll -out:out-edata.dll arm64ec-func.obj arm64-func.obj \ @@ -162,12 +200,15 @@ EXPORTS-BOTH-NEXT: RVA: 0x3000 EXPORTS-BOTH-NEXT: } EXPORTS-BOTH-NEXT: } +RUN: llvm-readobj out-both.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC,IMPLIB-NATIVE %s + # Export using both the -def and -defarm64native arguments. RUN: lld-link -machine:arm64x -dll -out:out-def-both.dll arm64ec-func.obj arm64-func.obj \ RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -def:func.def -defarm64native:func.def -noentry RUN: llvm-objdump -d out-def-both.dll | FileCheck --check-prefix=DISASM-BOTH %s RUN: llvm-readobj --headers --coff-exports out-def-both.dll | FileCheck --check-prefix=EXPORTS-BOTH %s +RUN: llvm-readobj out-def-both.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC,IMPLIB-NATIVE %s # -defarm64native is ignored if -def is not specified.