[llvm] 13f701b - [ms] [llvm-ml] Create the @feat.00 symbol, and populate it appropriately

Eric Astor via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 14:02:42 PDT 2020


Author: Eric Astor
Date: 2020-09-29T17:02:27-04:00
New Revision: 13f701b99ca1e0786258ef05b0439d4893aac8cb

URL: https://github.com/llvm/llvm-project/commit/13f701b99ca1e0786258ef05b0439d4893aac8cb
DIFF: https://github.com/llvm/llvm-project/commit/13f701b99ca1e0786258ef05b0439d4893aac8cb.diff

LOG: [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

Added: 
    llvm/test/tools/llvm-ml/feat00.test
    llvm/test/tools/llvm-ml/feat00_override.test

Modified: 
    llvm/tools/llvm-ml/llvm-ml.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-ml/feat00.test b/llvm/test/tools/llvm-ml/feat00.test
new file mode 100644
index 000000000000..1b5070e8c86a
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/feat00.test
@@ -0,0 +1,24 @@
+; 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:  }

diff  --git a/llvm/test/tools/llvm-ml/feat00_override.test b/llvm/test/tools/llvm-ml/feat00_override.test
new file mode 100644
index 000000000000..358fc8566081
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/feat00_override.test
@@ -0,0 +1,21 @@
+; 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
+
+ at 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:  }

diff  --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp
index 3a3984286e4a..1586870e0855 100644
--- a/llvm/tools/llvm-ml/llvm-ml.cpp
+++ b/llvm/tools/llvm-ml/llvm-ml.cpp
@@ -99,6 +99,12 @@ cl::opt<BitnessType> Bitness(cl::desc("Choose bitness:"), cl::init(m64),
                              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"));
@@ -195,7 +201,7 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget,
                          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));
 
@@ -240,6 +246,12 @@ int main(int argc, char **argv) {
   // 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()) {
@@ -354,6 +366,23 @@ int main(int argc, char **argv) {
         /*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);
 


        


More information about the llvm-commits mailing list