summaryrefslogtreecommitdiff
path: root/lld/COFF/SymbolTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF/SymbolTable.cpp')
-rw-r--r--lld/COFF/SymbolTable.cpp126
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;