--- /dev/null
+; RUN: llvm-ml -m32 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
+; RUN: llvm-ml -m64 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
+
+; RUN: llvm-ml -m32 -safeseh -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-SAFESEH
+; RUN: llvm-ml -m64 -safeseh -filetype=obj %s -o %t.obj 2>&1 | FileCheck %s --check-prefix=CHECK-SAFESEH64
+; RUN: llvm-readobj --syms %t.obj | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
+
+; CHECK-SAFESEH64: warning: /safeseh applies only to 32-bit X86 platforms; ignoring.
+
+.code
+noop:
+ ret
+end
+
+; CHECK-OBJ: Symbol {
+; CHECK-OBJ: Name: @feat.00
+; CHECK-OBJ-NOSAFESEH: Value: 2
+; CHECK-OBJ-SAFESEH: Value: 3
+; CHECK-OBJ-NEXT: Section: IMAGE_SYM_ABSOLUTE
+; CHECK-OBJ-NEXT: BaseType: Null
+; CHECK-OBJ-NEXT: ComplexType: Null
+; CHECK-OBJ-NEXT: StorageClass: External
+; CHECK-OBJ-NEXT: AuxSymbolCount: 0
+; CHECK-OBJ-NEXT: }
--- /dev/null
+; RUN: llvm-ml -m32 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
+; RUN: llvm-ml -m64 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
+; RUN: llvm-ml -m32 -safeseh -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
+
+.code
+
+@feat.00 = 99
+
+noop:
+ ret
+end
+
+; CHECK: Symbol {
+; CHECK: Name: @feat.00
+; CHECK: Value: 99
+; CHECK-NEXT: Section: IMAGE_SYM_ABSOLUTE
+; CHECK-NEXT: BaseType: Null
+; CHECK-NEXT: ComplexType: Null
+; CHECK-NEXT: StorageClass: Static
+; CHECK-NEXT: AuxSymbolCount: 0
+; CHECK-NEXT: }
cl::values(clEnumVal(m32, "32-bit"),
clEnumVal(m64, "64-bit (default)")));
+static cl::opt<bool> SafeSEH(
+ "safeseh",
+ cl::desc("Mark resulting object files as either containing no "
+ "exception handlers or containing exception handlers that "
+ "are all declared with .SAFESEH. Only available in 32-bit."));
+
static cl::opt<std::string>
TripleName("triple", cl::desc("Target triple to assemble for, "
"see -version for available targets"));
MCAsmInfo &MAI, MCSubtargetInfo &STI,
MCInstrInfo &MCII, MCTargetOptions &MCOptions) {
std::unique_ptr<MCAsmParser> Parser(
- createMCMasmParser(SrcMgr, Ctx, Str, MAI));
+ createMCMasmParser(SrcMgr, Ctx, Str, MAI, 0));
std::unique_ptr<MCTargetAsmParser> TAP(
TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
// construct the Triple object.
Triple TheTriple(TripleName);
+ if (SafeSEH && !(TheTriple.isArch32Bit() && TheTriple.isX86())) {
+ WithColor::warning()
+ << "/safeseh applies only to 32-bit X86 platforms; ignoring.\n";
+ SafeSEH = false;
+ }
+
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (std::error_code EC = BufferPtr.getError()) {
/*DWARFMustBeAtTheEnd*/ false));
}
+ if (TheTriple.isOSBinFormatCOFF()) {
+ // Emit an absolute @feat.00 symbol. This is a features bitfield read by
+ // link.exe.
+ int64_t Feat00Flags = 0x2;
+ if (SafeSEH) {
+ // According to the PE-COFF spec, the LSB of this value marks the object
+ // for "registered SEH". This means that all SEH handler entry points
+ // must be registered in .sxdata. Use of any unregistered handlers will
+ // cause the process to terminate immediately.
+ Feat00Flags |= 0x1;
+ }
+ MCSymbol *Feat00Sym = Ctx.getOrCreateSymbol("@feat.00");
+ Feat00Sym->setRedefinable(true);
+ Str->emitSymbolAttribute(Feat00Sym, MCSA_Global);
+ Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx));
+ }
+
// Use Assembler information for parsing.
Str->setUseAssemblerInfoForParsing(true);