Skip to content

Commit c47a4ef

Browse files
committed
[LLD][COFF] Demangle ARM64EC export names.
1 parent 49839f9 commit c47a4ef

File tree

2 files changed

+150
-16
lines changed

2 files changed

+150
-16
lines changed

lld/COFF/DriverUtils.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <optional>
4040

4141
using namespace llvm::COFF;
42+
using namespace llvm::object;
4243
using namespace llvm::opt;
4344
using namespace llvm;
4445
using llvm::sys::Process;
@@ -632,18 +633,6 @@ Export LinkerDriver::parseExport(StringRef arg) {
632633
fatal("invalid /export: " + arg);
633634
}
634635

635-
static StringRef undecorate(COFFLinkerContext &ctx, StringRef sym) {
636-
if (ctx.config.machine != I386)
637-
return sym;
638-
// In MSVC mode, a fully decorated stdcall function is exported
639-
// as-is with the leading underscore (with type IMPORT_NAME).
640-
// In MinGW mode, a decorated stdcall function gets the underscore
641-
// removed, just like normal cdecl functions.
642-
if (sym.starts_with("_") && sym.contains('@') && !ctx.config.mingw)
643-
return sym;
644-
return sym.starts_with("_") ? sym.substr(1) : sym;
645-
}
646-
647636
// Convert stdcall/fastcall style symbols into unsuffixed symbols,
648637
// with or without a leading underscore. (MinGW specific.)
649638
static StringRef killAt(StringRef sym, bool prefix) {
@@ -693,11 +682,29 @@ void LinkerDriver::fixupExports() {
693682
for (Export &e : ctx.config.exports) {
694683
if (!e.exportAs.empty()) {
695684
e.exportName = e.exportAs;
696-
} else if (!e.forwardTo.empty()) {
697-
e.exportName = undecorate(ctx, e.name);
698-
} else {
699-
e.exportName = undecorate(ctx, e.extName.empty() ? e.name : e.extName);
685+
continue;
686+
}
687+
688+
StringRef sym =
689+
!e.forwardTo.empty() || e.extName.empty() ? e.name : e.extName;
690+
if (ctx.config.machine == I386 && sym.starts_with("_")) {
691+
// In MSVC mode, a fully decorated stdcall function is exported
692+
// as-is with the leading underscore (with type IMPORT_NAME).
693+
// In MinGW mode, a decorated stdcall function gets the underscore
694+
// removed, just like normal cdecl functions.
695+
if (ctx.config.mingw || !sym.contains('@')) {
696+
e.exportName = sym.substr(1);
697+
continue;
698+
}
699+
}
700+
if (isArm64EC(ctx.config.machine) && !e.data && !e.constant) {
701+
if (std::optional<std::string> demangledName =
702+
getArm64ECDemangledFunctionName(sym)) {
703+
e.exportName = saver().save(*demangledName);
704+
continue;
705+
}
700706
}
707+
e.exportName = sym;
701708
}
702709

703710
if (ctx.config.killAt && ctx.config.machine == I386) {

lld/test/COFF/arm64ec-exports.test

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
REQUIRES: aarch64
2+
RUN: split-file %s %t.dir && cd %t.dir
3+
4+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func.s -o func.obj
5+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-mangled.s -o data-mangled.obj
6+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-demangled.s -o data-demangled.obj
7+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve1.s -o drectve1.obj
8+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve2.s -o drectve2.obj
9+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve3.s -o drectve3.obj
10+
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
11+
12+
Check that the export function name is always demangled.
13+
14+
RUN: lld-link -out:func.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec -export:func
15+
RUN: llvm-readobj --coff-exports func.dll | FileCheck %s
16+
RUN: llvm-readobj func.lib | FileCheck --check-prefix=IMPLIB %s
17+
18+
RUN: lld-link -out:func2.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#func,EXPORTAS,func"
19+
RUN: llvm-readobj --coff-exports func2.dll | FileCheck %s
20+
RUN: llvm-readobj func2.lib | FileCheck --check-prefix=IMPLIB %s
21+
22+
RUN: lld-link -out:func3.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#func"
23+
RUN: llvm-readobj --coff-exports func3.dll | FileCheck %s
24+
RUN: llvm-readobj func3.lib | FileCheck --check-prefix=IMPLIB %s
25+
26+
RUN: lld-link -out:func4.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve1.obj
27+
RUN: llvm-readobj --coff-exports func4.dll | FileCheck %s
28+
RUN: llvm-readobj func4.lib | FileCheck --check-prefix=IMPLIB %s
29+
30+
RUN: lld-link -out:func5.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve2.obj
31+
RUN: llvm-readobj --coff-exports func5.dll | FileCheck %s
32+
RUN: llvm-readobj func5.lib | FileCheck --check-prefix=IMPLIB %s
33+
34+
RUN: lld-link -out:func6.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve3.obj
35+
RUN: llvm-readobj --coff-exports func6.dll | FileCheck %s
36+
RUN: llvm-readobj func6.lib | FileCheck --check-prefix=IMPLIB %s
37+
38+
CHECK: Name: func
39+
40+
IMPLIB: File: func{{.*}}.lib(func{{.*}}.dll)
41+
IMPLIB-NEXT: Format: COFF-ARM64
42+
IMPLIB-NEXT: Arch: aarch64
43+
IMPLIB-NEXT: AddressSize: 64bit
44+
IMPLIB-EMPTY:
45+
IMPLIB-NEXT: File: func{{.*}}.lib(func{{.*}}.dll)
46+
IMPLIB-NEXT: Format: COFF-ARM64
47+
IMPLIB-NEXT: Arch: aarch64
48+
IMPLIB-NEXT: AddressSize: 64bit
49+
IMPLIB-EMPTY:
50+
IMPLIB-NEXT: File: func{{.*}}.lib(func{{.*}}.dll)
51+
IMPLIB-NEXT: Format: COFF-ARM64
52+
IMPLIB-NEXT: Arch: aarch64
53+
IMPLIB-NEXT: AddressSize: 64bit
54+
IMPLIB-EMPTY:
55+
IMPLIB-NEXT: File: func{{.*}}.dll
56+
IMPLIB-NEXT: Format: COFF-import-file-ARM64EC
57+
IMPLIB-NEXT: Type: code
58+
IMPLIB-NEXT: Name type: export as
59+
IMPLIB-NEXT: Export name: func
60+
IMPLIB-NEXT: Symbol: __imp_func
61+
IMPLIB-NEXT: Symbol: func
62+
IMPLIB-NEXT: Symbol: __imp_aux_func
63+
IMPLIB-NEXT: Symbol: #func
64+
65+
66+
Check data export name is not demangled.
67+
68+
RUN: lld-link -out:data.dll data-demangled.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec -export:data_sym,DATA
69+
RUN: llvm-readobj --coff-exports data.dll | FileCheck --check-prefix=DATA %s
70+
RUN: llvm-readobj data.lib | FileCheck --check-prefix=DATA-IMPLIB %s
71+
72+
DATA: Name: data_sym
73+
74+
DATA-IMPLIB: Format: COFF-import-file-ARM64EC
75+
DATA-IMPLIB-NEXT: Type: data
76+
DATA-IMPLIB-NEXT: Name type: name
77+
DATA-IMPLIB-NEXT: Export name: data_sym
78+
DATA-IMPLIB-NEXT: Symbol: __imp_data_sym
79+
80+
RUN: lld-link -out:data2.dll data-mangled.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#data_sym,DATA"
81+
RUN: llvm-readobj --coff-exports data2.dll | FileCheck --check-prefix=DATA2 %s
82+
RUN: llvm-readobj data2.lib | FileCheck --check-prefix=DATA2-IMPLIB %s
83+
84+
DATA2: Name: #data_sym
85+
86+
DATA2-IMPLIB: Format: COFF-import-file-ARM64EC
87+
DATA2-IMPLIB-NEXT: Type: data
88+
DATA2-IMPLIB-NEXT: Name type: name
89+
DATA2-IMPLIB-NEXT: Export name: #data_sym
90+
DATA2-IMPLIB-NEXT: Symbol: __imp_data_sym
91+
92+
#--- func.s
93+
.weak_anti_dep func
94+
func = "#func"
95+
96+
.text
97+
.globl "#func"
98+
.p2align 2, 0x0
99+
"#func":
100+
mov w0, #2
101+
ret
102+
103+
#--- data-mangled.s
104+
.data
105+
.globl "#data_sym"
106+
.p2align 2, 0x0
107+
"#data_sym":
108+
.word 0x01010101
109+
110+
#--- data-demangled.s
111+
.data
112+
.globl data_sym
113+
.p2align 2, 0x0
114+
data_sym:
115+
.word 0x01010101
116+
117+
#--- drectve1.s
118+
.section .drectve, "yn"
119+
.ascii " -export:func"
120+
121+
#--- drectve2.s
122+
.section .drectve, "yn"
123+
.ascii " -export:#func"
124+
125+
#--- drectve3.s
126+
.section .drectve, "yn"
127+
.ascii " -export:#func,EXPORTAS,func"

0 commit comments

Comments
 (0)