[lld] [LLD][COFF] Add support for EXPORTAS import name type. (PR #86541)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 26 05:19:54 PDT 2024
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/86541
>From 28ccc2ae9b02ab6364c78c0b0905fd79e99b003d Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Thu, 18 Jan 2024 23:45:45 +0100
Subject: [PATCH] [LLD][COFF] Add support for EXPORTAS import name type.
---
lld/COFF/Config.h | 8 ++--
lld/COFF/Driver.cpp | 2 +
lld/COFF/DriverUtils.cpp | 14 +++++-
lld/test/COFF/exportas.test | 88 +++++++++++++++++++++++++++++++++++++
4 files changed, 106 insertions(+), 6 deletions(-)
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 8f85929f1bea7f..917f88fc28280b 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -54,6 +54,7 @@ enum class EmitKind { Obj, LLVM, ASM };
struct Export {
StringRef name; // N in /export:N or /export:E=N
StringRef extName; // E in /export:E=N
+ StringRef exportAs; // E in /export:N,EXPORTAS,E
StringRef aliasTarget; // GNU specific: N in "alias == N"
Symbol *sym = nullptr;
uint16_t ordinal = 0;
@@ -73,10 +74,9 @@ struct Export {
StringRef exportName; // Name in DLL
bool operator==(const Export &e) const {
- return (name == e.name && extName == e.extName &&
- aliasTarget == e.aliasTarget &&
- ordinal == e.ordinal && noname == e.noname &&
- data == e.data && isPrivate == e.isPrivate);
+ return (name == e.name && extName == e.extName && exportAs == e.exportAs &&
+ aliasTarget == e.aliasTarget && ordinal == e.ordinal &&
+ noname == e.noname && data == e.data && isPrivate == e.isPrivate);
}
};
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 181492913c0d98..2b1d4abb6ed0d6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -945,6 +945,7 @@ void LinkerDriver::createImportLibrary(bool asLib) {
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.AliasTarget = std::string(e1.aliasTarget);
e2.Ordinal = e1.ordinal;
e2.Noname = e1.noname;
@@ -1044,6 +1045,7 @@ void LinkerDriver::parseModuleDefs(StringRef path) {
e2.name = saver().save(e1.Name);
e2.extName = saver().save(e1.ExtName);
}
+ e2.exportAs = saver().save(e1.ExportAs);
e2.aliasTarget = saver().save(e1.AliasTarget);
e2.ordinal = e1.Ordinal;
e2.noname = e1.Noname;
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 0fa4769bab19db..b4ff31a606da5e 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -585,7 +585,8 @@ Export LinkerDriver::parseExport(StringRef arg) {
}
}
- // Optional parameters "[, at ordinal[,NONAME]][,DATA][,PRIVATE]"
+ // Optional parameters
+ // "[, at ordinal[,NONAME]][,DATA][,PRIVATE][,EXPORTAS,exportname]"
while (!rest.empty()) {
StringRef tok;
std::tie(tok, rest) = rest.split(",");
@@ -607,6 +608,13 @@ Export LinkerDriver::parseExport(StringRef arg) {
e.isPrivate = true;
continue;
}
+ if (tok.equals_insensitive("exportas")) {
+ if (!rest.empty() && !rest.contains(','))
+ e.exportAs = rest;
+ else
+ error("invalid EXPORTAS value: " + rest);
+ break;
+ }
if (tok.starts_with("@")) {
int32_t ord;
if (tok.substr(1).getAsInteger(0, ord))
@@ -683,7 +691,9 @@ void LinkerDriver::fixupExports() {
}
for (Export &e : ctx.config.exports) {
- if (!e.forwardTo.empty()) {
+ if (!e.exportAs.empty()) {
+ e.exportName = e.exportAs;
+ } else if (!e.forwardTo.empty()) {
e.exportName = undecorate(ctx, e.name);
} else {
e.exportName = undecorate(ctx, e.extName.empty() ? e.name : e.extName);
diff --git a/lld/test/COFF/exportas.test b/lld/test/COFF/exportas.test
index c0295c3d7fb76d..d70547c39b40b4 100644
--- a/lld/test/COFF/exportas.test
+++ b/lld/test/COFF/exportas.test
@@ -9,6 +9,77 @@ RUN: lld-link -out:out1.dll -dll -noentry test.obj test.lib
RUN: llvm-readobj --coff-imports out1.dll | FileCheck --check-prefix=IMPORT %s
IMPORT: Symbol: expfunc
+Pass -export argument with EXPORTAS.
+
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows func.s -o func.obj
+RUN: lld-link -out:out2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc
+RUN: llvm-readobj --coff-exports out2.dll | FileCheck --check-prefix=EXPORT %s
+EXPORT: Name: expfunc
+
+RUN: llvm-readobj out2.lib | FileCheck --check-prefix=IMPLIB %s
+IMPLIB: Name type: export as
+IMPLIB-NEXT: Export name: expfunc
+IMPLIB-NEXT: Symbol: __imp_func
+IMPLIB-NEXT: Symbol: func
+
+Use .drectve section with EXPORTAS.
+
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows drectve.s -o drectve.obj
+RUN: lld-link -out:out3.dll -dll -noentry func.obj drectve.obj
+RUN: llvm-readobj --coff-exports out3.dll | FileCheck --check-prefix=EXPORT %s
+RUN: llvm-readobj out3.lib | FileCheck --check-prefix=IMPLIB %s
+
+Use a .def file with EXPORTAS.
+
+RUN: lld-link -out:out4.dll -dll -noentry func.obj -def:test.def
+RUN: llvm-readobj --coff-exports out4.dll | FileCheck --check-prefix=EXPORT %s
+RUN: llvm-readobj out4.lib | FileCheck --check-prefix=IMPLIB %s
+
+Use a .def file with EXPORTAS in a forwarding export.
+
+RUN: lld-link -out:out5.dll -dll -noentry func.obj -def:test2.def
+RUN: llvm-readobj --coff-exports out5.dll | FileCheck --check-prefix=FORWARD-EXPORT %s
+FORWARD-EXPORT: Export {
+FORWARD-EXPORT-NEXT: Ordinal: 1
+FORWARD-EXPORT-NEXT: Name: expfunc
+FORWARD-EXPORT-NEXT: ForwardedTo: otherdll.otherfunc
+FORWARD-EXPORT-NEXT: }
+
+RUN: llvm-readobj out5.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s
+FORWARD-IMPLIB: Name type: export as
+FORWARD-IMPLIB-NEXT: Export name: expfunc
+FORWARD-IMPLIB-NEXT: Symbol: __imp_func
+FORWARD-IMPLIB-NEXT: Symbol: func
+
+Pass -export argument with EXPORTAS in a forwarding export.
+
+RUN: lld-link -out:out6.dll -dll -noentry func.obj -export:func=otherdll.otherfunc,EXPORTAS,expfunc
+RUN: llvm-readobj --coff-exports out6.dll | FileCheck --check-prefix=FORWARD-EXPORT %s
+RUN: llvm-readobj out6.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s
+
+Pass -export argument with EXPORTAS in a data export.
+
+RUN: lld-link -out:out7.dll -dll -noentry func.obj -export:func,DATA, at 5,EXPORTAS,expfunc
+RUN: llvm-readobj --coff-exports out7.dll | FileCheck --check-prefix=ORD %s
+ORD: Ordinal: 5
+ORD-NEXT: Name: expfunc
+
+RUN: llvm-readobj out7.lib | FileCheck --check-prefix=ORD-IMPLIB %s
+ORD-IMPLIB: Type: data
+ORD-IMPLIB-NEXT: Name type: export as
+ORD-IMPLIB-NEXT: Export name: expfunc
+ORD-IMPLIB-NEXT: Symbol: __imp_func
+
+Check invalid EXPORTAS syntax.
+
+RUN: not lld-link -out:err1.dll -dll -noentry func.obj -export:func,EXPORTAS, 2>&1 | \
+RUN: FileCheck --check-prefix=ERR1 %s
+ERR1: error: invalid EXPORTAS value: {{$}}
+
+RUN: not lld-link -out:err2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc,DATA 2>&1 | \
+RUN: FileCheck --check-prefix=ERR2 %s
+ERR2: error: invalid EXPORTAS value: expfunc,DATA
+
#--- test.s
.section ".test", "rd"
.rva __imp_func
@@ -17,3 +88,20 @@ IMPORT: Symbol: expfunc
LIBRARY test.dll
EXPORTS
func EXPORTAS expfunc
+
+#--- test2.def
+LIBRARY test.dll
+EXPORTS
+ func=otherdll.otherfunc EXPORTAS expfunc
+
+#--- func.s
+ .text
+ .globl func
+ .p2align 2, 0x0
+func:
+ movl $1, %eax
+ retq
+
+#--- drectve.s
+ .section .drectve, "yn"
+ .ascii " -export:func,EXPORTAS,expfunc"
More information about the llvm-commits
mailing list