[lld] [LLD][COFF] Demangle ARM64EC export names. (PR #87068)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 29 06:59:34 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld

Author: Jacek Caban (cjacek)

<details>
<summary>Changes</summary>

This is compatible with MSVC. It matters when export is passed in mangled form (like -export:#func), it doesn't change handling of demangled form and explicit EXPORTAS cases. This form is currently used by clang, until #<!-- -->81940 lands.

When undecorating, we need a way to check if the export is a function, so using the current form of `undecorate()` isn't enough. With a bit tweaked logic, it felt more appropriate to just inline that helper instead of extending it.

---
Full diff: https://github.com/llvm/llvm-project/pull/87068.diff


2 Files Affected:

- (modified) lld/COFF/DriverUtils.cpp (+23-16) 
- (added) lld/test/COFF/arm64ec-exports.test (+127) 


``````````diff
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index b4ff31a606da5e..d66e381d7b30a9 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -39,6 +39,7 @@
 #include <optional>
 
 using namespace llvm::COFF;
+using namespace llvm::object;
 using namespace llvm::opt;
 using namespace llvm;
 using llvm::sys::Process;
@@ -632,18 +633,6 @@ Export LinkerDriver::parseExport(StringRef arg) {
   fatal("invalid /export: " + arg);
 }
 
-static StringRef undecorate(COFFLinkerContext &ctx, StringRef sym) {
-  if (ctx.config.machine != I386)
-    return sym;
-  // In MSVC mode, a fully decorated stdcall function is exported
-  // as-is with the leading underscore (with type IMPORT_NAME).
-  // In MinGW mode, a decorated stdcall function gets the underscore
-  // removed, just like normal cdecl functions.
-  if (sym.starts_with("_") && sym.contains('@') && !ctx.config.mingw)
-    return sym;
-  return sym.starts_with("_") ? sym.substr(1) : sym;
-}
-
 // Convert stdcall/fastcall style symbols into unsuffixed symbols,
 // with or without a leading underscore. (MinGW specific.)
 static StringRef killAt(StringRef sym, bool prefix) {
@@ -693,11 +682,29 @@ void LinkerDriver::fixupExports() {
   for (Export &e : ctx.config.exports) {
     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);
+      continue;
+    }
+
+    StringRef sym =
+        !e.forwardTo.empty() || e.extName.empty() ? e.name : e.extName;
+    if (ctx.config.machine == I386 && sym.starts_with("_")) {
+      // In MSVC mode, a fully decorated stdcall function is exported
+      // as-is with the leading underscore (with type IMPORT_NAME).
+      // In MinGW mode, a decorated stdcall function gets the underscore
+      // removed, just like normal cdecl functions.
+      if (ctx.config.mingw || !sym.contains('@')) {
+        e.exportName = sym.substr(1);
+        continue;
+      }
+    }
+    if (isArm64EC(ctx.config.machine) && !e.data && !e.constant) {
+      if (std::optional<std::string> demangledName =
+              getArm64ECDemangledFunctionName(sym)) {
+        e.exportName = saver().save(*demangledName);
+        continue;
+      }
     }
+    e.exportName = sym;
   }
 
   if (ctx.config.killAt && ctx.config.machine == I386) {
diff --git a/lld/test/COFF/arm64ec-exports.test b/lld/test/COFF/arm64ec-exports.test
new file mode 100644
index 00000000000000..d636d04ee06cca
--- /dev/null
+++ b/lld/test/COFF/arm64ec-exports.test
@@ -0,0 +1,127 @@
+REQUIRES: aarch64
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func.s -o func.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-mangled.s -o data-mangled.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-demangled.s -o data-demangled.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve1.s -o drectve1.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve2.s -o drectve2.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve3.s -o drectve3.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+
+Check that the export function name is always demangled.
+
+RUN: lld-link -out:func.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec -export:func
+RUN: llvm-readobj --coff-exports func.dll | FileCheck %s
+RUN: llvm-readobj func.lib | FileCheck --check-prefix=IMPLIB %s
+
+RUN: lld-link -out:func2.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#func,EXPORTAS,func"
+RUN: llvm-readobj --coff-exports func2.dll | FileCheck %s
+RUN: llvm-readobj func2.lib | FileCheck --check-prefix=IMPLIB %s
+
+RUN: lld-link -out:func3.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#func"
+RUN: llvm-readobj --coff-exports func3.dll | FileCheck %s
+RUN: llvm-readobj func3.lib | FileCheck --check-prefix=IMPLIB %s
+
+RUN: lld-link -out:func4.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve1.obj
+RUN: llvm-readobj --coff-exports func4.dll | FileCheck %s
+RUN: llvm-readobj func4.lib | FileCheck --check-prefix=IMPLIB %s
+
+RUN: lld-link -out:func5.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve2.obj
+RUN: llvm-readobj --coff-exports func5.dll | FileCheck %s
+RUN: llvm-readobj func5.lib | FileCheck --check-prefix=IMPLIB %s
+
+RUN: lld-link -out:func6.dll func.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec drectve3.obj
+RUN: llvm-readobj --coff-exports func6.dll | FileCheck %s
+RUN: llvm-readobj func6.lib | FileCheck --check-prefix=IMPLIB %s
+
+CHECK: Name: func
+
+IMPLIB:      File: func{{.*}}.lib(func{{.*}}.dll)
+IMPLIB-NEXT: Format: COFF-ARM64
+IMPLIB-NEXT: Arch: aarch64
+IMPLIB-NEXT: AddressSize: 64bit
+IMPLIB-EMPTY:
+IMPLIB-NEXT: File: func{{.*}}.lib(func{{.*}}.dll)
+IMPLIB-NEXT: Format: COFF-ARM64
+IMPLIB-NEXT: Arch: aarch64
+IMPLIB-NEXT: AddressSize: 64bit
+IMPLIB-EMPTY:
+IMPLIB-NEXT: File: func{{.*}}.lib(func{{.*}}.dll)
+IMPLIB-NEXT: Format: COFF-ARM64
+IMPLIB-NEXT: Arch: aarch64
+IMPLIB-NEXT: AddressSize: 64bit
+IMPLIB-EMPTY:
+IMPLIB-NEXT: File: func{{.*}}.dll
+IMPLIB-NEXT: Format: COFF-import-file-ARM64EC
+IMPLIB-NEXT: Type: code
+IMPLIB-NEXT: Name type: export as
+IMPLIB-NEXT: Export name: func
+IMPLIB-NEXT: Symbol: __imp_func
+IMPLIB-NEXT: Symbol: func
+IMPLIB-NEXT: Symbol: __imp_aux_func
+IMPLIB-NEXT: Symbol: #func
+
+
+Check data export name is not demangled.
+
+RUN: lld-link -out:data.dll data-demangled.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec -export:data_sym,DATA
+RUN: llvm-readobj --coff-exports data.dll | FileCheck --check-prefix=DATA %s
+RUN: llvm-readobj data.lib | FileCheck --check-prefix=DATA-IMPLIB %s
+
+DATA: Name: data_sym
+
+DATA-IMPLIB:      Format: COFF-import-file-ARM64EC
+DATA-IMPLIB-NEXT: Type: data
+DATA-IMPLIB-NEXT: Name type: name
+DATA-IMPLIB-NEXT: Export name: data_sym
+DATA-IMPLIB-NEXT: Symbol: __imp_data_sym
+
+RUN: lld-link -out:data2.dll data-mangled.obj loadconfig-arm64ec.obj -dll -noentry -machine:arm64ec "-export:#data_sym,DATA"
+RUN: llvm-readobj --coff-exports data2.dll | FileCheck --check-prefix=DATA2 %s
+RUN: llvm-readobj data2.lib | FileCheck --check-prefix=DATA2-IMPLIB %s
+
+DATA2: Name: #data_sym
+
+DATA2-IMPLIB:      Format: COFF-import-file-ARM64EC
+DATA2-IMPLIB-NEXT: Type: data
+DATA2-IMPLIB-NEXT: Name type: name
+DATA2-IMPLIB-NEXT: Export name: #data_sym
+DATA2-IMPLIB-NEXT: Symbol: __imp_data_sym
+
+#--- func.s
+    .weak_anti_dep func
+    func = "#func"
+
+    .text
+    .globl "#func"
+    .p2align 2, 0x0
+"#func":
+    mov w0, #2
+    ret
+
+#--- data-mangled.s
+    .data
+    .globl "#data_sym"
+    .p2align 2, 0x0
+"#data_sym":
+    .word 0x01010101
+
+#--- data-demangled.s
+    .data
+    .globl data_sym
+    .p2align 2, 0x0
+data_sym:
+    .word 0x01010101
+
+#--- drectve1.s
+    .section .drectve, "yn"
+    .ascii " -export:func"
+
+#--- drectve2.s
+    .section .drectve, "yn"
+    .ascii " -export:#func"
+
+#--- drectve3.s
+    .section .drectve, "yn"
+    .ascii " -export:#func,EXPORTAS,func"

``````````

</details>


https://github.com/llvm/llvm-project/pull/87068


More information about the llvm-commits mailing list