-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLD][COFF] Prepare both load configs on ARM64X #120326
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
Conversation
Depends on #120324. |
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-lld-coff Author: Jacek Caban (cjacek) ChangesFull diff: https://github.com/llvm/llvm-project/pull/120326.diff 9 Files Affected:
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index bef55abb7f856e..9d45e9b926b1f6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2822,6 +2822,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (ctx.symtabEC)
ctx.symtabEC->initializeECThunks();
+ ctx.forEachSymtab([](SymbolTable &symtab) { symtab.initializeLoadConfig(); });
// Identify unreferenced COMDAT sections.
if (config->doGC) {
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 6b3375e13e8393..7e243fc626d38d 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 {
@@ -595,6 +596,52 @@ 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 (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});
}
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index b694893b903aa3..8548a6d036a9db 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -138,6 +138,10 @@ class SymbolTable {
callback(pair.second);
}
+ DefinedRegular *loadConfigSym = nullptr;
+ uint32_t loadConfigSize = 0;
+ void initializeLoadConfig();
+
private:
/// Given a name without "__imp_" prefix, returns a defined symbol
/// with the "__imp_" prefix, if it exists.
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 3c6112b7fc89ad..5946c2944aa212 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -282,7 +282,8 @@ class Writer {
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;
@@ -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 =
@@ -2649,39 +2638,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 +2669,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'";
diff --git a/lld/test/COFF/arm64x-loadconfig.s b/lld/test/COFF/arm64x-loadconfig.s
index 0d4fe0ed6d6e0a..6023828a2746f7 100644
--- a/lld/test/COFF/arm64x-loadconfig.s
+++ b/lld/test/COFF/arm64x-loadconfig.s
@@ -4,6 +4,7 @@
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig.s -o loadconfig.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig-short.s -o loadconfig-short.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows loadconfig-short.s -o loadconfig-short-arm64ec.obj
// RUN: lld-link -machine:arm64x -out:out.dll -dll -noentry loadconfig.obj test.obj
@@ -43,6 +44,7 @@
// HEADERS-NEXT: VirtualSize: 0x38
// RUN: lld-link -machine:arm64x -out:out-short.dll -dll -noentry loadconfig-short.obj 2>&1 | FileCheck --check-prefix=WARN-RELOC-SIZE %s
+// RUN: lld-link -machine:arm64x -out:out-short.dll -dll -noentry loadconfig-short-arm64ec.obj 2>&1 | FileCheck --check-prefix=WARN-RELOC-SIZE %s
// WARN-RELOC-SIZE: lld-link: warning: '_load_config_used' structure too small to include dynamic relocations
#--- test.s
diff --git a/lld/test/COFF/guard-warnings.s b/lld/test/COFF/guard-warnings.s
index 77448ee95c0095..092871597d1f80 100644
--- a/lld/test/COFF/guard-warnings.s
+++ b/lld/test/COFF/guard-warnings.s
@@ -38,7 +38,7 @@
# RUN: llvm-mc -triple x86_64-windows-msvc %t/loadcfg-misaligned2.s -filetype=obj -o %t/loadcfg-misaligned2.obj
# RUN: lld-link %t/main.obj %t/loadcfg-misaligned2.obj -guard:cf,longjmp,ehcont -out:%t-misaligned2.exe -entry:main %basename_t-exp.lib 2>&1 | FileCheck %s --check-prefix=WARN_ALIGN2
-# WARN_ALIGN2: warning: '_load_config_used' is misaligned (RVA is 0x{{[0-9A-F]*}}2 not aligned to 8 bytes)
+# WARN_ALIGN2: warning: '_load_config_used' is misaligned (section offset is 0x{{[0-9A-F]*}}2 not aligned to 8 bytes)
# RUN: llvm-mc -triple x86_64-windows-msvc %t/loadcfg-full.s -filetype=obj -o %t/loadcfg-full.obj
# RUN: lld-link %t/main.obj %t/loadcfg-full.obj -guard:cf,longjmp,ehcont -out:%t.exe -entry:main %basename_t-exp.lib 2>&1 | FileCheck %s --check-prefix=NOWARN --allow-empty
diff --git a/lld/test/COFF/loadcfg-short.test b/lld/test/COFF/loadcfg-short.test
new file mode 100644
index 00000000000000..dd4d4389ddc1cc
--- /dev/null
+++ b/lld/test/COFF/loadcfg-short.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used section chunk is too small
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: '030000'
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/loadcfg-size.test b/lld/test/COFF/loadcfg-size.test
new file mode 100644
index 00000000000000..871590f2328b63
--- /dev/null
+++ b/lld/test/COFF/loadcfg-size.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used specifies a size larger than its containing section chunk
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: '0c00000000000000'
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/loadcfg-uninitialized.test b/lld/test/COFF/loadcfg-uninitialized.test
new file mode 100644
index 00000000000000..5f956bc7224bc9
--- /dev/null
+++ b/lld/test/COFF/loadcfg-uninitialized.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used points to uninitialized data
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ VirtualSize: 0x140
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
|
@llvm/pr-subscribers-lld Author: Jacek Caban (cjacek) ChangesFull diff: https://github.com/llvm/llvm-project/pull/120326.diff 9 Files Affected:
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index bef55abb7f856e..9d45e9b926b1f6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2822,6 +2822,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (ctx.symtabEC)
ctx.symtabEC->initializeECThunks();
+ ctx.forEachSymtab([](SymbolTable &symtab) { symtab.initializeLoadConfig(); });
// Identify unreferenced COMDAT sections.
if (config->doGC) {
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 6b3375e13e8393..7e243fc626d38d 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 {
@@ -595,6 +596,52 @@ 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 (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});
}
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index b694893b903aa3..8548a6d036a9db 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -138,6 +138,10 @@ class SymbolTable {
callback(pair.second);
}
+ DefinedRegular *loadConfigSym = nullptr;
+ uint32_t loadConfigSize = 0;
+ void initializeLoadConfig();
+
private:
/// Given a name without "__imp_" prefix, returns a defined symbol
/// with the "__imp_" prefix, if it exists.
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 3c6112b7fc89ad..5946c2944aa212 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -282,7 +282,8 @@ class Writer {
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;
@@ -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 =
@@ -2649,39 +2638,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 +2669,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'";
diff --git a/lld/test/COFF/arm64x-loadconfig.s b/lld/test/COFF/arm64x-loadconfig.s
index 0d4fe0ed6d6e0a..6023828a2746f7 100644
--- a/lld/test/COFF/arm64x-loadconfig.s
+++ b/lld/test/COFF/arm64x-loadconfig.s
@@ -4,6 +4,7 @@
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig.s -o loadconfig.obj
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig-short.s -o loadconfig-short.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows loadconfig-short.s -o loadconfig-short-arm64ec.obj
// RUN: lld-link -machine:arm64x -out:out.dll -dll -noentry loadconfig.obj test.obj
@@ -43,6 +44,7 @@
// HEADERS-NEXT: VirtualSize: 0x38
// RUN: lld-link -machine:arm64x -out:out-short.dll -dll -noentry loadconfig-short.obj 2>&1 | FileCheck --check-prefix=WARN-RELOC-SIZE %s
+// RUN: lld-link -machine:arm64x -out:out-short.dll -dll -noentry loadconfig-short-arm64ec.obj 2>&1 | FileCheck --check-prefix=WARN-RELOC-SIZE %s
// WARN-RELOC-SIZE: lld-link: warning: '_load_config_used' structure too small to include dynamic relocations
#--- test.s
diff --git a/lld/test/COFF/guard-warnings.s b/lld/test/COFF/guard-warnings.s
index 77448ee95c0095..092871597d1f80 100644
--- a/lld/test/COFF/guard-warnings.s
+++ b/lld/test/COFF/guard-warnings.s
@@ -38,7 +38,7 @@
# RUN: llvm-mc -triple x86_64-windows-msvc %t/loadcfg-misaligned2.s -filetype=obj -o %t/loadcfg-misaligned2.obj
# RUN: lld-link %t/main.obj %t/loadcfg-misaligned2.obj -guard:cf,longjmp,ehcont -out:%t-misaligned2.exe -entry:main %basename_t-exp.lib 2>&1 | FileCheck %s --check-prefix=WARN_ALIGN2
-# WARN_ALIGN2: warning: '_load_config_used' is misaligned (RVA is 0x{{[0-9A-F]*}}2 not aligned to 8 bytes)
+# WARN_ALIGN2: warning: '_load_config_used' is misaligned (section offset is 0x{{[0-9A-F]*}}2 not aligned to 8 bytes)
# RUN: llvm-mc -triple x86_64-windows-msvc %t/loadcfg-full.s -filetype=obj -o %t/loadcfg-full.obj
# RUN: lld-link %t/main.obj %t/loadcfg-full.obj -guard:cf,longjmp,ehcont -out:%t.exe -entry:main %basename_t-exp.lib 2>&1 | FileCheck %s --check-prefix=NOWARN --allow-empty
diff --git a/lld/test/COFF/loadcfg-short.test b/lld/test/COFF/loadcfg-short.test
new file mode 100644
index 00000000000000..dd4d4389ddc1cc
--- /dev/null
+++ b/lld/test/COFF/loadcfg-short.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used section chunk is too small
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: '030000'
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/loadcfg-size.test b/lld/test/COFF/loadcfg-size.test
new file mode 100644
index 00000000000000..871590f2328b63
--- /dev/null
+++ b/lld/test/COFF/loadcfg-size.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used specifies a size larger than its containing section chunk
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: '0c00000000000000'
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/loadcfg-uninitialized.test b/lld/test/COFF/loadcfg-uninitialized.test
new file mode 100644
index 00000000000000..5f956bc7224bc9
--- /dev/null
+++ b/lld/test/COFF/loadcfg-uninitialized.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: not lld-link -out:%t.dll %t.obj -dll -noentry 2>&1 | FileCheck %s
+# CHECK: lld-link: error: _load_config_used points to uninitialized data
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ VirtualSize: 0x140
+symbols:
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
|
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.
LGTM
1693c46
to
878f226
Compare
No description provided.