[lld] 4d4a43d - [LLD][COFF] Create EC alias symbols for entry points and exports (#114297)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 31 10:05:57 PDT 2024
Author: Jacek Caban
Date: 2024-10-31T18:05:54+01:00
New Revision: 4d4a43dc51a5e138bb07ef0481ca8f724561444d
URL: https://github.com/llvm/llvm-project/commit/4d4a43dc51a5e138bb07ef0481ca8f724561444d
DIFF: https://github.com/llvm/llvm-project/commit/4d4a43dc51a5e138bb07ef0481ca8f724561444d.diff
LOG: [LLD][COFF] Create EC alias symbols for entry points and exports (#114297)
On ARM64EC, a symbol may be defined in either its mangled or demangled
form (or both). To ensure consistent linking for entry points and
exports, define an anti-dependency symbol that binds both forms, similar
to how compiler-generated code references external functions.
Added:
lld/test/COFF/arm64ec-entry-mangle.test
Modified:
lld/COFF/Driver.cpp
lld/COFF/Driver.h
lld/test/COFF/arm64ec-delayimport.test
Removed:
################################################################################
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 08c1476a595f64..d717afac473898 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -415,7 +415,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
case OPT_entry:
if (!arg->getValue()[0])
fatal("missing entry point symbol name");
- ctx.config.entry = addUndefined(mangle(arg->getValue()));
+ ctx.config.entry = addUndefined(mangle(arg->getValue()), true);
break;
case OPT_failifmismatch:
checkFailIfMismatch(arg->getValue(), file);
@@ -696,12 +696,33 @@ void LinkerDriver::addLibSearchPaths() {
}
}
-Symbol *LinkerDriver::addUndefined(StringRef name) {
+Symbol *LinkerDriver::addUndefined(StringRef name, bool aliasEC) {
Symbol *b = ctx.symtab.addUndefined(name);
if (!b->isGCRoot) {
b->isGCRoot = true;
ctx.config.gcroot.push_back(b);
}
+
+ // On ARM64EC, a symbol may be defined in either its mangled or demangled form
+ // (or both). Define an anti-dependency symbol that binds both forms, similar
+ // to how compiler-generated code references external functions.
+ if (aliasEC && isArm64EC(ctx.config.machine)) {
+ if (std::optional<std::string> mangledName =
+ getArm64ECMangledFunctionName(name)) {
+ auto u = dyn_cast<Undefined>(b);
+ if (u && !u->weakAlias) {
+ Symbol *t = ctx.symtab.addUndefined(saver().save(*mangledName));
+ u->setWeakAlias(t, true);
+ }
+ } else {
+ std::optional<std::string> demangledName =
+ getArm64ECDemangledFunctionName(name);
+ Symbol *us = ctx.symtab.addUndefined(saver().save(*demangledName));
+ auto u = dyn_cast<Undefined>(us);
+ if (u && !u->weakAlias)
+ u->setWeakAlias(b, true);
+ }
+ }
return b;
}
@@ -2342,22 +2363,22 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (auto *arg = args.getLastArg(OPT_entry)) {
if (!arg->getValue()[0])
fatal("missing entry point symbol name");
- config->entry = addUndefined(mangle(arg->getValue()));
+ config->entry = addUndefined(mangle(arg->getValue()), true);
} else if (!config->entry && !config->noEntry) {
if (args.hasArg(OPT_dll)) {
StringRef s = (config->machine == I386) ? "__DllMainCRTStartup at 12"
: "_DllMainCRTStartup";
- config->entry = addUndefined(s);
+ config->entry = addUndefined(s, true);
} else if (config->driverWdm) {
// /driver:wdm implies /entry:_NtProcessStartup
- config->entry = addUndefined(mangle("_NtProcessStartup"));
+ config->entry = addUndefined(mangle("_NtProcessStartup"), true);
} else {
// Windows specific -- If entry point name is not given, we need to
// infer that from user-defined entry name.
StringRef s = findDefaultEntry();
if (s.empty())
fatal("entry point must be defined");
- config->entry = addUndefined(s);
+ config->entry = addUndefined(s, true);
log("Entry name inferred: " + s);
}
}
@@ -2371,7 +2392,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (config->machine == I386) {
config->delayLoadHelper = addUndefined("___delayLoadHelper2 at 8");
} else {
- config->delayLoadHelper = addUndefined("__delayLoadHelper2");
+ config->delayLoadHelper = addUndefined("__delayLoadHelper2", true);
}
}
}
@@ -2505,7 +2526,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
for (Export &e : config->exports) {
if (!e.forwardTo.empty())
continue;
- e.sym = addUndefined(e.name);
+ e.sym = addUndefined(e.name, !e.data);
if (e.source != ExportSource::Directives)
e.symbolName = mangleMaybe(e.sym);
}
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 58a2ed23106243..3889feb7511c0a 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -170,7 +170,7 @@ class LinkerDriver {
std::set<std::string> visitedLibs;
- Symbol *addUndefined(StringRef sym);
+ Symbol *addUndefined(StringRef sym, bool aliasEC = false);
void addUndefinedGlob(StringRef arg);
diff --git a/lld/test/COFF/arm64ec-delayimport.test b/lld/test/COFF/arm64ec-delayimport.test
index a0236d902eeaba..6797d84e088686 100644
--- a/lld/test/COFF/arm64ec-delayimport.test
+++ b/lld/test/COFF/arm64ec-delayimport.test
@@ -2,12 +2,14 @@ REQUIRES: aarch64, x86
RUN: split-file %s %t.dir && cd %t.dir
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows helper-mangled.s -o helper-mangled.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows helper-demangled.s -o helper-demangled.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
RUN: llvm-lib -machine:arm64ec -def:test.def -out:test-arm64ec.lib
RUN: llvm-lib -machine:arm64ec -def:test2.def -out:test2-arm64ec.lib
RUN: lld-link -machine:arm64ec -dll -noentry -out:out.dll loadconfig-arm64ec.obj test.obj \
-RUN: test-arm64ec.lib test2-arm64ec.lib -delayload:test.dll -map
+RUN: helper-mangled.obj test-arm64ec.lib test2-arm64ec.lib -delayload:test.dll -map
RUN: llvm-readobj --hex-dump=.test out.dll | FileCheck --check-prefix=TESTSEC %s
TESTSEC: 0x180008000 00600000 88700000 00200000 10100000
@@ -97,7 +99,7 @@ IMPORTS-NEXT: }
IMPORTS-NEXT: }
RUN: FileCheck --check-prefix=MAP %s < out.map
-MAP: 0001:00000008 #__delayLoadHelper2 0000000180001008 test.obj
+MAP: 0001:00000008 #__delayLoadHelper2 0000000180001008 helper-mangled.obj
MAP: 0001:00000010 #func 0000000180001010 test-arm64ec:test.dll
MAP-NEXT: 0001:0000001c __impchk_func 000000018000101c test-arm64ec:test.dll
MAP-NEXT: 0001:00000030 #func2 0000000180001030 test-arm64ec:test.dll
@@ -138,6 +140,21 @@ RELOC-NEXT: Type: DIR64
RELOC-NEXT: Address: 0x6008
RELOC-NEXT: }
+Verify that a demangled version of __delayLoadHelper2 can be used.
+
+RUN: lld-link -machine:arm64ec -dll -noentry -out:out2.dll loadconfig-arm64ec.obj test.obj \
+RUN: helper-demangled.obj test-arm64ec.lib test2-arm64ec.lib -delayload:test.dll
+RUN: llvm-objdump -d out2.dll | FileCheck --check-prefix=DISASM %s
+
+Verify that the mangled version of __delayLoadHelper2 can be used from a library.
+Even if an anti-dependency alias is defined by the helper, it won't appear in
+the archive index, so we need to locate it by its mangled name.
+
+RUN: llvm-lib -machine:arm64ec -out:helper.lib helper-mangled.obj
+RUN: lld-link -machine:arm64ec -dll -noentry -out:out3.dll loadconfig-arm64ec.obj test.obj \
+RUN: helper.lib test-arm64ec.lib test2-arm64ec.lib -delayload:test.dll
+RUN: llvm-objdump -d out3.dll | FileCheck --check-prefix=DISASM %s
+
#--- test.s
.section .test,"r"
.rva __imp_func
@@ -159,16 +176,6 @@ __icall_helper_arm64ec:
mov w0, #0
ret
- .section .text,"xr",discard,"#__delayLoadHelper2"
- .globl "#__delayLoadHelper2"
- .p2align 2, 0x0
-"#__delayLoadHelper2":
- mov w0, #1
- ret
-
- .weak_anti_dep __delayLoadHelper2
-.set __delayLoadHelper2,"#__delayLoadHelper2"
-
.section .hybmp$x, "yi"
.symidx __imp_func
.symidx func_exit_thunk
@@ -189,6 +196,25 @@ func2_exit_thunk:
mov w0, #3
ret
+#--- helper-mangled.s
+ .section .text,"xr",discard,"#__delayLoadHelper2"
+ .globl "#__delayLoadHelper2"
+ .p2align 2, 0x0
+"#__delayLoadHelper2":
+ mov w0, #1
+ ret
+
+ .weak_anti_dep __delayLoadHelper2
+.set __delayLoadHelper2,"#__delayLoadHelper2"
+
+#--- helper-demangled.s
+ .section .text,"xr",discard,__delayLoadHelper2
+ .globl __delayLoadHelper2
+ .p2align 2, 0x0
+__delayLoadHelper2:
+ mov w0, #1
+ ret
+
#--- test.def
NAME test.dll
EXPORTS
diff --git a/lld/test/COFF/arm64ec-entry-mangle.test b/lld/test/COFF/arm64ec-entry-mangle.test
new file mode 100644
index 00000000000000..65283f16d02fa9
--- /dev/null
+++ b/lld/test/COFF/arm64ec-entry-mangle.test
@@ -0,0 +1,129 @@
+REQUIRES: aarch64, x86
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows demangled-dll-main.s -o demangled-dll-main.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows mangled-dll-main.s -o mangled-dll-main.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows demangled-func.s -o demangled-func.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows mangled-func.s -o mangled-func.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ref-demangled.s -o ref-demangled.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows demangled-entry-drectve.s -o demangled-entry-drectve.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows demangled-dll-main.s -o x64-dll-main.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+
+RUN: llvm-lib -machine:arm64ec -out:func.lib mangled-func.obj
+RUN: llvm-lib -machine:arm64ec -out:dllmain.lib mangled-dll-main.obj
+
+Ensure that the linker recognizes the demangled version of _DllMainCRTStartup.
+RUN: lld-link -machine:arm64ec -dll -out:demangled-main.dll demangled-dll-main.obj loadconfig-arm64ec.obj
+RUN: llvm-objdump -d demangled-main.dll | FileCheck -check-prefix=DISASM %s
+
+DISASM: 0000000180001000 <.text>:
+DISASM-NEXT: 180001000: d65f03c0 ret
+DISASM-EMPTY:
+DISASM-NEXT: Disassembly of section .hexpthk:
+DISASM-EMPTY:
+DISASM: 180002000: 48 8b c4 movq %rsp, %rax
+DISASM-NEXT: 180002003: 48 89 58 20 movq %rbx, 0x20(%rax)
+DISASM-NEXT: 180002007: 55 pushq %rbp
+DISASM-NEXT: 180002008: 5d popq %rbp
+DISASM-NEXT: 180002009: e9 f2 ef ff ff jmp 0x180001000 <.text>
+DISASM-NEXT: 18000200e: cc int3
+DISASM-NEXT: 18000200f: cc int3
+
+Ensure that the linker recognizes the mangled version of #_DllMainCRTStartup.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-dllmain.dll mangled-dll-main.obj loadconfig-arm64ec.obj
+RUN: llvm-objdump -d mangled-dllmain.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled version of _DllMainCRTStartup from an archive.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-lib-dllmain.dll dllmain.lib loadconfig-arm64ec.obj
+RUN: llvm-objdump -d mangled-lib-dllmain.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the demangled entry function.
+RUN: lld-link -machine:arm64ec -dll -out:demangled-entry.dll demangled-func.obj loadconfig-arm64ec.obj -entry:func
+RUN: llvm-objdump -d demangled-entry.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled entry function when it is referenced by its demangled name.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-entry.dll mangled-func.obj loadconfig-arm64ec.obj -entry:func
+RUN: llvm-objdump -d mangled-entry.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled entry function when it is referenced by its demangled
+name in drectve section.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-entry.dll mangled-func.obj loadconfig-arm64ec.obj demangled-entry-drectve.obj
+RUN: llvm-objdump -d mangled-entry.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled entry function from an archive.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-lib-entry.dll func.lib loadconfig-arm64ec.obj -entry:func
+RUN: llvm-objdump -d mangled-lib-entry.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the entry function when referenced by its mangled name.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-entry2.dll mangled-func.obj loadconfig-arm64ec.obj "-entry:#func"
+RUN: llvm-objdump -d mangled-entry2.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the demangled exported function.
+RUN: lld-link -machine:arm64ec -dll -out:demangled-export.dll demangled-func.obj \
+RUN: loadconfig-arm64ec.obj -noentry -export:func
+RUN: llvm-objdump -d demangled-export.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled exported function when referenced by its demangled name.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-export.dll mangled-func.obj \
+RUN: loadconfig-arm64ec.obj -noentry -export:func
+RUN: llvm-objdump -d mangled-export.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled exported function when referenced by its mangled name.
+RUN: lld-link -machine:arm64ec -dll -out:mangled-export2.dll mangled-func.obj \
+RUN: loadconfig-arm64ec.obj -noentry "-export:#func"
+RUN: llvm-objdump -d mangled-export2.dll | FileCheck -check-prefix=DISASM %s
+
+Verify that the linker recognizes the mangled exported function when referenced
+by its mangled name and creates a demangled alias for it.
+RUN: lld-link -machine:arm64ec -dll -noentry -out:demangled-export-ref.dll mangled-func.obj \
+RUN: ref-demangled.obj loadconfig-arm64ec.obj "-export:#func"
+RUN: llvm-objdump -d demangled-export-ref.dll | FileCheck -check-prefix=DISASM %s
+
+DISASM2: 0000000180001000 <.text>:
+DISASM2-NEXT: 180001000: d65f03c0 ret
+
+Verify that the linker emits appropriate errors for mismatched mangling.
+RUN: not lld-link -machine:arm64ec -dll -out:test.dll demangled-func.obj loadconfig-arm64ec.obj \
+RUN: "-entry:#func" 2>&1 | FileCheck -check-prefix=FUNC-NOT-FOUND %s
+RUN: not lld-link -machine:arm64ec -dll -out:test.dll demangled-func.obj loadconfig-arm64ec.obj \
+RUN: -noentry "-export:#func" 2>&1 | FileCheck -check-prefix=FUNC-NOT-FOUND %s
+FUNC-NOT-FOUND: undefined symbol: #func
+
+Verify that the linker recognizes the demangled x86_64 _DllMainCRTStartup.
+RUN: lld-link -machine:arm64ec -dll -out:test.dll x64-dll-main.obj loadconfig-arm64ec.obj
+RUN: llvm-objdump -d test.dll | FileCheck -check-prefix=DISASM-X64 %s
+DISASM-X64: 0000000180001000 <.text>:
+DISASM-X64-NEXT: 180001000: c3 retq
+
+#--- demangled-dll-main.s
+ .text
+ .globl _DllMainCRTStartup
+_DllMainCRTStartup:
+ ret
+
+#--- mangled-dll-main.s
+ .text
+ .globl "#_DllMainCRTStartup"
+"#_DllMainCRTStartup":
+ ret
+
+#--- demangled-func.s
+ .text
+ .globl func
+func:
+ ret
+
+#--- mangled-func.s
+ .text
+ .globl "#func"
+"#func":
+ ret
+
+#--- ref-demangled.s
+ .data
+ .rva func
+
+#--- demangled-entry-drectve.s
+ .section .drectve,"rd"
+ .ascii " -entry:func"
More information about the llvm-commits
mailing list