[lld] [LLD][COFF] Add support for hybrid ARM64X entry points (PR #123096)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 15 09:44:43 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
Author: Jacek Caban (cjacek)
<details>
<summary>Changes</summary>
Store the entry symbol in SymbolTable instead of Configuration, as it differs between symbol tables.
---
Full diff: https://github.com/llvm/llvm-project/pull/123096.diff
6 Files Affected:
- (modified) lld/COFF/Config.h (-1)
- (modified) lld/COFF/Driver.cpp (+21-18)
- (modified) lld/COFF/MapFile.cpp (+1-1)
- (modified) lld/COFF/SymbolTable.h (+3)
- (modified) lld/COFF/Writer.cpp (+15-3)
- (added) lld/test/COFF/arm64x-entry.test (+92)
``````````diff
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 9e6b17e87c9e70..924560fef0231d 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -120,7 +120,6 @@ struct Configuration {
size_t wordsize;
bool verbose = false;
WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
- Symbol *entry = nullptr;
bool noEntry = false;
std::string outputFile;
std::string importName;
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index beb135f08fa3b1..0de4c8ff5b250d 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -491,8 +491,9 @@ void LinkerDriver::parseDirectives(InputFile *file) {
case OPT_entry:
if (!arg->getValue()[0])
Fatal(ctx) << "missing entry point symbol name";
- ctx.config.entry =
- file->symtab.addGCRoot(file->symtab.mangle(arg->getValue()), true);
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);
+ });
break;
case OPT_failifmismatch:
checkFailIfMismatch(arg->getValue(), file);
@@ -1394,8 +1395,9 @@ void LinkerDriver::createECExportThunks() {
}
}
- if (ctx.config.entry)
- maybeCreateECExportThunk(ctx.config.entry->getName(), ctx.config.entry);
+ if (ctx.symtabEC->entry)
+ maybeCreateECExportThunk(ctx.symtabEC->entry->getName(),
+ ctx.symtabEC->entry);
for (Export &e : ctx.config.exports) {
if (!e.data)
maybeCreateECExportThunk(e.extName.empty() ? e.name : e.extName, e.sym);
@@ -2357,33 +2359,32 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
}
// Handle /entry and /dll
- {
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
llvm::TimeTraceScope timeScope("Entry point");
if (auto *arg = args.getLastArg(OPT_entry)) {
if (!arg->getValue()[0])
Fatal(ctx) << "missing entry point symbol name";
- config->entry =
- ctx.symtab.addGCRoot(ctx.symtab.mangle(arg->getValue()), true);
- } else if (!config->entry && !config->noEntry) {
+ symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true);
+ } else if (!symtab.entry && !config->noEntry) {
if (args.hasArg(OPT_dll)) {
StringRef s = (config->machine == I386) ? "__DllMainCRTStartup at 12"
: "_DllMainCRTStartup";
- config->entry = ctx.symtab.addGCRoot(s, true);
+ symtab.entry = symtab.addGCRoot(s, true);
} else if (config->driverWdm) {
// /driver:wdm implies /entry:_NtProcessStartup
- config->entry =
- ctx.symtab.addGCRoot(ctx.symtab.mangle("_NtProcessStartup"), true);
+ symtab.entry =
+ symtab.addGCRoot(symtab.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 = ctx.symtab.findDefaultEntry();
+ StringRef s = symtab.findDefaultEntry();
if (s.empty())
Fatal(ctx) << "entry point must be defined";
- config->entry = ctx.symtab.addGCRoot(s, true);
+ symtab.entry = symtab.addGCRoot(s, true);
Log(ctx) << "Entry name inferred: " << s;
}
}
- }
+ });
// Handle /delayload
{
@@ -2522,10 +2523,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
{
llvm::TimeTraceScope timeScope("Add unresolved symbols");
do {
- // Windows specific -- if entry point is not found,
- // search for its mangled names.
- if (config->entry)
- ctx.symtab.mangleMaybe(config->entry);
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ // Windows specific -- if entry point is not found,
+ // search for its mangled names.
+ if (symtab.entry)
+ symtab.mangleMaybe(symtab.entry);
+ });
// Windows specific -- Make sure we resolve all dllexported symbols.
for (Export &e : config->exports) {
diff --git a/lld/COFF/MapFile.cpp b/lld/COFF/MapFile.cpp
index e3531c04e77473..af87587d143d56 100644
--- a/lld/COFF/MapFile.cpp
+++ b/lld/COFF/MapFile.cpp
@@ -301,7 +301,7 @@ void lld::coff::writeMapFile(COFFLinkerContext &ctx) {
uint64_t entryAddress = 0;
if (!ctx.config.noEntry) {
- Defined *entry = dyn_cast_or_null<Defined>(ctx.config.entry);
+ Defined *entry = dyn_cast_or_null<Defined>(ctx.symtab.entry);
if (entry) {
Chunk *chunk = entry->getChunk();
entrySecIndex = chunk->getOutputSectionIdx();
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index 1de0b3e1deac3e..809b5d9dfea307 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -143,6 +143,9 @@ class SymbolTable {
bool isEC() const { return machine == ARM64EC; }
+ // An entry point symbol.
+ Symbol *entry = nullptr;
+
// A list of chunks which to be added to .rdata.
std::vector<Chunk *> localImportChunks;
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index eb82a9cc015933..a839f400f7a882 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1748,7 +1748,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
pe->SizeOfImage = sizeOfImage;
pe->SizeOfHeaders = sizeOfHeaders;
if (!config->noEntry) {
- Defined *entry = cast<Defined>(config->entry);
+ Defined *entry = cast<Defined>(ctx.symtab.entry);
pe->AddressOfEntryPoint = entry->getRVA();
// Pointer to thumb code must have the LSB set, so adjust it.
if (config->machine == ARMNT)
@@ -2031,8 +2031,10 @@ void Writer::createGuardCFTables() {
}
// Mark the image entry as address-taken.
- if (config->entry)
- maybeAddAddressTakenFunction(addressTakenSyms, config->entry);
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ if (symtab.entry)
+ maybeAddAddressTakenFunction(addressTakenSyms, symtab.entry);
+ });
// Mark exported symbols in executable sections as address-taken.
for (Export &e : config->exports)
@@ -2584,6 +2586,16 @@ void Writer::createDynamicRelocs() {
coffHeaderOffset + offsetof(coff_file_header, Machine),
AMD64);
+ if (ctx.symtab.entry || ctx.hybridSymtab->entry) {
+ Defined *entrySym = ctx.hybridSymtab->entry
+ ? dyn_cast<Defined>(ctx.hybridSymtab->entry)
+ : nullptr;
+ ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+ peHeaderOffset +
+ offsetof(pe32plus_header, AddressOfEntryPoint),
+ entrySym);
+ }
+
// Set the hybrid load config to the EC load config.
ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
dataDirOffset64 +
diff --git a/lld/test/COFF/arm64x-entry.test b/lld/test/COFF/arm64x-entry.test
new file mode 100644
index 00000000000000..d5363c66544a5f
--- /dev/null
+++ b/lld/test/COFF/arm64x-entry.test
@@ -0,0 +1,92 @@
+REQUIRES: aarch64, x86
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-dllmain.s -o arm64ec-dllmain.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows arm64-dllmain.s -o arm64-dllmain.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func.s -o arm64ec-func.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows arm64-func.s -o arm64-func.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64-drectve.s -o arm64ec-drectve.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows arm64-drectve.s -o arm64-drectve.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+RUN: lld-link -machine:arm64x -dll -out:out.dll arm64ec-dllmain.obj arm64-dllmain.obj \
+RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj
+
+RUN: llvm-objdump -d out.dll | FileCheck --check-prefix=DISASM %s
+DISASM: Disassembly of section .text:
+DISASM-EMPTY:
+DISASM-NEXT: 0000000180001000 <.text>:
+DISASM-NEXT: 180001000: 52800020 mov w0, #0x1 // =1
+DISASM-NEXT: 180001004: d65f03c0 ret
+DISASM-NEXT: ...
+DISASM-NEXT: 180002000: 52800040 mov w0, #0x2 // =2
+DISASM-NEXT: 180002004: d65f03c0 ret
+DISASM-EMPTY:
+DISASM-NEXT: Disassembly of section .hexpthk:
+DISASM-EMPTY:
+DISASM-NEXT: 0000000180003000 <.hexpthk>:
+DISASM-NEXT: 180003000: 48 8b c4 movq %rsp, %rax
+DISASM-NEXT: 180003003: 48 89 58 20 movq %rbx, 0x20(%rax)
+DISASM-NEXT: 180003007: 55 pushq %rbp
+DISASM-NEXT: 180003008: 5d popq %rbp
+DISASM-NEXT: 180003009: e9 f2 ef ff ff jmp 0x180002000 <.text+0x1000>
+DISASM-NEXT: 18000300e: cc int3
+DISASM-NEXT: 18000300f: cc int3
+
+RUN: llvm-readobj --headers out.dll | FileCheck --check-prefix=READOBJ %s
+READOBJ: AddressOfEntryPoint: 0x1000
+READOBJ: HybridObject {
+READOBJ: AddressOfEntryPoint: 0x3000
+READOBJ: }
+
+RUN: lld-link -machine:arm64x -dll -out:out2.dll arm64ec-func.obj arm64-func.obj \
+RUN: arm64ec-drectve.obj loadconfig-arm64.obj loadconfig-arm64ec.obj
+RUN: llvm-objdump -d out2.dll | FileCheck --check-prefix=DISASM %s
+RUN: llvm-readobj --headers --coff-load-config out2.dll | FileCheck --check-prefix=READOBJ %s
+
+RUN: lld-link -machine:arm64x -dll -out:out3.dll arm64ec-func.obj arm64-func.obj \
+RUN: arm64-drectve.obj loadconfig-arm64.obj loadconfig-arm64ec.obj
+RUN: llvm-objdump -d out3.dll | FileCheck --check-prefix=DISASM %s
+RUN: llvm-readobj --headers --coff-load-config out3.dll | FileCheck --check-prefix=READOBJ %s
+
+RUN: lld-link -machine:arm64x -dll -out:out4.dll arm64ec-func.obj arm64-func.obj \
+RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -entry:func
+RUN: llvm-objdump -d out4.dll | FileCheck --check-prefix=DISASM %s
+RUN: llvm-readobj --headers --coff-load-config out4.dll | FileCheck --check-prefix=READOBJ %s
+
+#--- arm64-dllmain.s
+ .section .text,"xr",discard,_DllMainCRTStartup
+ .globl _DllMainCRTStartup
+ .p2align 2
+_DllMainCRTStartup:
+ mov w0, #1
+ ret
+
+#--- arm64ec-dllmain.s
+ .section .text,"xr",discard,_DllMainCRTStartup
+ .globl _DllMainCRTStartup
+ .p2align 2
+_DllMainCRTStartup:
+ mov w0, #2
+ ret
+
+#--- arm64-func.s
+ .section .text,"xr",discard,func
+ .globl func
+ .p2align 2
+func:
+ mov w0, #1
+ ret
+
+#--- arm64ec-func.s
+ .section .text,"xr",discard,func
+ .globl func
+ .p2align 2
+func:
+ mov w0, #2
+ ret
+
+#--- arm64-drectve.s
+.section .drectve
+ .ascii "-entry:func"
``````````
</details>
https://github.com/llvm/llvm-project/pull/123096
More information about the llvm-commits
mailing list