[lld] r362579 - Read .note.gnu.property sections and emit a merged .note.gnu.property section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 4 20:04:47 PDT 2019


Author: ruiu
Date: Tue Jun  4 20:04:46 2019
New Revision: 362579

URL: http://llvm.org/viewvc/llvm-project?rev=362579&view=rev
Log:
Read .note.gnu.property sections and emit a merged .note.gnu.property section.

This patch also adds `--require-cet` option for the sake of testing.
The actual feature for IBT-aware PLT is not included in this patch.

This is a part of https://reviews.llvm.org/D59780. Submitting this
first should make it easy to work with a related change
(https://reviews.llvm.org/D62609).

Differential Revision: https://reviews.llvm.org/D62853

Added:
    lld/trunk/test/ELF/Inputs/i386-cet1.s
    lld/trunk/test/ELF/Inputs/i386-cet2.s
    lld/trunk/test/ELF/Inputs/i386-cet3.s
    lld/trunk/test/ELF/Inputs/i386-cet4.s
    lld/trunk/test/ELF/Inputs/x86-64-cet1.s
    lld/trunk/test/ELF/Inputs/x86-64-cet2.s
    lld/trunk/test/ELF/Inputs/x86-64-cet3.s
    lld/trunk/test/ELF/Inputs/x86-64-cet4.s
    lld/trunk/test/ELF/i386-cet.s
    lld/trunk/test/ELF/x86-64-cet.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Tue Jun  4 20:04:46 2019
@@ -82,6 +82,7 @@ struct VersionDefinition {
 // Most fields are initialized by the driver.
 struct Configuration {
   uint8_t OSABI = 0;
+  uint32_t AndFeatures = 0;
   llvm::CachePruningPolicy ThinLTOCachePolicy;
   llvm::StringMap<uint64_t> SectionStartMap;
   llvm::StringRef Chroot;
@@ -147,6 +148,7 @@ struct Configuration {
   bool ExportDynamic;
   bool FixCortexA53Errata843419;
   bool FormatBinary = false;
+  bool RequireCET;
   bool GcSections;
   bool GdbIndex;
   bool GnuHash = false;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Jun  4 20:04:46 2019
@@ -334,6 +334,9 @@ static void checkOptions() {
     if (Config->SingleRoRx && !Script->HasSectionsCommand)
       error("-execute-only and -no-rosegment cannot be used together");
   }
+
+  if (Config->ZRetpolineplt && Config->RequireCET)
+    error("--require-cet may not be used with -z retpolineplt");
 }
 
 static const char *getReproduceOption(opt::InputArgList &Args) {
@@ -813,6 +816,7 @@ static void readConfigs(opt::InputArgLis
   Config->FilterList = args::getStrings(Args, OPT_filter);
   Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
   Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419);
+  Config->RequireCET = Args.hasArg(OPT_require_cet);
   Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
   Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
   Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
@@ -1584,6 +1588,30 @@ static void wrapSymbols(ArrayRef<Wrapped
     Symtab->wrap(W.Sym, W.Real, W.Wrap);
 }
 
+// To enable CET (x86's hardware-assited control flow enforcement), each
+// source file must be compiled with -fcf-protection. Object files compiled
+// with the flag contain feature flags indicating that they are compatible
+// with CET. We enable the feature only when all object files are compatible
+// with CET.
+//
+// This function returns the merged feature flags. If 0, we cannot enable CET.
+//
+// Note that the CET-aware PLT is not implemented yet. We do error
+// check only.
+template <class ELFT> static uint32_t getAndFeatures() {
+  if (Config->EMachine != EM_386 && Config->EMachine != EM_X86_64)
+    return 0;
+
+  uint32_t Ret = -1;
+  for (InputFile *F : ObjectFiles) {
+    uint32_t Features = cast<ObjFile<ELFT>>(F)->AndFeatures;
+    if (!Features && Config->RequireCET)
+      error(toString(F) + ": --require-cet: file is not compatible with CET");
+    Ret &= Features;
+  }
+  return Ret;
+}
+
 static const char *LibcallRoutineNames[] = {
 #define HANDLE_LIBCALL(code, name) name,
 #include "llvm/IR/RuntimeLibcalls.def"
@@ -1762,6 +1790,10 @@ template <class ELFT> void LinkerDriver:
            (S->Name.startswith(".debug") || S->Name.startswith(".zdebug"));
   });
 
+  // Read .note.gnu.property sections from input object files which
+  // contain a hint to tweak linker's and loader's behaviors.
+  Config->AndFeatures = getAndFeatures<ELFT>();
+
   Config->EFlags = Target->calcEFlags();
   // MaxPageSize (sometimes called abi page size) is the maximum page size that
   // the output can be run on. For example if the OS can use 4k or 64k page

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Jun  4 20:04:46 2019
@@ -25,6 +25,7 @@
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Support/ARMAttributeParser.h"
 #include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TarWriter.h"
 #include "llvm/Support/raw_ostream.h"
@@ -34,6 +35,7 @@ using namespace llvm::ELF;
 using namespace llvm::object;
 using namespace llvm::sys;
 using namespace llvm::sys::fs;
+using namespace llvm::support::endian;
 
 using namespace lld;
 using namespace lld::elf;
@@ -753,6 +755,68 @@ static void updateSupportedARMFeatures(c
   }
 }
 
+// If a source file is compiled with x86 hardware-assisted call flow control
+// enabled, the generated object file contains feature flags indicating that
+// fact. This function reads the feature flags and returns it.
+//
+// Essentially we want to read a single 32-bit value in this function, but this
+// function is rather complicated because the value is buried deep inside a
+// .note.gnu.property section.
+//
+// The section consists of one or more NOTE records. Each NOTE record consists
+// of zero or more type-length-value fields. We want to find a field of a
+// certain type. It seems a bit too much to just store a 32-bit value, perhaps
+// the ABI is unnecessarily complicated.
+template <class ELFT>
+static uint32_t readAndFeatures(ObjFile<ELFT> *Obj, ArrayRef<uint8_t> Data) {
+  using Elf_Nhdr = typename ELFT::Nhdr;
+  using Elf_Note = typename ELFT::Note;
+
+  while (!Data.empty()) {
+    // Read one NOTE record.
+    if (Data.size() < sizeof(Elf_Nhdr))
+      fatal(toString(Obj) + ": .note.gnu.property: section too short");
+
+    auto *Nhdr = reinterpret_cast<const Elf_Nhdr *>(Data.data());
+    if (Data.size() < Nhdr->getSize())
+      fatal(toString(Obj) + ": .note.gnu.property: section too short");
+
+    Elf_Note Note(*Nhdr);
+    if (Nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || Note.getName() != "GNU") {
+      Data = Data.slice(Nhdr->getSize());
+      continue;
+    }
+
+    // Read a body of a NOTE record, which consists of type-length-value fields.
+    ArrayRef<uint8_t> Desc = Note.getDesc();
+    while (!Desc.empty()) {
+      if (Desc.size() < 8)
+        fatal(toString(Obj) + ": .note.gnu.property: section too short");
+
+      uint32_t Type = read32le(Desc.data());
+      uint32_t Size = read32le(Desc.data() + 4);
+
+      if (Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
+        // We found the field.
+        return read32le(Desc.data() + 8);
+      }
+
+      // On 64-bit, a payload may be followed by a 4-byte padding to make its
+      // size a multiple of 8.
+      if (ELFT::Is64Bits)
+        Size = alignTo(Size, 8);
+
+      Desc = Desc.slice(Size + 8); // +8 for Type and Size
+    }
+
+    // Go to next NOTE record if a note section didn't contain
+    // X86_FEATURES_1_AND description.
+    Data = Data.slice(Nhdr->getSize());
+  }
+
+  return 0;
+}
+
 template <class ELFT>
 InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
   uint32_t Idx = Sec.sh_info;
@@ -901,6 +965,19 @@ InputSectionBase *ObjFile<ELFT>::createI
   if (Name == ".note.GNU-stack")
     return &InputSection::Discarded;
 
+  // If an object file is compatible with Intel Control-Flow Enforcement
+  // Technology (CET), it has a .note.gnu.property section containing the
+  // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag.
+  //
+  // Since we merge bitmaps from multiple object files to create a new
+  // .note.gnu.property containing a single AND'ed bitmap, we discard an input
+  // file's .note.gnu.property section.
+  if (Name == ".note.gnu.property") {
+    ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));
+    this->AndFeatures = readAndFeatures(this, Contents);
+    return &InputSection::Discarded;
+  }
+
   // Split stacks is a feature to support a discontiguous stack,
   // commonly used in the programming language Go. For the details,
   // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Tue Jun  4 20:04:46 2019
