IdataContents Idata;
DelayLoadContents DelayIdata;
EdataContents Edata;
- RVATableChunk *GuardFidsTable = nullptr;
- RVATableChunk *SEHTable = nullptr;
+ bool SetNoSEHCharacteristic = false;
DebugDirectoryChunk *DebugDirectory = nullptr;
std::vector<Chunk *> DebugRecords;
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
if (Config->GuardCF != GuardCFLevel::Off)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
- if (Config->Machine == I386 && !SEHTable &&
- !Symtab->findUnderscore("_load_config_used"))
+ if (SetNoSEHCharacteristic)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
if (Config->TerminalServerAware)
PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
}
void Writer::createSEHTable() {
+ // Set the no SEH characteristic on x86 binaries unless we find exception
+ // handlers.
+ SetNoSEHCharacteristic = true;
+
SymbolRVASet Handlers;
for (ObjFile *File : ObjFile::Instances) {
// FIXME: We should error here instead of earlier unless /safeseh:no was
markSymbolsForRVATable(File, File->getSXDataChunks(), Handlers);
}
+ // Remove the "no SEH" characteristic if all object files were built with
+ // safeseh, we found some exception handlers, and there is a load config in
+ // the object.
+ SetNoSEHCharacteristic =
+ Handlers.empty() || !Symtab->findUnderscore("_load_config_used");
+
maybeAddRVATable(std::move(Handlers), "__safe_se_handler_table",
"__safe_se_handler_count");
}
--- /dev/null
+# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj
+# RUN: lld-link %t.obj -safeseh -out:%t.exe -entry:main
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# This object lacks a _load_config_used global, so we set
+# IMAGE_DLL_CHARACTERISTICS_NO_SEH even though there is an exception handler.
+# This is a more secure default. If someone wants to use a CRT without a load
+# config and they want to use 32-bit SEH, they will need to provide a
+# safeseh-compatible load config.
+
+# CHECK-LABEL: Characteristics [
+# CHECK: IMAGE_DLL_CHARACTERISTICS_NO_SEH
+# CHECK: ]
+
+# CHECK-LABEL: DataDirectory {
+# CHECK: LoadConfigTableRVA: 0x0
+# CHECK: LoadConfigTableSize: 0x0
+# CHECK: }
+
+# CHECK-NOT: LoadConfig
+# CHECK-NOT: SEHTable
+
+ .def @feat.00;
+ .scl 3;
+ .type 0;
+ .endef
+ .globl @feat.00
+@feat.00 = 1
+
+ .text
+ .def _main; .scl 2; .type 32; .endef
+ .globl _main
+_main:
+ pushl $_my_handler
+ movl $42, %eax
+ popl %ecx
+ ret
+
+ .def _my_handler; .scl 3; .type 32; .endef
+_my_handler:
+ ret
+
+.safeseh _my_handler
# __safe_se_handler_table needs to be relocated against ImageBase.
# check that the relocation is present.
+#
# CHECK-NOGC-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH
# CHECK-NOGC: BaseReloc [
# CHECK-NOGC: Entry {
# CHECK-NOGC-NEXT: 0x401006
# CHECK-NOGC-NEXT: ]
-# Without the SEH table, the address is absolute, so check that we do
-# not have a relocation for it.
-# CHECK-GC-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH
+# If we enable GC, the exception handler should be removed, and we should add
+# the DLL characteristic flag that indicates that there are no exception
+# handlers in this DLL. The exception handler table in the load config should
+# be empty and there should be no relocations for it.
+#
+# CHECK-GC: Characteristics [
+# CHECK-GC: IMAGE_DLL_CHARACTERISTICS_NO_SEH
+# CHECK-GC: ]
# CHECK-GC: BaseReloc [
# CHECK-GC-NEXT: ]
# CHECK-GC: LoadConfig [