summaryrefslogtreecommitdiff
path: root/lld/COFF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF/Writer.cpp')
-rw-r--r--lld/COFF/Writer.cpp135
1 files changed, 66 insertions, 69 deletions
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 3c6112b7fc89..a5b2b6238db1 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -282,7 +282,8 @@ private:
uint32_t getSizeOfInitializedData();
void prepareLoadConfig();
- template <typename T> void prepareLoadConfig(T *loadConfig);
+ template <typename T>
+ void prepareLoadConfig(SymbolTable &symtab, T *loadConfig);
std::unique_ptr<FileOutputBuffer> &buffer;
std::map<PartialSectionKey, PartialSection *> partialSections;
@@ -574,7 +575,7 @@ bool Writer::createThunks(OutputSection *os, int margin) {
// Create a code map for CHPE metadata.
void Writer::createECCodeMap() {
- if (!isArm64EC(ctx.config.machine))
+ if (!ctx.symtabEC)
return;
// Clear the map in case we were're recomputing the map after adding
@@ -610,7 +611,8 @@ void Writer::createECCodeMap() {
closeRange();
- Symbol *tableCountSym = ctx.symtab.findUnderscore("__hybrid_code_map_count");
+ Symbol *tableCountSym =
+ ctx.symtabEC->findUnderscore("__hybrid_code_map_count");
cast<DefinedAbsolute>(tableCountSym)->setVA(codeMap.size());
}
@@ -944,7 +946,7 @@ void Writer::appendECImportTables() {
const uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
- // IAT is always placed at the begining of .rdata section and its size
+ // IAT is always placed at the beginning of .rdata section and its size
// is aligned to 4KB. Insert it here, after all merges all done.
if (PartialSection *importAddresses = findPartialSection(".idata$5", rdata)) {
if (!rdataSec->chunks.empty())
@@ -1228,8 +1230,7 @@ void Writer::createMiscChunks() {
// Create /guard:cf tables if requested.
createGuardCFTables();
- if (isArm64EC(config->machine))
- createECChunks();
+ createECChunks();
if (config->autoImport)
createRuntimePseudoRelocs();
@@ -1837,22 +1838,10 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA();
dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize();
}
- if (Symbol *sym = ctx.symtab.findUnderscore("_load_config_used")) {
- if (auto *b = dyn_cast<DefinedRegular>(sym)) {
- SectionChunk *sc = b->getChunk();
- assert(b->getRVA() >= sc->getRVA());
- uint64_t offsetInChunk = b->getRVA() - sc->getRVA();
- if (!sc->hasData || offsetInChunk + 4 > sc->getSize())
- Fatal(ctx) << "_load_config_used is malformed";
-
- ArrayRef<uint8_t> secContents = sc->getContents();
- uint32_t loadConfigSize =
- *reinterpret_cast<const ulittle32_t *>(&secContents[offsetInChunk]);
- if (offsetInChunk + loadConfigSize > sc->getSize())
- Fatal(ctx) << "_load_config_used is too large";
- dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = b->getRVA();
- dir[LOAD_CONFIG_TABLE].Size = loadConfigSize;
- }
+ if (ctx.symtab.loadConfigSym) {
+ dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress =
+ ctx.symtab.loadConfigSym->getRVA();
+ dir[LOAD_CONFIG_TABLE].Size = ctx.symtab.loadConfigSize;
}
if (!delayIdata.empty()) {
dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
@@ -2169,7 +2158,11 @@ void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
// Create CHPE metadata chunks.
void Writer::createECChunks() {
- for (Symbol *s : ctx.symtab.expSymbols) {
+ SymbolTable *symtab = ctx.symtabEC;
+ if (!symtab)
+ return;
+
+ for (Symbol *s : symtab->expSymbols) {
auto sym = dyn_cast<Defined>(s);
if (!sym || !sym->getChunk())
continue;
@@ -2188,9 +2181,9 @@ void Writer::createECChunks() {
// we should use the #foo$hp_target symbol as the redirection target.
// First, try to look up the $hp_target symbol. If it can't be found,
// assume it's a regular function and look for #foo instead.
- Symbol *targetSym = ctx.symtab.find((targetName + "$hp_target").str());
+ Symbol *targetSym = symtab->find((targetName + "$hp_target").str());
if (!targetSym)
- targetSym = ctx.symtab.find(targetName);
+ targetSym = symtab->find(targetName);
Defined *t = dyn_cast_or_null<Defined>(targetSym);
if (t && isArm64EC(t->getChunk()->getMachine()))
exportThunks.push_back({chunk, t});
@@ -2199,20 +2192,20 @@ void Writer::createECChunks() {
auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
rdataSec->addChunk(codeMapChunk);
- Symbol *codeMapSym = ctx.symtab.findUnderscore("__hybrid_code_map");
+ Symbol *codeMapSym = symtab->findUnderscore("__hybrid_code_map");
replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName(),
codeMapChunk);
CHPECodeRangesChunk *ranges = make<CHPECodeRangesChunk>(exportThunks);
rdataSec->addChunk(ranges);
Symbol *rangesSym =
- ctx.symtab.findUnderscore("__x64_code_ranges_to_entry_points");
+ symtab->findUnderscore("__x64_code_ranges_to_entry_points");
replaceSymbol<DefinedSynthetic>(rangesSym, rangesSym->getName(), ranges);
CHPERedirectionChunk *entryPoints = make<CHPERedirectionChunk>(exportThunks);
a64xrmSec->addChunk(entryPoints);
Symbol *entryPointsSym =
- ctx.symtab.findUnderscore("__arm64x_redirection_metadata");
+ symtab->findUnderscore("__arm64x_redirection_metadata");
replaceSymbol<DefinedSynthetic>(entryPointsSym, entryPointsSym->getName(),
entryPoints);
}
@@ -2305,7 +2298,8 @@ void Writer::setSectionPermissions() {
// Set symbols used by ARM64EC metadata.
void Writer::setECSymbols() {
- if (!isArm64EC(ctx.config.machine))
+ SymbolTable *symtab = ctx.symtabEC;
+ if (!symtab)
return;
llvm::stable_sort(exportThunks, [](const std::pair<Chunk *, Defined *> &a,
@@ -2313,45 +2307,45 @@ void Writer::setECSymbols() {
return a.first->getRVA() < b.first->getRVA();
});
- Symbol *rfeTableSym = ctx.symtab.findUnderscore("__arm64x_extra_rfe_table");
+ Symbol *rfeTableSym = symtab->findUnderscore("__arm64x_extra_rfe_table");
replaceSymbol<DefinedSynthetic>(rfeTableSym, "__arm64x_extra_rfe_table",
pdata.first);
if (pdata.first) {
Symbol *rfeSizeSym =
- ctx.symtab.findUnderscore("__arm64x_extra_rfe_table_size");
+ symtab->findUnderscore("__arm64x_extra_rfe_table_size");
cast<DefinedAbsolute>(rfeSizeSym)
->setVA(pdata.last->getRVA() + pdata.last->getSize() -
pdata.first->getRVA());
}
Symbol *rangesCountSym =
- ctx.symtab.findUnderscore("__x64_code_ranges_to_entry_points_count");
+ symtab->findUnderscore("__x64_code_ranges_to_entry_points_count");
cast<DefinedAbsolute>(rangesCountSym)->setVA(exportThunks.size());
Symbol *entryPointCountSym =
- ctx.symtab.findUnderscore("__arm64x_redirection_metadata_count");
+ symtab->findUnderscore("__arm64x_redirection_metadata_count");
cast<DefinedAbsolute>(entryPointCountSym)->setVA(exportThunks.size());
- Symbol *iatSym = ctx.symtab.findUnderscore("__hybrid_auxiliary_iat");
+ Symbol *iatSym = symtab->findUnderscore("__hybrid_auxiliary_iat");
replaceSymbol<DefinedSynthetic>(iatSym, "__hybrid_auxiliary_iat",
idata.auxIat.empty() ? nullptr
: idata.auxIat.front());
- Symbol *iatCopySym = ctx.symtab.findUnderscore("__hybrid_auxiliary_iat_copy");
+ Symbol *iatCopySym = symtab->findUnderscore("__hybrid_auxiliary_iat_copy");
replaceSymbol<DefinedSynthetic>(
iatCopySym, "__hybrid_auxiliary_iat_copy",
idata.auxIatCopy.empty() ? nullptr : idata.auxIatCopy.front());
Symbol *delayIatSym =
- ctx.symtab.findUnderscore("__hybrid_auxiliary_delayload_iat");
+ symtab->findUnderscore("__hybrid_auxiliary_delayload_iat");
replaceSymbol<DefinedSynthetic>(
delayIatSym, "__hybrid_auxiliary_delayload_iat",
delayIdata.getAuxIat().empty() ? nullptr
: delayIdata.getAuxIat().front());
Symbol *delayIatCopySym =
- ctx.symtab.findUnderscore("__hybrid_auxiliary_delayload_iat_copy");
+ symtab->findUnderscore("__hybrid_auxiliary_delayload_iat_copy");
replaceSymbol<DefinedSynthetic>(
delayIatCopySym, "__hybrid_auxiliary_delayload_iat_copy",
delayIdata.getAuxIatCopy().empty() ? nullptr
@@ -2649,39 +2643,25 @@ void Writer::fixTlsAlignment() {
}
void Writer::prepareLoadConfig() {
- Symbol *sym = ctx.symtab.findUnderscore("_load_config_used");
- auto *b = cast_if_present<DefinedRegular>(sym);
- if (!b) {
- if (ctx.config.guardCF != GuardCFLevel::Off)
- Warn(ctx)
- << "Control Flow Guard is enabled but '_load_config_used' is missing";
- if (ctx.config.dependentLoadFlags)
- Warn(ctx) << "_load_config_used not found, /dependentloadflag will have "
- "no effect";
- return;
- }
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ if (!symtab.loadConfigSym)
+ return;
- OutputSection *sec = ctx.getOutputSection(b->getChunk());
- uint8_t *buf = buffer->getBufferStart();
- uint8_t *secBuf = buf + sec->getFileOff();
- uint8_t *symBuf = secBuf + (b->getRVA() - sec->getRVA());
- uint32_t expectedAlign = ctx.config.is64() ? 8 : 4;
- if (b->getChunk()->getAlignment() < expectedAlign)
- Warn(ctx) << "'_load_config_used' is misaligned (expected alignment to be "
- << expectedAlign << " bytes, got "
- << b->getChunk()->getAlignment() << " instead)";
- else if (!isAligned(Align(expectedAlign), b->getRVA()))
- Warn(ctx) << "'_load_config_used' is misaligned (RVA is 0x"
- << Twine::utohexstr(b->getRVA()) << " not aligned to "
- << expectedAlign << " bytes)";
-
- if (ctx.config.is64())
- prepareLoadConfig(reinterpret_cast<coff_load_configuration64 *>(symBuf));
- else
- prepareLoadConfig(reinterpret_cast<coff_load_configuration32 *>(symBuf));
+ OutputSection *sec = ctx.getOutputSection(symtab.loadConfigSym->getChunk());
+ uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
+ uint8_t *symBuf = secBuf + (symtab.loadConfigSym->getRVA() - sec->getRVA());
+
+ if (ctx.config.is64())
+ prepareLoadConfig(symtab,
+ reinterpret_cast<coff_load_configuration64 *>(symBuf));
+ else
+ prepareLoadConfig(symtab,
+ reinterpret_cast<coff_load_configuration32 *>(symBuf));
+ });
}
-template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
+template <typename T>
+void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) {
size_t loadConfigSize = loadConfig->Size;
#define RETURN_IF_NOT_CONTAINS(field) \
@@ -2694,12 +2674,12 @@ template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
if (loadConfigSize >= offsetof(T, field) + sizeof(T::field))
#define CHECK_VA(field, sym) \
- if (auto *s = dyn_cast<DefinedSynthetic>(ctx.symtab.findUnderscore(sym))) \
+ if (auto *s = dyn_cast<DefinedSynthetic>(symtab.findUnderscore(sym))) \
if (loadConfig->field != ctx.config.imageBase + s->getRVA()) \
Warn(ctx) << #field " not set correctly in '_load_config_used'";
#define CHECK_ABSOLUTE(field, sym) \
- if (auto *s = dyn_cast<DefinedAbsolute>(ctx.symtab.findUnderscore(sym))) \
+ if (auto *s = dyn_cast<DefinedAbsolute>(symtab.findUnderscore(sym))) \
if (loadConfig->field != s->getVA()) \
Warn(ctx) << #field " not set correctly in '_load_config_used'";
@@ -2720,6 +2700,23 @@ template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
}
}
+ IF_CONTAINS(CHPEMetadataPointer) {
+ // On ARM64X, only the EC version of the load config contains
+ // CHPEMetadataPointer. Copy its value to the native load config.
+ if (ctx.hybridSymtab && !symtab.isEC() &&
+ ctx.hybridSymtab->loadConfigSize >=
+ offsetof(T, CHPEMetadataPointer) + sizeof(T::CHPEMetadataPointer)) {
+ OutputSection *sec =
+ ctx.getOutputSection(ctx.hybridSymtab->loadConfigSym->getChunk());
+ uint8_t *secBuf = buffer->getBufferStart() + sec->getFileOff();
+ auto hybridLoadConfig =
+ reinterpret_cast<const coff_load_configuration64 *>(
+ secBuf +
+ (ctx.hybridSymtab->loadConfigSym->getRVA() - sec->getRVA()));
+ loadConfig->CHPEMetadataPointer = hybridLoadConfig->CHPEMetadataPointer;
+ }
+ }
+
if (ctx.config.guardCF == GuardCFLevel::Off)
return;
RETURN_IF_NOT_CONTAINS(GuardFlags)