@@ -228,6 +228,8 @@ public:
   // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
   uint32_t MipsGp0 = 0;
 
+  uint32_t AndFeatures = 0;
+
   // Name of source file obtained from STT_FILE symbol value,
   // or empty string if there is no such symbol in object file
   // symbol table.

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Tue Jun  4 20:04:46 2019
@@ -171,6 +171,10 @@ defm fini: Eq<"fini", "Specify a finaliz
 def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,
   HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">;
 
+// This option is intentionally hidden from the user as the implementation
+// is not complete.
+def require_cet: F<"require-cet">;
+
 defm format: Eq<"format", "Change the input format of the inputs following this option">,
   MetaVarName<"[default,elf,binary]">;
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Tue Jun  4 20:04:46 2019
@@ -288,6 +288,35 @@ static size_t getHashSize() {
   }
 }
 
+// This class represents a linker-synthesized .note.gnu.property section.
+//
+// In x86, object files may contain feature flags indicating the features that
+// they are using. The flags are stored in a .note.gnu.property section.
+//
+// lld reads the sections from input files and merges them by computing AND of
+// the flags. The result is written as a new .note.gnu.property section.
+//
+// If the flag is zero (which indicates that the intersection of the feature
+// sets is empty, or some input files didn't have .note.gnu.property sections),
+// we don't create this section.
+GnuPropertySection::GnuPropertySection()
+    : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, 4,
+                       ".note.gnu.property") {}
+
+void GnuPropertySection::writeTo(uint8_t *Buf) {
+  write32(Buf, 4);                                   // Name size
+  write32(Buf + 4, Config->Is64 ? 16 : 12);          // Content size
+  write32(Buf + 8, NT_GNU_PROPERTY_TYPE_0);          // Type
+  memcpy(Buf + 12, "GNU", 4);                        // Name string
+  write32(Buf + 16, GNU_PROPERTY_X86_FEATURE_1_AND); // Feature type
+  write32(Buf + 20, 4);                              // Feature size
+  write32(Buf + 24, Config->AndFeatures);            // Feature flags
+  if (Config->Is64)
+    write32(Buf + 28, 0); // Padding
+}
+
+size_t GnuPropertySection::getSize() const { return Config->Is64 ? 32 : 28; }
+
 BuildIdSection::BuildIdSection()
     : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"),
       HashSize(getHashSize()) {}

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Tue Jun  4 20:04:46 2019
@@ -147,6 +147,13 @@ public:
   size_t getSize() const override { return 0; }
 };
 
