[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