-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[LLD][COFF] Add support for ARM64X same-address thunks #151255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -500,7 +500,9 @@ void LinkerDriver::parseDirectives(InputFile *file) { | |
file->symtab.parseAlternateName(arg->getValue()); | ||
break; | ||
case OPT_arm64xsameaddress: | ||
if (!file->symtab.isEC()) | ||
if (file->symtab.isEC()) | ||
parseSameAddress(arg->getValue()); | ||
else | ||
Warn(ctx) << arg->getSpelling() | ||
<< " is not allowed in non-ARM64EC files (" << toString(file) | ||
<< ")"; | ||
|
@@ -2295,6 +2297,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { | |
args.filtered(OPT_dependentloadflag, OPT_dependentloadflag_opt)) | ||
parseDependentLoadFlags(arg); | ||
|
||
for (auto *arg : args.filtered(OPT_arm64xsameaddress)) { | ||
if (ctx.hybridSymtab) | ||
parseSameAddress(arg->getValue()); | ||
else | ||
Warn(ctx) << arg->getSpelling() << " is allowed only on EC targets"; | ||
} | ||
|
||
if (tar) { | ||
llvm::TimeTraceScope timeScope("Reproducer: response file"); | ||
tar->append( | ||
|
@@ -2668,12 +2677,46 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { | |
createECExportThunks(); | ||
|
||
// Resolve remaining undefined symbols and warn about imported locals. | ||
std::vector<Undefined *> aliases; | ||
ctx.forEachSymtab( | ||
[&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(); }); | ||
[&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(aliases); }); | ||
|
||
if (errorCount()) | ||
return; | ||
|
||
ctx.forEachActiveSymtab([](SymbolTable &symtab) { | ||
symtab.initializeECThunks(); | ||
symtab.initializeLoadConfig(); | ||
}); | ||
|
||
// Identify unreferenced COMDAT sections. | ||
if (config->doGC) { | ||
if (config->mingw) { | ||
// markLive doesn't traverse .eh_frame, but the personality function is | ||
// only reached that way. The proper solution would be to parse and | ||
// traverse the .eh_frame section, like the ELF linker does. | ||
// For now, just manually try to retain the known possible personality | ||
// functions. This doesn't bring in more object files, but only marks | ||
// functions that already have been included to be retained. | ||
ctx.forEachSymtab([&](SymbolTable &symtab) { | ||
for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0", | ||
"rust_eh_personality"}) { | ||
Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n)); | ||
if (d && !d->isGCRoot) { | ||
d->isGCRoot = true; | ||
config->gcroot.push_back(d); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
markLive(ctx); | ||
} | ||
|
||
ctx.symtab.initializeSameAddressThunks(); | ||
for (auto alias : aliases) | ||
alias->resolveWeakAlias(); | ||
|
||
|
||
if (config->mingw) { | ||
// Make sure the crtend.o object is the last object file. This object | ||
// file can contain terminating section chunks that need to be placed | ||
|
@@ -2765,35 +2808,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { | |
if (auto *arg = args.getLastArg(OPT_print_symbol_order)) | ||
config->printSymbolOrder = arg->getValue(); | ||
|
||
if (ctx.symtab.isEC()) | ||
ctx.symtab.initializeECThunks(); | ||
ctx.forEachActiveSymtab( | ||
[](SymbolTable &symtab) { symtab.initializeLoadConfig(); }); | ||
|
||
// Identify unreferenced COMDAT sections. | ||
if (config->doGC) { | ||
if (config->mingw) { | ||
// markLive doesn't traverse .eh_frame, but the personality function is | ||
// only reached that way. The proper solution would be to parse and | ||
// traverse the .eh_frame section, like the ELF linker does. | ||
// For now, just manually try to retain the known possible personality | ||
// functions. This doesn't bring in more object files, but only marks | ||
// functions that already have been included to be retained. | ||
ctx.forEachSymtab([&](SymbolTable &symtab) { | ||
for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0", | ||
"rust_eh_personality"}) { | ||
Defined *d = dyn_cast_or_null<Defined>(symtab.findUnderscore(n)); | ||
if (d && !d->isGCRoot) { | ||
d->isGCRoot = true; | ||
config->gcroot.push_back(d); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
markLive(ctx); | ||
} | ||
|
||
// Needs to happen after the last call to addFile(). | ||
convertResources(); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -328,6 +328,22 @@ void LinkerDriver::parseSwaprun(StringRef arg) { | |
} while (!arg.empty()); | ||
} | ||
|
||
void LinkerDriver::parseSameAddress(StringRef arg) { | ||
auto mangledName = getArm64ECMangledFunctionName(arg); | ||
Symbol *sym = ctx.symtab.addUndefined(mangledName ? *mangledName : arg); | ||
|
||
// MSVC appears to generate thunks even for non-hybrid ARM64EC images. | ||
// As a side effect, the native symbol is pulled in. Since this is used | ||
// in the CRT for thread-local constructors, it results in the image | ||
// containing unnecessary native code. As these thunks don't appear to | ||
// be useful, we limit this behavior to actual hybrid targets. This may | ||
// change if compatibility becomes necessary. | ||
if (ctx.config.machine != ARM64X) | ||
|
||
return; | ||
Symbol *nativeSym = ctx.hybridSymtab->addUndefined(arg); | ||
ctx.config.sameAddresses.emplace_back(sym, nativeSym); | ||
} | ||
|
||
// An RAII temporary file class that automatically removes a temporary file. | ||
namespace { | ||
class TemporaryFile { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously,
initializeECThunks()
only was called on one out of two symtabs - now it's called on both. Presumably just for code simplicity here, or is it a functional change?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
initializeECThunks()
already checks the machine type, so the previous check was redundant.