+class GnuPropertySection : public SyntheticSection {
+public:
+  GnuPropertySection();
+  void writeTo(uint8_t *Buf) override;
+  size_t getSize() const override;
+};
+
 // .note.gnu.build-id section.
 class BuildIdSection : public SyntheticSection {
   // First 16 bytes are a header.

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=362579&r1=362578&r2=362579&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Jun  4 20:04:46 2019
@@ -433,6 +433,9 @@ template <class ELFT> static void create
   In.Iplt = make<PltSection>(true);
   Add(In.Iplt);
 
+  if (Config->AndFeatures)
+    Add(make<GnuPropertySection>());
+
   // .note.GNU-stack is always added when we are creating a re-linkable
   // object file. Other linkers are using the presence of this marker
   // section to control the executable-ness of the stack area, but that

Added: lld/trunk/test/ELF/Inputs/i386-cet1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/i386-cet1.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/i386-cet1.s (added)
+++ lld/trunk/test/ELF/Inputs/i386-cet1.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,16 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 12
+.long 5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 3
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/i386-cet2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/i386-cet2.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/i386-cet2.s (added)
+++ lld/trunk/test/ELF/Inputs/i386-cet2.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,20 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 24
+.long 5
+.asciz "GNU"
+
+.long 0xc0000000
+.long 4
+.long 0
+
+.long 0xc0000002
+.long 4
+.long 3
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/i386-cet3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/i386-cet3.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/i386-cet3.s (added)
+++ lld/trunk/test/ELF/Inputs/i386-cet3.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,5 @@
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/i386-cet4.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/i386-cet4.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/i386-cet4.s (added)
+++ lld/trunk/test/ELF/Inputs/i386-cet4.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,16 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 12
+.long 5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 0xfffffffd
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/x86-64-cet1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-cet1.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-cet1.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-cet1.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,17 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 16
+.long 5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 3
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/x86-64-cet2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-cet2.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-cet2.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-cet2.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,22 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 32
+.long 5
+.asciz "GNU"
+
+.long 0xc0000000
+.long 4
+.long 0
+.long 0
+
+.long 0xc0000002
+.long 4
+.long 3
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/x86-64-cet3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-cet3.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-cet3.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-cet3.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,5 @@
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/Inputs/x86-64-cet4.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/x86-64-cet4.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/x86-64-cet4.s (added)
+++ lld/trunk/test/ELF/Inputs/x86-64-cet4.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,17 @@
+.section ".note.gnu.property", "a"
+.align 4
+.long 4
+.long 16
+.long 5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 0xfffffffd
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  ret

Added: lld/trunk/test/ELF/i386-cet.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/i386-cet.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/i386-cet.s (added)
+++ lld/trunk/test/ELF/i386-cet.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,48 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet1.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet2.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet3.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet4.s -o %t4.o
+
+# RUN: ld.lld -e func1 %t.o %t1.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
+
+# RUN: ld.lld -e func1 %t.o %t2.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
+
+# CET: Properties: x86 feature: IBT, SHSTK
+
+# RUN: ld.lld -e func1 %t.o %t3.o -o %t
+# RUN: llvm-readelf -S %t | FileCheck -check-prefix=NOCET %s
+
+# NOCET:     Section Headers
+# NOCET-NOT: .note.gnu.property
+
+# RUN: not ld.lld -e func1 %t.o %t3.o -o %t --require-cet 2>&1 \
+# RUN:   | FileCheck -check-prefix=ERROR %s
+# ERROR: i386-cet.s.tmp3.o: --require-cet: file is not compatible with CET
+
+# RUN: ld.lld -e func1 %t.o %t4.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=NOSHSTK -match-full-lines %s
+
+# Check .note.gnu.protery without property SHSTK.
+# NOSHSTK: Properties: x86 feature: IBT
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 3
+.long 0
+
+.text
+.globl func1
+.type func1, at function
+func1:
+  call func2
+  ret

Added: lld/trunk/test/ELF/x86-64-cet.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-cet.s?rev=362579&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-cet.s (added)
+++ lld/trunk/test/ELF/x86-64-cet.s Tue Jun  4 20:04:46 2019
@@ -0,0 +1,48 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet1.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet2.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet3.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet4.s -o %t4.o
+
+# RUN: ld.lld -e func1 %t.o %t1.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
+
+# RUN: ld.lld -e func1 %t.o %t2.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
+
+# CET: Properties: x86 feature: IBT, SHSTK
+
+# RUN: ld.lld -e func1 %t.o %t3.o -o %t
+# RUN: llvm-readelf -S %t | FileCheck -check-prefix=NOCET %s
+
+# NOCET:     Section Headers
+# NOCET-NOT: .note.gnu.property
+
+# RUN: not ld.lld -e func1 %t.o %t3.o -o %t --require-cet 2>&1 \
+# RUN:   | FileCheck -check-prefix=ERROR %s
+# ERROR: x86-64-cet.s.tmp3.o: --require-cet: file is not compatible with CET
+
+# RUN: ld.lld -e func1 %t.o %t4.o -o %t
+# RUN: llvm-readelf -n %t | FileCheck -check-prefix=NOSHSTK -match-full-lines %s
+
+# Check .note.gnu.protery without property SHSTK.
+# NOSHSTK: Properties: x86 feature: IBT
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000002
+.long 4
+.long 3
+.long 0
+
+.text
+.globl func1
+.type func1, at function
+func1:
+  call func2
+  ret




More information about the llvm-commits mailing list