Skip to content

Commit 1dbe8a6

Browse files
committed
[LLD][COFF] Add support for EXPORTAS import name type.
FIXME: Split general export parsing fixes.
1 parent 454097c commit 1dbe8a6

File tree

5 files changed

+122
-8
lines changed

5 files changed

+122
-8
lines changed

lld/COFF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct Export {
6161
bool data = false;
6262
bool isPrivate = false;
6363
bool constant = false;
64+
bool exportAs = false;
6465

6566
// If an export is a form of /export:foo=dllname.bar, that means
6667
// that foo should be exported as an alias to bar in the DLL.

lld/COFF/Driver.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,10 @@ void LinkerDriver::createImportLibrary(bool asLib) {
944944
COFFShortExport e2;
945945
e2.Name = std::string(e1.name);
946946
e2.SymbolName = std::string(e1.symbolName);
947-
e2.ExtName = std::string(e1.extName);
947+
if (e1.exportAs)
948+
e2.ExportAs = std::string(e1.exportName);
949+
else
950+
e2.ExtName = std::string(e1.extName);
948951
e2.AliasTarget = std::string(e1.aliasTarget);
949952
e2.Ordinal = e1.ordinal;
950953
e2.Noname = e1.noname;
@@ -1040,11 +1043,20 @@ void LinkerDriver::parseModuleDefs(StringRef path) {
10401043
StringRef(e1.Name).contains('.')) {
10411044
e2.name = saver().save(e1.ExtName);
10421045
e2.forwardTo = saver().save(e1.Name);
1046+
if (!e1.ExportAs.empty()) {
1047+
e2.extName = e2.exportName = saver().save(e1.ExportAs);
1048+
e2.exportAs = true;
1049+
}
10431050
ctx.config.exports.push_back(e2);
10441051
continue;
10451052
}
10461053
e2.name = saver().save(e1.Name);
1047-
e2.extName = saver().save(e1.ExtName);
1054+
if (e1.ExportAs.empty()) {
1055+
e2.extName = saver().save(e1.ExtName);
1056+
} else {
1057+
e2.extName = e2.exportName = saver().save(e1.ExportAs);
1058+
e2.exportAs = true;
1059+
}
10481060
e2.aliasTarget = saver().save(e1.AliasTarget);
10491061
e2.ordinal = e1.Ordinal;
10501062
e2.noname = e1.Noname;

lld/COFF/DriverUtils.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -577,11 +577,10 @@ Export LinkerDriver::parseExport(StringRef arg) {
577577
if (y.contains(".")) {
578578
e.name = x;
579579
e.forwardTo = y;
580-
return e;
580+
} else {
581+
e.extName = x;
582+
e.name = y;
581583
}
582-
583-
e.extName = x;
584-
e.name = y;
585584
if (e.name.empty())
586585
goto err;
587586
}
@@ -608,6 +607,13 @@ Export LinkerDriver::parseExport(StringRef arg) {
608607
e.isPrivate = true;
609608
continue;
610609
}
610+
if (tok.equals_insensitive("exportas")) {
611+
if (rest.empty() || rest.contains(','))
612+
goto err;
613+
e.extName = e.exportName = rest;
614+
e.exportAs = true;
615+
break;
616+
}
611617
if (tok.starts_with("@")) {
612618
int32_t ord;
613619
if (tok.substr(1).getAsInteger(0, ord))
@@ -684,6 +690,8 @@ void LinkerDriver::fixupExports() {
684690
}
685691

686692
for (Export &e : ctx.config.exports) {
693+
if (!e.exportName.empty())
694+
continue;
687695
if (!e.forwardTo.empty()) {
688696
e.exportName = undecorate(ctx, e.name);
689697
} else {
@@ -694,8 +702,10 @@ void LinkerDriver::fixupExports() {
694702
if (ctx.config.killAt && ctx.config.machine == I386) {
695703
for (Export &e : ctx.config.exports) {
696704
e.name = killAt(e.name, true);
697-
e.exportName = killAt(e.exportName, false);
698-
e.extName = killAt(e.extName, true);
705+
if (!e.exportAs) {
706+
e.exportName = killAt(e.exportName, false);
707+
e.extName = killAt(e.extName, true);
708+
}
699709
e.symbolName = killAt(e.symbolName, true);
700710
}
701711
}

lld/COFF/InputFiles.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,9 @@ void ImportFile::parse() {
971971
extName = ltrim1(name, "?@_");
972972
extName = extName.substr(0, extName.find('@'));
973973
break;
974+
case IMPORT_NAME_EXPORTAS:
975+
extName = StringRef(nameStart + dllName.size() + 1);
976+
break;
974977
}
975978

976979
this->hdr = hdr;

lld/test/COFF/exportas.test

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
REQUIRES: x86
2+
RUN: split-file %s %t.dir && cd %t.dir
3+
4+
RUN: llvm-mc -filetype=obj -triple=x86_64-windows test.s -o test.obj
5+
RUN: llvm-lib -machine:amd64 -out:test.lib -def:test.def
6+
RUN: lld-link -out:out1.dll -dll -noentry test.obj test.lib
7+
RUN: llvm-readobj --coff-imports out1.dll | FileCheck --check-prefix=IMPORT %s
8+
IMPORT: Symbol: expfunc
9+
10+
RUN: llvm-mc -filetype=obj -triple=x86_64-windows func.s -o func.obj
11+
RUN: lld-link -out:out2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc
12+
RUN: llvm-readobj --coff-exports out2.dll | FileCheck --check-prefix=EXPORT %s
13+
EXPORT: Name: expfunc
14+
15+
RUN: llvm-readobj out2.lib | FileCheck --check-prefix=IMPLIB %s
16+
IMPLIB: Name type: export as
17+
IMPLIB-NEXT: Export name: expfunc
18+
IMPLIB-NEXT: Symbol: __imp_func
19+
IMPLIB-NEXT: Symbol: func
20+
21+
RUN: llvm-mc -filetype=obj -triple=x86_64-windows drectve.s -o drectve.obj
22+
RUN: lld-link -out:out3.dll -dll -noentry func.obj drectve.obj
23+
RUN: llvm-readobj --coff-exports out3.dll | FileCheck --check-prefix=EXPORT %s
24+
RUN: llvm-readobj out3.lib | FileCheck --check-prefix=IMPLIB %s
25+
26+
RUN: lld-link -out:out4.dll -dll -noentry func.obj -def:test.def
27+
RUN: llvm-readobj --coff-exports out4.dll | FileCheck --check-prefix=EXPORT %s
28+
RUN: llvm-readobj out4.lib | FileCheck --check-prefix=IMPLIB %s
29+
30+
RUN: lld-link -out:out5.dll -dll -noentry func.obj -def:test2.def
31+
RUN: llvm-readobj --coff-exports out5.dll | FileCheck --check-prefix=FORWARD-EXPORT %s
32+
FORWARD-EXPORT: Export {
33+
FORWARD-EXPORT-NEXT: Ordinal: 1
34+
FORWARD-EXPORT-NEXT: Name: expfunc
35+
FORWARD-EXPORT-NEXT: ForwardedTo: otherdll.otherfunc
36+
FORWARD-EXPORT-NEXT: }
37+
38+
RUN: llvm-readobj out5.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s
39+
FORWARD-IMPLIB: Name type: export as
40+
FORWARD-IMPLIB-NEXT: Export name: expfunc
41+
FORWARD-IMPLIB-NEXT: Symbol: __imp_func
42+
FORWARD-IMPLIB-NEXT: Symbol: func
43+
44+
RUN: lld-link -out:out6.dll -dll -noentry func.obj -export:func=otherdll.otherfunc,EXPORTAS,expfunc
45+
RUN: llvm-readobj --coff-exports out6.dll | FileCheck --check-prefix=FORWARD-EXPORT %s
46+
RUN: llvm-readobj out6.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s
47+
48+
49+
RUN: lld-link -out:out7.dll -dll -noentry func.obj -export:func,DATA,@5,EXPORTAS,expfunc
50+
RUN: llvm-readobj --coff-exports out7.dll | FileCheck --check-prefix=ORD %s
51+
ORD: Ordinal: 5
52+
ORD-NEXT: Name: expfunc
53+
54+
RUN: llvm-readobj out7.lib | FileCheck --check-prefix=ORD-IMPLIB %s
55+
ORD-IMPLIB: Type: data
56+
ORD-IMPLIB-NEXT: Name type: export as
57+
ORD-IMPLIB-NEXT: Export name: expfunc
58+
ORD-IMPLIB-NEXT: Symbol: __imp_func
59+
60+
61+
RUN: not lld-link -out:err.dll -dll -noentry func.obj "-export:func,EXPORTAS,"
62+
RUN: not lld-link -out:err.dll -dll -noentry func.obj "-export:func,EXPORTAS,expfunc,DATA"
63+
64+
#--- test.s
65+
.section ".test", "rd"
66+
.rva __imp_func
67+
68+
#--- test.def
69+
LIBRARY test.dll
70+
EXPORTS
71+
func EXPORTAS expfunc
72+
73+
#--- test2.def
74+
LIBRARY test.dll
75+
EXPORTS
76+
func=otherdll.otherfunc EXPORTAS expfunc
77+
78+
#--- func.s
79+
.text
80+
.globl func
81+
.p2align 2, 0x0
82+
func:
83+
movl $1, %eax
84+
retq
85+
86+
#--- drectve.s
87+
.section .drectve, "yn"
88+
.ascii " -export:func,EXPORTAS,expfunc"

0 commit comments

Comments
 (0)