diff options
Diffstat (limited to 'lld/COFF/SymbolTable.cpp')
| -rw-r--r-- | lld/COFF/SymbolTable.cpp | 126 |
1 files changed, 58 insertions, 68 deletions
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index b1d375b22658..ae88675ab93a 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -27,6 +27,7 @@ #include <utility> using namespace llvm; +using namespace llvm::support; namespace lld::coff { @@ -36,71 +37,6 @@ StringRef ltrim1(StringRef s, const char *chars) { return s; } -static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) { - if (mt == IMAGE_FILE_MACHINE_UNKNOWN) - return true; - switch (ctx.config.machine) { - case ARM64: - return mt == ARM64 || mt == ARM64X; - case ARM64EC: - return COFF::isArm64EC(mt) || mt == AMD64; - case ARM64X: - return COFF::isAnyArm64(mt) || mt == AMD64; - case IMAGE_FILE_MACHINE_UNKNOWN: - return true; - default: - return ctx.config.machine == mt; - } -} - -void SymbolTable::addFile(InputFile *file) { - Log(ctx) << "Reading " << toString(file); - if (file->lazy) { - if (auto *f = dyn_cast<BitcodeFile>(file)) - f->parseLazy(); - else - cast<ObjFile>(file)->parseLazy(); - } else { - file->parse(); - if (auto *f = dyn_cast<ObjFile>(file)) { - ctx.objFileInstances.push_back(f); - } else if (auto *f = dyn_cast<BitcodeFile>(file)) { - if (ltoCompilationDone) { - Err(ctx) << "LTO object file " << toString(file) - << " linked in after " - "doing LTO compilation."; - } - ctx.bitcodeFileInstances.push_back(f); - } else if (auto *f = dyn_cast<ImportFile>(file)) { - ctx.importFileInstances.push_back(f); - } - } - - MachineTypes mt = file->getMachineType(); - // The ARM64EC target must be explicitly specified and cannot be inferred. - if (mt == ARM64EC && - (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN || - (ctx.config.machineInferred && - (ctx.config.machine == ARM64 || ctx.config.machine == AMD64)))) { - Err(ctx) << toString(file) - << ": machine type arm64ec is ambiguous and cannot be " - "inferred, use /machine:arm64ec or /machine:arm64x"; - return; - } - if (!compatibleMachineType(ctx, mt)) { - Err(ctx) << toString(file) << ": machine type " << machineToStr(mt) - << " conflicts with " << machineToStr(ctx.config.machine); - return; - } - if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN && - mt != IMAGE_FILE_MACHINE_UNKNOWN) { - ctx.config.machineInferred = true; - ctx.driver.setMachine(mt); - } - - ctx.driver.parseDirectives(file); -} - static COFFSyncStream errorOrWarn(COFFLinkerContext &ctx) { return {ctx, ctx.config.forceUnresolved ? DiagLevel::Warn : DiagLevel::Err}; } @@ -117,7 +53,7 @@ static void forceLazy(Symbol *s) { case Symbol::Kind::LazyObjectKind: { InputFile *file = cast<LazyObject>(s)->file; file->lazy = false; - file->symtab.addFile(file); + file->symtab.ctx.driver.addFile(file); break; } case Symbol::Kind::LazyDLLSymbolKind: { @@ -596,6 +532,61 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, InputFile *file) { return result; } +void SymbolTable::initializeLoadConfig() { + auto sym = + dyn_cast_or_null<DefinedRegular>(findUnderscore("_load_config_used")); + if (!sym) { + if (isEC()) { + Warn(ctx) << "EC version of '_load_config_used' is missing"; + return; + } + if (ctx.hybridSymtab) { + Warn(ctx) << "native version of '_load_config_used' is missing for " + "ARM64X target"; + return; + } + 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; + } + + SectionChunk *sc = sym->getChunk(); + if (!sc->hasData) { + Err(ctx) << "_load_config_used points to uninitialized data"; + return; + } + uint64_t offsetInChunk = sym->getValue(); + if (offsetInChunk + 4 > sc->getSize()) { + Err(ctx) << "_load_config_used section chunk is too small"; + return; + } + + ArrayRef<uint8_t> secContents = sc->getContents(); + loadConfigSize = + *reinterpret_cast<const ulittle32_t *>(&secContents[offsetInChunk]); + if (offsetInChunk + loadConfigSize > sc->getSize()) { + Err(ctx) << "_load_config_used specifies a size larger than its containing " + "section chunk"; + return; + } + + uint32_t expectedAlign = ctx.config.is64() ? 8 : 4; + if (sc->getAlignment() < expectedAlign) + Warn(ctx) << "'_load_config_used' is misaligned (expected alignment to be " + << expectedAlign << " bytes, got " << sc->getAlignment() + << " instead)"; + else if (!isAligned(Align(expectedAlign), offsetInChunk)) + Warn(ctx) << "'_load_config_used' is misaligned (section offset is 0x" + << Twine::utohexstr(sym->getValue()) << " not aligned to " + << expectedAlign << " bytes)"; + + loadConfigSym = sym; +} + void SymbolTable::addEntryThunk(Symbol *from, Symbol *to) { entryThunks.push_back({from, to}); } @@ -729,7 +720,7 @@ void SymbolTable::addLazyObject(InputFile *f, StringRef n) { return; s->pendingArchiveLoad = true; f->lazy = false; - addFile(f); + ctx.driver.addFile(f); } void SymbolTable::addLazyDLLSymbol(DLLFile *f, DLLFile::Symbol *sym, @@ -1007,7 +998,6 @@ Symbol *SymbolTable::addUndefined(StringRef name) { } void SymbolTable::compileBitcodeFiles() { - ltoCompilationDone = true; if (ctx.bitcodeFileInstances.empty()) return; |
