Skip to content

Commit 13f701b

Browse files
committed
[ms] [llvm-ml] Create the @feat.00 symbol, and populate it appropriately
@feat.00 is a bitfield read by Microsoft-style linkers, and is required to signal (e.g.) /safeseh support on 32-bit systems. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D88451
1 parent feb7453 commit 13f701b

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

llvm/test/tools/llvm-ml/feat00.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-ml -m32 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
2+
; RUN: llvm-ml -m64 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
3+
4+
; RUN: llvm-ml -m32 -safeseh -filetype=obj %s | llvm-readobj --syms - | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-SAFESEH
5+
; RUN: llvm-ml -m64 -safeseh -filetype=obj %s -o %t.obj 2>&1 | FileCheck %s --check-prefix=CHECK-SAFESEH64
6+
; RUN: llvm-readobj --syms %t.obj | FileCheck %s --check-prefix=CHECK-OBJ --check-prefix=CHECK-OBJ-NOSAFESEH
7+
8+
; CHECK-SAFESEH64: warning: /safeseh applies only to 32-bit X86 platforms; ignoring.
9+
10+
.code
11+
noop:
12+
ret
13+
end
14+
15+
; CHECK-OBJ: Symbol {
16+
; CHECK-OBJ: Name: @feat.00
17+
; CHECK-OBJ-NOSAFESEH: Value: 2
18+
; CHECK-OBJ-SAFESEH: Value: 3
19+
; CHECK-OBJ-NEXT: Section: IMAGE_SYM_ABSOLUTE
20+
; CHECK-OBJ-NEXT: BaseType: Null
21+
; CHECK-OBJ-NEXT: ComplexType: Null
22+
; CHECK-OBJ-NEXT: StorageClass: External
23+
; CHECK-OBJ-NEXT: AuxSymbolCount: 0
24+
; CHECK-OBJ-NEXT: }
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: llvm-ml -m32 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
2+
; RUN: llvm-ml -m64 -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
3+
; RUN: llvm-ml -m32 -safeseh -filetype=obj %s | llvm-readobj --syms - | FileCheck %s
4+
5+
.code
6+
7+
@feat.00 = 99
8+
9+
noop:
10+
ret
11+
end
12+
13+
; CHECK: Symbol {
14+
; CHECK: Name: @feat.00
15+
; CHECK: Value: 99
16+
; CHECK-NEXT: Section: IMAGE_SYM_ABSOLUTE
17+
; CHECK-NEXT: BaseType: Null
18+
; CHECK-NEXT: ComplexType: Null
19+
; CHECK-NEXT: StorageClass: Static
20+
; CHECK-NEXT: AuxSymbolCount: 0
21+
; CHECK-NEXT: }

llvm/tools/llvm-ml/llvm-ml.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ cl::opt<BitnessType> Bitness(cl::desc("Choose bitness:"), cl::init(m64),
9999
cl::values(clEnumVal(m32, "32-bit"),
100100
clEnumVal(m64, "64-bit (default)")));
101101

102+
static cl::opt<bool> SafeSEH(
103+
"safeseh",
104+
cl::desc("Mark resulting object files as either containing no "
105+
"exception handlers or containing exception handlers that "
106+
"are all declared with .SAFESEH. Only available in 32-bit."));
107+
102108
static cl::opt<std::string>
103109
TripleName("triple", cl::desc("Target triple to assemble for, "
104110
"see -version for available targets"));
@@ -195,7 +201,7 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget,
195201
MCAsmInfo &MAI, MCSubtargetInfo &STI,
196202
MCInstrInfo &MCII, MCTargetOptions &MCOptions) {
197203
std::unique_ptr<MCAsmParser> Parser(
198-
createMCMasmParser(SrcMgr, Ctx, Str, MAI));
204+
createMCMasmParser(SrcMgr, Ctx, Str, MAI, 0));
199205
std::unique_ptr<MCTargetAsmParser> TAP(
200206
TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
201207

@@ -240,6 +246,12 @@ int main(int argc, char **argv) {
240246
// construct the Triple object.
241247
Triple TheTriple(TripleName);
242248

249+
if (SafeSEH && !(TheTriple.isArch32Bit() && TheTriple.isX86())) {
250+
WithColor::warning()
251+
<< "/safeseh applies only to 32-bit X86 platforms; ignoring.\n";
252+
SafeSEH = false;
253+
}
254+
243255
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
244256
MemoryBuffer::getFileOrSTDIN(InputFilename);
245257
if (std::error_code EC = BufferPtr.getError()) {
@@ -354,6 +366,23 @@ int main(int argc, char **argv) {
354366
/*DWARFMustBeAtTheEnd*/ false));
355367
}
356368

369+
if (TheTriple.isOSBinFormatCOFF()) {
370+
// Emit an absolute @feat.00 symbol. This is a features bitfield read by
371+
// link.exe.
372+
int64_t Feat00Flags = 0x2;
373+
if (SafeSEH) {
374+
// According to the PE-COFF spec, the LSB of this value marks the object
375+
// for "registered SEH". This means that all SEH handler entry points
376+
// must be registered in .sxdata. Use of any unregistered handlers will
377+
// cause the process to terminate immediately.
378+
Feat00Flags |= 0x1;
379+
}
380+
MCSymbol *Feat00Sym = Ctx.getOrCreateSymbol("@feat.00");
381+
Feat00Sym->setRedefinable(true);
382+
Str->emitSymbolAttribute(Feat00Sym, MCSA_Global);
383+
Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx));
384+
}
385+
357386
// Use Assembler information for parsing.
358387
Str->setUseAssemblerInfoForParsing(true);
359388

0 commit comments

Comments
 (0)