[lld] r362793 - [ELF][AArch64] Support for BTI and PAC

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 7 06:00:17 PDT 2019


Author: psmith
Date: Fri Jun  7 06:00:17 2019
New Revision: 362793

URL: http://llvm.org/viewvc/llvm-project?rev=362793&view=rev
Log:
[ELF][AArch64] Support for BTI and PAC

Branch Target Identification (BTI) and Pointer Authentication (PAC) are
architecture features introduced in v8.5a and 8.3a respectively. The new
instructions have been added in the hint space so that binaries take
advantage of support where it exists yet still run on older hardware. The
impact of each feature is:

BTI: For executable pages that have been guarded, all indirect branches
must have a destination that is a BTI instruction of the appropriate type.
For the static linker, this means that PLT entries must have a "BTI c" as
the first instruction in the sequence. BTI is an all or nothing
property for a link unit, any indirect branch not landing on a valid
destination will cause a Branch Target Exception.

PAC: The dynamic loader encodes with PACIA the address of the destination
that the PLT entry will load from the .plt.got, placing the result in a
subset of the top-bits that are not valid virtual addresses. The PLT entry
may authenticate these top-bits using the AUTIA instruction before
branching to the destination. Use of PAC in PLT sequences is a contract
between the dynamic loader and the static linker, it is independent of
whether the relocatable objects use PAC.

BTI and PAC are independent features that can be combined. So we can have
several combinations of PLT:
- Standard with no BTI or PAC
- BTI PLT with "BTI c" as first instruction.
- PAC PLT with "AUTIA1716" before the indirect branch to X17.
- BTIPAC PLT with "BTI c" as first instruction and "AUTIA1716" before the
  first indirect branch to X17.
    
The use of BTI and PAC in relocatable object files are encoded by feature
bits in the .note.gnu.property section in a similar way to Intel CET. There
is one AArch64 specific program property GNU_PROPERTY_AARCH64_FEATURE_1_AND
and two target feature bits defined:
- GNU_PROPERTY_AARCH64_FEATURE_1_BTI
-- All executable sections are compatible with BTI.
- GNU_PROPERTY_AARCH64_FEATURE_1_PAC
-- All executable sections have return address signing enabled.

Due to the properties of FEATURE_1_AND the static linker can tell when all
input relocatable objects have the BTI and PAC feature bits set. The static
linker uses this to enable the appropriate PLT sequence.
Neither -> standard PLT
GNU_PROPERTY_AARCH64_FEATURE_1_BTI -> BTI PLT
GNU_PROPERTY_AARCH64_FEATURE_1_PAC -> PAC PLT
Both properties -> BTIPAC PLT

In addition to the .note.gnu.properties there are two new command line
options:
--force-bti : Act as if all relocatable inputs had
GNU_PROPERTY_AARCH64_FEATURE_1_BTI and warn for every relocatable object
that does not.
--pac-plt : Act as if all relocatable inputs had
GNU_PROPERTY_AARCH64_FEATURE_1_PAC. As PAC is a contract between the loader
and static linker no warning is given if it is not present in an input.

Two processor specific dynamic tags are used to communicate that a non
standard PLT sequence is being used.
DTI_AARCH64_BTI_PLT and DTI_AARCH64_BTI_PAC.

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


Added:
    lld/trunk/test/ELF/Inputs/aarch64-addrifunc.s
    lld/trunk/test/ELF/Inputs/aarch64-bti1.s
    lld/trunk/test/ELF/Inputs/aarch64-btipac1.s
    lld/trunk/test/ELF/Inputs/aarch64-func2.s
    lld/trunk/test/ELF/Inputs/aarch64-func3-bti.s
    lld/trunk/test/ELF/Inputs/aarch64-func3-btipac.s
    lld/trunk/test/ELF/Inputs/aarch64-func3-pac.s
    lld/trunk/test/ELF/Inputs/aarch64-func3.s
    lld/trunk/test/ELF/Inputs/aarch64-nobti.s
    lld/trunk/test/ELF/Inputs/aarch64-nopac.s
    lld/trunk/test/ELF/Inputs/aarch64-pac1.s
    lld/trunk/test/ELF/aarch64-bti-pac-cli-error.s
    lld/trunk/test/ELF/aarch64-feature-bti.s
    lld/trunk/test/ELF/aarch64-feature-btipac.s
    lld/trunk/test/ELF/aarch64-feature-pac.s
    lld/trunk/test/ELF/aarch64-ifunc-bti.s
    lld/trunk/test/ELF/aarch64-property-relocatable.s
Modified:
    lld/trunk/ELF/Arch/AArch64.cpp
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/docs/ld.lld.1

Modified: lld/trunk/ELF/Arch/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AArch64.cpp?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AArch64.cpp (original)
+++ lld/trunk/ELF/Arch/AArch64.cpp Fri Jun  7 06:00:17 2019
@@ -28,7 +28,7 @@ uint64_t elf::getAArch64Page(uint64_t Ex
 }
 
 namespace {
-class AArch64 final : public TargetInfo {
+class AArch64 : public TargetInfo {
 public:
   AArch64();
   RelExpr getRelExpr(RelType Type, const Symbol &S,
@@ -431,7 +431,157 @@ void AArch64::relaxTlsIeToLe(uint8_t *Lo
   llvm_unreachable("invalid relocation for TLS IE to LE relaxation");
 }
 
-TargetInfo *elf::getAArch64TargetInfo() {
-  static AArch64 Target;
-  return &Target;
+// AArch64 may use security features in variant PLT sequences. These are:
+// Pointer Authentication (PAC), introduced in armv8.3-a and Branch Target
+// Indicator (BTI) introduced in armv8.5-a. The additional instructions used
+// in the variant Plt sequences are encoded in the Hint space so they can be
+// deployed on older architectures, which treat the instructions as a nop.
+// PAC and BTI can be combined leading to the following combinations:
+// writePltHeader
+// writePltHeaderBti (no PAC Header needed)
+// writePlt
+// writePltBti (BTI only)
+// writePltPac (PAC only)
+// writePltBtiPac (BTI and PAC)
+//
+// When PAC is enabled the dynamic loader encrypts the address that it places
+// in the .got.plt using the pacia1716 instruction which encrypts the value in
+// x17 using the modifier in x16. The static linker places autia1716 before the
+// indirect branch to x17 to authenticate the address in x17 with the modifier
+// in x16. This makes it more difficult for an attacker to modify the value in
+// the .got.plt.
+//
+// When BTI is enabled all indirect branches must land on a bti instruction.
+// The static linker must place a bti instruction at the start of any PLT entry
+// that may be the target of an indirect branch. As the PLT entries call the
+// lazy resolver indirectly this must have a bti instruction at start. In
+// general a bti instruction is not needed for a PLT entry as indirect calls
+// are resolved to the function address and not the PLT entry for the function.
+// There are a small number of cases where the PLT address can escape, such as
+// taking the address of a function or ifunc via a non got-generating
+// relocation, and a shared library refers to that symbol.
+//
+// We use the bti c variant of the instruction which permits indirect branches
+// (br) via x16/x17 and indirect function calls (blr) via any register. The ABI
+// guarantees that all indirect branches from code requiring BTI protection
+// will go via x16/x17
+
+namespace {
+class AArch64BtiPac final : public AArch64 {
+public:
+  AArch64BtiPac();
+  void writePltHeader(uint8_t *Buf) const override;
+  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
+                int32_t Index, unsigned RelOff) const override;
+
+private:
+  bool BtiHeader; // bti instruction needed in PLT Header
+  bool BtiEntry;  // bti instruction needed in PLT Entry
+  bool PacEntry;  // autia1716 instruction needed in PLT Entry
+};
+} // namespace
+
+AArch64BtiPac::AArch64BtiPac() {
+  BtiHeader = (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
+  // A BTI (Branch Target Indicator) Plt Entry is only required if the
+  // address of the PLT entry can be taken by the program, which permits an
+  // indirect jump to the PLT entry. This can happen when the address
+  // of the PLT entry for a function is canonicalised due to the address of
+  // the function in an executable being taken by a shared library.
+  // FIXME: There is a potential optimization to omit the BTI if we detect
+  // that the address of the PLT entry isn't taken.
+  BtiEntry = BtiHeader && !Config->Shared;
+  PacEntry = (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC);
+
+  if (BtiEntry || PacEntry)
+    PltEntrySize = 24;
+}
+
+void AArch64BtiPac::writePltHeader(uint8_t *Buf) const {
+  const uint8_t BtiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
+  const uint8_t PltData[] = {
+      0xf0, 0x7b, 0xbf, 0xa9, // stp    x16, x30, [sp,#-16]!
+      0x10, 0x00, 0x00, 0x90, // adrp   x16, Page(&(.plt.got[2]))
+      0x11, 0x02, 0x40, 0xf9, // ldr    x17, [x16, Offset(&(.plt.got[2]))]
+      0x10, 0x02, 0x00, 0x91, // add    x16, x16, Offset(&(.plt.got[2]))
+      0x20, 0x02, 0x1f, 0xd6, // br     x17
+      0x1f, 0x20, 0x03, 0xd5, // nop
+      0x1f, 0x20, 0x03, 0xd5  // nop
+  };
+  const uint8_t NopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
+
+  uint64_t Got = In.GotPlt->getVA();
+  uint64_t Plt = In.Plt->getVA();
+
+  if (BtiHeader) {
+    // PltHeader is called indirectly by Plt[N]. Prefix PltData with a BTI C
+    // instruction.
+    memcpy(Buf, BtiData, sizeof(BtiData));
+    Buf += sizeof(BtiData);
+    Plt += sizeof(BtiData);
+  }
+  memcpy(Buf, PltData, sizeof(PltData));
+
+  relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
+              getAArch64Page(Got + 16) - getAArch64Page(Plt + 8));
+  relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);
+  relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16);
+  if (!BtiHeader)
+    // We didn't add the BTI c instruction so round out size with NOP.
+    memcpy(Buf + sizeof(PltData), NopData, sizeof(NopData));
+}
+
+void AArch64BtiPac::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
+                             uint64_t PltEntryAddr, int32_t Index,
+                             unsigned RelOff) const {
+  // The PLT entry is of the form:
+  // [BtiData] AddrInst (PacBr | StdBr) [NopData]
+  const uint8_t BtiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
+  const uint8_t AddrInst[] = {
+      0x10, 0x00, 0x00, 0x90,  // adrp x16, Page(&(.plt.got[n]))
+      0x11, 0x02, 0x40, 0xf9,  // ldr  x17, [x16, Offset(&(.plt.got[n]))]
+      0x10, 0x02, 0x00, 0x91   // add  x16, x16, Offset(&(.plt.got[n]))
+  };
+  const uint8_t PacBr[] = {
+      0x9f, 0x21, 0x03, 0xd5,  // autia1716
+      0x20, 0x02, 0x1f, 0xd6   // br   x17
+  };
+  const uint8_t StdBr[] = {
+      0x20, 0x02, 0x1f, 0xd6,  // br   x17
+      0x1f, 0x20, 0x03, 0xd5   // nop
+  };
+  const uint8_t NopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
+
+  if (BtiEntry) {
+    memcpy(Buf, BtiData, sizeof(BtiData));
+    Buf += sizeof(BtiData);
+    PltEntryAddr += sizeof(BtiData);
+  }
+
+  memcpy(Buf, AddrInst, sizeof(AddrInst));
+  relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,
+              getAArch64Page(GotPltEntryAddr) -
+                  getAArch64Page(PltEntryAddr));
+  relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotPltEntryAddr);
+  relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr);
+
+  if (PacEntry)
+    memcpy(Buf + sizeof(AddrInst), PacBr, sizeof(PacBr));
+  else
+    memcpy(Buf + sizeof(AddrInst), StdBr, sizeof(StdBr));
+  if (!BtiEntry)
+    // We didn't add the BTI c instruction so round out size with NOP.
+    memcpy(Buf + sizeof(AddrInst) + sizeof(StdBr), NopData, sizeof(NopData));
+}
+
+static TargetInfo *getTargetInfo() {
+  if (Config->AndFeatures & (GNU_PROPERTY_AARCH64_FEATURE_1_BTI |
+                             GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
+    static AArch64BtiPac T;
+    return &T;
+  }
+  static AArch64 T;
+  return &T;
 }
+
+TargetInfo *elf::getAArch64TargetInfo() { return getTargetInfo(); }

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Jun  7 06:00:17 2019
@@ -147,6 +147,7 @@ struct Configuration {
   bool ExecuteOnly;
   bool ExportDynamic;
   bool FixCortexA53Errata843419;
+  bool ForceBTI;
   bool FormatBinary = false;
   bool RequireCET;
   bool GcSections;
@@ -168,6 +169,7 @@ struct Configuration {
   bool OFormatBinary;
   bool Omagic;
   bool OptRemarksWithHotness;
+  bool PacPlt;
   bool PicThunk;
   bool Pie;
   bool PrintGcSections;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Jun  7 06:00:17 2019
@@ -337,6 +337,13 @@ static void checkOptions() {
 
   if (Config->ZRetpolineplt && Config->RequireCET)
     error("--require-cet may not be used with -z retpolineplt");
+
+  if (Config->EMachine != EM_AARCH64) {
+    if (Config->PacPlt)
+      error("--pac-plt only supported on AArch64");
+    if (Config->ForceBTI)
+      error("--force-bti only supported on AArch64");
+  }
 }
 
 static const char *getReproduceOption(opt::InputArgList &Args) {
@@ -816,6 +823,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->ForceBTI = Args.hasArg(OPT_force_bti);
   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);
@@ -851,6 +859,7 @@ static void readConfigs(opt::InputArgLis
   Config->Optimize = args::getInteger(Args, OPT_O, 1);
   Config->OrphanHandling = getOrphanHandling(Args);
   Config->OutputFile = Args.getLastArgValue(OPT_o);
+  Config->PacPlt = Args.hasArg(OPT_pac_plt);
   Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);
   Config->PrintIcfSections =
       Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
@@ -1594,20 +1603,32 @@ static void wrapSymbols(ArrayRef<Wrapped
 // with CET.
 //
 // This function returns the merged feature flags. If 0, we cannot enable CET.
+// This is also the case with AARCH64's BTI and PAC which use the similar
+// GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
 //
 // 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)
+  if (Config->EMachine != EM_386 && Config->EMachine != EM_X86_64 &&
+      Config->EMachine != EM_AARCH64)
     return 0;
 
   uint32_t Ret = -1;
   for (InputFile *F : ObjectFiles) {
     uint32_t Features = cast<ObjFile<ELFT>>(F)->AndFeatures;
-    if (!Features && Config->RequireCET)
+    if (Config->ForceBTI && !(Features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
+      warn(toString(F) + ": --force-bti: file does not have BTI property");
+      Features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+    } else if (!Features && Config->RequireCET)
       error(toString(F) + ": --require-cet: file is not compatible with CET");
     Ret &= Features;
   }
+
+  // Force enable pointer authentication Plt, we don't warn in this case as
+  // this does not require support in the object for correctness.
+  if (Config->PacPlt)
+    Ret |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+
   return Ret;
 }
 
@@ -1793,6 +1814,11 @@ template <class ELFT> void LinkerDriver:
   // contain a hint to tweak linker's and loader's behaviors.
   Config->AndFeatures = getAndFeatures<ELFT>();
 
+  // The Target instance handles target-specific stuff, such as applying
+  // relocations or writing a PLT section. It also contains target-dependent
+  // values such as a default image base address.
+  Target = getTarget();
+
   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=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Fri Jun  7 06:00:17 2019
@@ -787,6 +787,10 @@ static uint32_t readAndFeatures(ObjFile<
       continue;
     }
 
+    uint32_t FeatureAndType = Config->EMachine == EM_AARCH64
+                                  ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
+                                  : GNU_PROPERTY_X86_FEATURE_1_AND;
+
     // Read a body of a NOTE record, which consists of type-length-value fields.
     ArrayRef<uint8_t> Desc = Note.getDesc();
     while (!Desc.empty()) {
@@ -796,7 +800,7 @@ static uint32_t readAndFeatures(ObjFile<
       uint32_t Type = read32le(Desc.data());
       uint32_t Size = read32le(Desc.data() + 4);
 
-      if (Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
+      if (Type == FeatureAndType) {
         // We found a FEATURE_1_AND field. There may be more than one of these
         // in a .note.gnu.propery section, for a relocatable object we
         // accumulate the bits set.
@@ -966,8 +970,9 @@ 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
+  // Object files that use processor features such as Intel Control-Flow
+  // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a
+  // .note.gnu.property section containing a bitfield of feature bits like 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

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Fri Jun  7 06:00:17 2019
@@ -175,6 +175,9 @@ def fix_cortex_a53_843419: F<"fix-cortex
 // is not complete.
 def require_cet: F<"require-cet">;
 
+def force_bti: F<"force-bti">,
+  HelpText<"Force enable AArch64 BTI in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property">;
+
 defm format: Eq<"format", "Change the input format of the inputs following this option">,
   MetaVarName<"[default,elf,binary]">;
 
@@ -269,6 +272,9 @@ defm pack_dyn_relocs:
   Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
   MetaVarName<"[none,android,relr,android+relr]">;
 
+def pac_plt: F<"pac-plt">,
+  HelpText<"AArch64 only, use pointer authentication in PLT">;
+
 defm use_android_relr_tags: B<"use-android-relr-tags",
     "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
     "Use SHT_RELR / DT_RELR* tags (default)">;

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Fri Jun  7 06:00:17 2019
@@ -290,8 +290,9 @@ 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.
+// In x86 and AArch64, object files may contain feature flags indicating the
+// features that they have used. 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.
@@ -304,11 +305,15 @@ GnuPropertySection::GnuPropertySection()
                        ".note.gnu.property") {}
 
 void GnuPropertySection::writeTo(uint8_t *Buf) {
+  uint32_t FeatureAndType = Config->EMachine == EM_AARCH64
+                                ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
+                                : GNU_PROPERTY_X86_FEATURE_1_AND;
+
   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 + 16, FeatureAndType);                 // Feature type
   write32(Buf + 20, 4);                              // Feature size
   write32(Buf + 24, Config->AndFeatures);            // Feature flags
   if (Config->Is64)
@@ -1340,6 +1345,13 @@ template <class ELFT> void DynamicSectio
     addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL);
   }
 
+  if (Config->EMachine == EM_AARCH64) {
+    if (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+      addInt(DT_AARCH64_BTI_PLT, 0);
+    if (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
+      addInt(DT_AARCH64_PAC_PLT, 0);
+  }
+
   addInSec(DT_SYMTAB, In.DynSymTab);
   addInt(DT_SYMENT, sizeof(Elf_Sym));
   addInSec(DT_STRTAB, In.DynStrTab);

Modified: lld/trunk/docs/ld.lld.1
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/ld.lld.1?rev=362793&r1=362792&r2=362793&view=diff
==============================================================================
--- lld/trunk/docs/ld.lld.1 (original)
+++ lld/trunk/docs/ld.lld.1 Fri Jun  7 06:00:17 2019
@@ -182,6 +182,8 @@ Set the
 field to the specified value.
 .It Fl -fini Ns = Ns Ar symbol
 Specify a finalizer function.
+.It Fl -force-bti
+Force enable AArch64 BTI instruction in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
 .It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format
 Specify the format of the inputs following this option.
 .Ar input-format
@@ -382,6 +384,8 @@ is the default. If
 .Fl -use-android-relr-tags
 is specified, use SHT_ANDROID_RELR instead of SHT_RELR.
 .Pp
+.It Fl -pac-plt
+AArch64 only, use pointer authentication in PLT.
 .It Fl -pic-veneer
 Always generate position independent thunks.
 .It Fl -pie , Fl -pic-executable

Added: lld/trunk/test/ELF/Inputs/aarch64-addrifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-addrifunc.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-addrifunc.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-addrifunc.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,8 @@
+        .text
+        .globl myfunc
+        .globl func1
+        .type func1, %function
+func1:
+        adrp x8, :got: myfunc
+        ldr x8, [x8, :got_lo12: myfunc]
+        ret

Added: lld/trunk/test/ELF/Inputs/aarch64-bti1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-bti1.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-bti1.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-bti1.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,19 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 1          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-btipac1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-btipac1.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-btipac1.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-btipac1.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,19 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 3          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC and BTI
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-func2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-func2.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-func2.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-func2.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,8 @@
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-func3-bti.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-func3-bti.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-func3-bti.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-func3-bti.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,16 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 1          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+.long 0
+
+.text
+.globl func3
+.type func3, at function
+func3:
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-func3-btipac.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-func3-btipac.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-func3-btipac.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-func3-btipac.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,16 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 3          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+.long 0
+
+.text
+.globl func3
+.type func3, at function
+func3:
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-func3-pac.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-func3-pac.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-func3-pac.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-func3-pac.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,16 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 2          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+.long 0
+
+.text
+.globl func3
+.type func3, at function
+func3:
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-func3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-func3.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-func3.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-func3.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,5 @@
+.text
+.globl func3
+.type func3, at function
+func3:
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-nobti.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-nobti.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-nobti.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-nobti.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,8 @@
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-nopac.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-nopac.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-nopac.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-nopac.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,8 @@
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/Inputs/aarch64-pac1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/aarch64-pac1.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/aarch64-pac1.s (added)
+++ lld/trunk/test/ELF/Inputs/aarch64-pac1.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,19 @@
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 2          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+.long 0
+
+.text
+.globl func2
+.type func2, at function
+func2:
+  .globl func3
+  .type func3, @function
+  bl func3
+  ret

Added: lld/trunk/test/ELF/aarch64-bti-pac-cli-error.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-bti-pac-cli-error.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-bti-pac-cli-error.s (added)
+++ lld/trunk/test/ELF/aarch64-bti-pac-cli-error.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj -o %t.o %s
+# RUN: not ld.lld --pac-plt --force-bti %t.o -o %t 2>&1 | FileCheck %s
+#
+## Check that we error if --pac-plt and --force-bti are used when target is not
+## aarch64
+
+# CHECK: error: --pac-plt only supported on AArch64
+# CHECK-NEXT: error: --force-bti only supported on AArch64
+
+        .globl start
+start:  ret

Added: lld/trunk/test/ELF/aarch64-feature-bti.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-feature-bti.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-feature-bti.s (added)
+++ lld/trunk/test/ELF/aarch64-feature-bti.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,218 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-bti1.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-bti.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o
+
+## We do not add BTI support when the inputs don't have the .note.gnu.property
+## field.
+
+# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOBTI %s
+# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s
+# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOBTIDYN %s
+
+# NOBTIDYN-NOT:   0x0000000070000001 (AARCH64_BTI_PLT)
+# NOBTIDYN-NOT:   0x0000000070000003 (AARCH64_PAC_PLT)
+
+# NOBTI: 0000000000010000 func2:
+# NOBTI-NEXT:    10000: bl      #48 <func3 at plt>
+# NOBTI-NEXT:    10004: ret
+# NOBTI: Disassembly of section .plt:
+# NOBTI: 0000000000010010 .plt:
+# NOBTI-NEXT:    10010: stp     x16, x30, [sp, #-16]!
+# NOBTI-NEXT:    10014: adrp    x16, #131072
+# NOBTI-NEXT:    10018: ldr     x17, [x16, #16]
+# NOBTI-NEXT:    1001c: add     x16, x16, #16
+# NOBTI-NEXT:    10020: br      x17
+# NOBTI-NEXT:    10024: nop
+# NOBTI-NEXT:    10028: nop
+# NOBTI-NEXT:    1002c: nop
+# NOBTI: 0000000000010030 func3 at plt:
+# NOBTI-NEXT:    10030: adrp    x16, #131072
+# NOBTI-NEXT:    10034: ldr     x17, [x16, #24]
+# NOBTI-NEXT:    10038: add     x16, x16, #24
+# NOBTI-NEXT:    1003c: br      x17
+
+## Expect a bti c at the start of plt[0], the plt entries do not need bti c as
+## their address doesn't escape the shared object, so they can't be indirectly
+## called. Expect no other difference.
+
+# RUN: ld.lld %t1.o %t3.o --shared -o %t.so
+# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix BTIPROP %s
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %t.so | FileCheck --check-prefix BTISO %s
+# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT %s
+# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix BTIDYN %s
+
+# BTIPROP: Properties:    aarch64 feature: BTI
+
+# BTIDYN:      0x0000000070000001 (AARCH64_BTI_PLT)
+# BTIDYN-NOT:  0x0000000070000003 (AARCH64_PAC_PLT)
+
+# BTISO: 0000000000010000 func2:
+# BTISO-NEXT:    10000: bl      #48 <func3 at plt>
+# BTISO-NEXT:    10004: ret
+# BTISO: Disassembly of section .plt:
+# BTISO: 0000000000010010 .plt:
+# BTISO-NEXT:    10010: bti     c
+# BTISO-NEXT:    10014: stp     x16, x30, [sp, #-16]!
+# BTISO-NEXT:    10018: adrp    x16, #131072
+# BTISO-NEXT:    1001c: ldr     x17, [x16, #16]
+# BTISO-NEXT:    10020: add     x16, x16, #16
+# BTISO-NEXT:    10024: br      x17
+# BTISO-NEXT:    10028: nop
+# BTISO-NEXT:    1002c: nop
+# BTISO: 0000000000010030 func3 at plt:
+# BTISO-NEXT:    10030: adrp    x16, #131072
+# BTISO-NEXT:    10034: ldr     x17, [x16, #24]
+# BTISO-NEXT:    10038: add     x16, x16, #24
+# BTISO-NEXT:    1003c: br      x17
+
+## The .got.plt should be identical between the BTI and no BTI DSO PLT.
+# SOGOTPLT: Hex dump of section '.got.plt'
+# SOGOTPLT-NEXT:  0x00030000 00000000 00000000 00000000 00000000
+# SOGOTPLT-NEXT:  0x00030010 00000000 00000000 10000100 00000000
+
+## Build an executable with all relocatable inputs having the BTI
+## .note.gnu.property. We expect a bti c in front of all PLT entries as the
+## address of a PLT entry can escape an executable.
+
+# RUN: ld.lld %t2.o --shared -o %t2.so
+
+# RUN: ld.lld %t.o %t.so %t2.so -o %t.exe
+# RUN: llvm-readelf --dynamic-table -n %t.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %t.exe | FileCheck --check-prefix=EXECBTI %s
+
+# EXECBTI: Disassembly of section .text:
+# EXECBTI: 0000000000210000 func1:
+# EXECBTI-NEXT:   210000: bl      #48 <func2 at plt>
+# EXECBTI-NEXT:   210004: ret
+# EXECBTI: Disassembly of section .plt:
+# EXECBTI: 0000000000210010 .plt:
+# EXECBTI-NEXT:   210010: bti     c
+# EXECBTI-NEXT:   210014: stp     x16, x30, [sp, #-16]!
+# EXECBTI-NEXT:   210018: adrp    x16, #131072
+# EXECBTI-NEXT:   21001c: ldr     x17, [x16, #16]
+# EXECBTI-NEXT:   210020: add     x16, x16, #16
+# EXECBTI-NEXT:   210024: br      x17
+# EXECBTI-NEXT:   210028: nop
+# EXECBTI-NEXT:   21002c: nop
+# EXECBTI: 0000000000210030 func2 at plt:
+# EXECBTI-NEXT:   210030: bti     c
+# EXECBTI-NEXT:   210034: adrp    x16, #131072
+# EXECBTI-NEXT:   210038: ldr     x17, [x16, #24]
+# EXECBTI-NEXT:   21003c: add     x16, x16, #24
+# EXECBTI-NEXT:   210040: br      x17
+# EXECBTI-NEXT:   210044: nop
+
+## We expect the same for PIE, as the address of an ifunc can escape
+# RUN: ld.lld --pie %t.o %t.so %t2.so -o %tpie.exe
+# RUN: llvm-readelf -n %tpie.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-readelf --dynamic-table -n %tpie.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tpie.exe | FileCheck --check-prefix=PIE %s
+
+# PIE: Disassembly of section .text:
+# PIE: 0000000000010000 func1:
+# PIE-NEXT:    10000: bl      #48 <func2 at plt>
+# PIE-NEXT:    10004: ret
+# PIE: Disassembly of section .plt:
+# PIE: 0000000000010010 .plt:
+# PIE-NEXT:    10010: bti     c
+# PIE-NEXT:    10014: stp     x16, x30, [sp, #-16]!
+# PIE-NEXT:    10018: adrp    x16, #131072
+# PIE-NEXT:    1001c: ldr     x17, [x16, #16]
+# PIE-NEXT:    10020: add     x16, x16, #16
+# PIE-NEXT:    10024: br      x17
+# PIE-NEXT:    10028: nop
+# PIE-NEXT:    1002c: nop
+# PIE: 0000000000010030 func2 at plt:
+# PIE-NEXT:    10030: bti     c
+# PIE-NEXT:    10034: adrp    x16, #131072
+# PIE-NEXT:    10038: ldr     x17, [x16, #24]
+# PIE-NEXT:    1003c: add     x16, x16, #24
+# PIE-NEXT:    10040: br      x17
+# PIE-NEXT:    10044: nop
+
+## Build and executable with not all relocatable inputs having the BTI
+## .note.property, expect no bti c and no .note.gnu.property entry
+
+# RUN: ld.lld %t.o %t2.o %t.so -o %tnobti.exe
+# RUN: llvm-readelf --dynamic-table %tnobti.exe | FileCheck --check-prefix NOBTIDYN %s
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tnobti.exe | FileCheck --check-prefix=NOEX %s
+
+# NOEX: Disassembly of section .text:
+# NOEX: 0000000000210000 func1:
+# NOEX-NEXT:   210000: bl      #48 <func2 at plt>
+# NOEX-NEXT:   210004: ret
+# NOEX: 0000000000210008 func3:
+# NOEX-NEXT:   210008: ret
+# NOEX: Disassembly of section .plt:
+# NOEX: 0000000000210010 .plt:
+# NOEX-NEXT:   210010: stp     x16, x30, [sp, #-16]!
+# NOEX-NEXT:   210014: adrp    x16, #131072
+# NOEX-NEXT:   210018: ldr     x17, [x16, #16]
+# NOEX-NEXT:   21001c: add     x16, x16, #16
+# NOEX-NEXT:   210020: br      x17
+# NOEX-NEXT:   210024: nop
+# NOEX-NEXT:   210028: nop
+# NOEX-NEXT:   21002c: nop
+# NOEX: 0000000000210030 func2 at plt:
+# NOEX-NEXT:   210030: adrp    x16, #131072
+# NOEX-NEXT:   210034: ldr     x17, [x16, #24]
+# NOEX-NEXT:   210038: add     x16, x16, #24
+# NOEX-NEXT:   21003c: br      x17
+
+## Force BTI entries with the --force-bti command line option. Expect a warning
+## from the file without the .note.gnu.property.
+
+# RUN: ld.lld %t.o %t2.o --force-bti %t.so -o %tforcebti.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s
+
+# FORCE-WARN: aarch64-feature-bti.s.tmp2.o: --force-bti: file does not have BTI property
+
+
+# RUN: llvm-readelf -n %tforcebti.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-readelf --dynamic-table %tforcebti.exe | FileCheck --check-prefix BTIDYN %s
+# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tforcebti.exe | FileCheck --check-prefix=FORCE %s
+
+# FORCE: Disassembly of section .text:
+# FORCE: 0000000000210000 func1:
+# FORCE-NEXT:   210000: bl      #48 <func2 at plt>
+# FORCE-NEXT:   210004: ret
+# FORCE: 0000000000210008 func3:
+# FORCE-NEXT:   210008: ret
+# FORCE: Disassembly of section .plt:
+# FORCE: 0000000000210010 .plt:
+# FORCE-NEXT:   210010: bti     c
+# FORCE-NEXT:   210014: stp     x16, x30, [sp, #-16]!
+# FORCE-NEXT:   210018: adrp    x16, #131072
+# FORCE-NEXT:   21001c: ldr     x17, [x16, #16]
+# FORCE-NEXT:   210020: add     x16, x16, #16
+# FORCE-NEXT:   210024: br      x17
+# FORCE-NEXT:   210028: nop
+# FORCE-NEXT:   21002c: nop
+# FORCE: 0000000000210030 func2 at plt:
+# FORCE-NEXT:   210030: bti     c
+# FORCE-NEXT:   210034: adrp    x16, #131072
+# FORCE-NEXT:   210038: ldr     x17, [x16, #24]
+# FORCE-NEXT:   21003c: add     x16, x16, #24
+# FORCE-NEXT:   210040: br      x17
+# FORCE-NEXT:   210044: nop
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 1          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+.long 0
+
+.text
+.globl _start
+.type func1,%function
+func1:
+  bl func2
+  ret

Added: lld/trunk/test/ELF/aarch64-feature-btipac.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-feature-btipac.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-feature-btipac.s (added)
+++ lld/trunk/test/ELF/aarch64-feature-btipac.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,142 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-btipac1.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-btipac.s -o %t3btipac.o
+
+## Build shared library with all inputs having BTI and PAC, expect PLT
+## entries supporting both PAC and BTI. For a shared library this means:
+## PLT[0] has bti c at start
+## PLT[n] has autia1716 before br x17
+
+# RUN: ld.lld %t1.o %t3btipac.o --shared -o %t.so
+# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix BTIPACPROP %s
+# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.so | FileCheck --check-prefix BTIPACSO %s
+# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix BTIPACDYN %s
+
+# BTIPACSO: Disassembly of section .text:
+# BTIPACSO: 0000000000010000 func2:
+# BTIPACSO-NEXT:    10000: bl      #48 <func3 at plt>
+# BTIPACSO-NEXT:    10004: ret
+# BTIPACSO: 0000000000010008 func3:
+# BTIPACSO-NEXT:    10008: ret
+# BTIPACSO: Disassembly of section .plt:
+# BTIPACSO: 0000000000010010 .plt:
+# BTIPACSO-NEXT:    10010: bti     c
+# BTIPACSO-NEXT:    10014: stp     x16, x30, [sp, #-16]!
+# BTIPACSO-NEXT:    10018: adrp    x16, #131072
+# BTIPACSO-NEXT:    1001c: ldr     x17, [x16, #16]
+# BTIPACSO-NEXT:    10020: add     x16, x16, #16
+# BTIPACSO-NEXT:    10024: br      x17
+# BTIPACSO-NEXT:    10028: nop
+# BTIPACSO-NEXT:    1002c: nop
+# BTIPACSO: 0000000000010030 func3 at plt:
+# BTIPACSO-NEXT:    10030: adrp    x16, #131072
+# BTIPACSO-NEXT:    10034: ldr     x17, [x16, #24]
+# BTIPACSO-NEXT:    10038: add     x16, x16, #24
+# BTIPACSO-NEXT:    1003c: autia1716
+# BTIPACSO-NEXT:    10040: br      x17
+# BTIPACSO-NEXT:    10044: nop
+
+# BTIPACPROP:    Properties:    aarch64 feature: BTI, PAC
+
+# BTIPACDYN:   0x0000000070000001 (AARCH64_BTI_PLT)
+# BTIPACDYN:   0x0000000070000003 (AARCH64_PAC_PLT)
+
+## Make an executable with both BTI and PAC properties. Expect:
+## PLT[0] bti c as first instruction
+## PLT[n] bti n as first instruction, autia1716 before br x17
+
+# RUN: ld.lld %t.o %t3btipac.o %t.so -o %t.exe
+# RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s
+# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s
+# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s
+
+# BTIPACEX: Disassembly of section .text:
+# BTIPACEX: 0000000000210000 func1:
+# BTIPACEX-NEXT:   210000: bl      #48 <func2 at plt>
+# BTIPACEX-NEXT:   210004: ret
+# BTIPACEX-NEXT:   210008: ret
+# BTIPACEX: 000000000021000c func3:
+# BTIPACEX-NEXT:   21000c: ret
+# BTIPACEX: Disassembly of section .plt:
+# BTIPACEX: 0000000000210010 .plt:
+# BTIPACEX-NEXT:   210010: bti     c
+# BTIPACEX-NEXT:   210014: stp     x16, x30, [sp, #-16]!
+# BTIPACEX-NEXT:   210018: adrp    x16, #131072
+# BTIPACEX-NEXT:   21001c: ldr     x17, [x16, #16]
+# BTIPACEX-NEXT:   210020: add     x16, x16, #16
+# BTIPACEX-NEXT:   210024: br      x17
+# BTIPACEX-NEXT:   210028: nop
+# BTIPACEX-NEXT:   21002c: nop
+# BTIPACEX: 0000000000210030 func2 at plt:
+# BTIPACEX-NEXT:   210030: bti     c
+# BTIPACEX-NEXT:   210034: adrp    x16, #131072
+# BTIPACEX-NEXT:   210038: ldr     x17, [x16, #24]
+# BTIPACEX-NEXT:   21003c: add     x16, x16, #24
+# BTIPACEX-NEXT:   210040: autia1716
+# BTIPACEX-NEXT:   210044: br      x17
+
+## Check that combinations of BTI+PAC with 0 properties results in standard PLT
+
+# RUN: ld.lld %t.o %t3.o %t.so -o %t.exe
+# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix EX %s
+# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix=NODYN %s
+
+# EX: Disassembly of section .text:
+# EX: 0000000000210000 func1:
+# EX-NEXT:   210000: bl      #48 <func2 at plt>
+# EX-NEXT:   210004: ret
+# EX-NEXT:   210008: ret
+# EX: 000000000021000c func3:
+# EX-NEXT:   21000c: ret
+# EX: Disassembly of section .plt:
+# EX: 0000000000210010 .plt:
+# EX-NEXT:   210010: stp     x16, x30, [sp, #-16]!
+# EX-NEXT:   210014: adrp    x16, #131072
+# EX-NEXT:   210018: ldr     x17, [x16, #16]
+# EX-NEXT:   21001c: add     x16, x16, #16
+# EX-NEXT:   210020: br      x17
+# EX-NEXT:   210024: nop
+# EX-NEXT:   210028: nop
+# EX-NEXT:   21002c: nop
+# EX: 0000000000210030 func2 at plt:
+# EX:        210030: adrp    x16, #131072
+# EX-NEXT:   210034: ldr     x17, [x16, #24]
+# EX-NEXT:   210038: add     x16, x16, #24
+# EX-NEXT:   21003c: br      x17
+
+# NODYN-NOT:   0x0000000070000001 (AARCH64_BTI_PLT)
+# NODYN-NOT:   0x0000000070000003 (AARCH64_PAC_PLT)
+
+## Check that combination of --pac-plt and --force-bti warns for the file that
+## doesn't contain the BTI property, but generates PAC and BTI PLT sequences.
+## The --pac-plt doesn't warn as it is not required for correctness.
+
+# RUN: ld.lld %t.o %t3.o %t.so --pac-plt --force-bti -o %t.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s
+
+# FORCE-WARN: aarch64-feature-btipac.s.tmp3.o: --force-bti: file does not have BTI property
+
+# RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s
+# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s
+# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 3          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC
+.long 0
+
+.text
+.globl _start
+.type func1,%function
+func1:
+  bl func2
+  ret
+.globl func3
+.type func3,%function
+  ret

Added: lld/trunk/test/ELF/aarch64-feature-pac.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-feature-pac.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-feature-pac.s (added)
+++ lld/trunk/test/ELF/aarch64-feature-pac.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,129 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o
+
+## We do not add PAC support when the inputs don't have the .note.gnu.property
+## field.
+
+# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so
+# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s
+# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s
+# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s
+
+# NOPAC: 0000000000010000 func2:
+# NOPAC-NEXT:    10000: bl      #48 <func3 at plt>
+# NOPAC-NEXT:    10004: ret
+# NOPAC: Disassembly of section .plt:
+# NOPAC: 0000000000010010 .plt:
+# NOPAC-NEXT:    10010: stp     x16, x30, [sp, #-16]!
+# NOPAC-NEXT:    10014: adrp    x16, #131072
+# NOPAC-NEXT:    10018: ldr     x17, [x16, #16]
+# NOPAC-NEXT:    1001c: add     x16, x16, #16
+# NOPAC-NEXT:    10020: br      x17
+# NOPAC-NEXT:    10024: nop
+# NOPAC-NEXT:    10028: nop
+# NOPAC-NEXT:    1002c: nop
+# NOPAC: 0000000000010030 func3 at plt:
+# NOPAC-NEXT:    10030: adrp    x16, #131072
+# NOPAC-NEXT:    10034: ldr     x17, [x16, #24]
+# NOPAC-NEXT:    10038: add     x16, x16, #24
+# NOPAC-NEXT:    1003c: br      x17
+
+# NOPACDYN-NOT:   0x0000000070000001 (AARCH64_BTI_PLT)
+# NOPACDYN-NOT:   0x0000000070000003 (AARCH64_PAC_PLT)
+
+# RUN: ld.lld %t1.o %t3.o --shared -o %t.so
+# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s
+# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s
+# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT %s
+# RUN: llvm-readelf --dynamic-table %t.so |  FileCheck --check-prefix PACDYN %s
+
+## PAC has no effect on PLT[0], for PLT[N] autia1716 is used to authenticate
+## the address in x17 (context in x16) before branching to it. The dynamic
+## loader is responsible for calling pacia1716 on the entry.
+# PACSO: 0000000000010000 func2:
+# PACSO-NEXT:    10000: bl      #48 <func3 at plt>
+# PACSO-NEXT:    10004: ret
+# PACSO: Disassembly of section .plt:
+# PACSO: 0000000000010010 .plt:
+# PACSO-NEXT:    10010: stp     x16, x30, [sp, #-16]!
+# PACSO-NEXT:    10014: adrp    x16, #131072
+# PACSO-NEXT:    10018: ldr     x17, [x16, #16]
+# PACSO-NEXT:    1001c: add     x16, x16, #16
+# PACSO-NEXT:    10020: br      x17
+# PACSO-NEXT:    10024: nop
+# PACSO-NEXT:    10028: nop
+# PACSO-NEXT:    1002c: nop
+# PACSO: 0000000000010030 func3 at plt:
+# PACSO-NEXT:    10030: adrp    x16, #131072
+# PACSO-NEXT:    10034: ldr     x17, [x16, #24]
+# PACSO-NEXT:    10038: add     x16, x16, #24
+# PACSO-NEXT:    1003c: autia1716
+# PACSO-NEXT:    10040: br      x17
+# PACSO-NEXT:    10044: nop
+
+# The .got.plt should be identical between the PAC and no PAC DSO PLT.
+# SOGOTPLT: Hex dump of section '.got.plt':
+# SOGOTPLT-NEXT: 0x00030000 00000000 00000000 00000000 00000000
+# SOGOTPLT-NEXT: 0x00030010 00000000 00000000 10000100 00000000
+
+# PACPROP: Properties:    aarch64 feature: PAC
+
+# PACDYN-NOT:      0x0000000070000001 (AARCH64_BTI_PLT)
+# PACDYN:          0x0000000070000003 (AARCH64_PAC_PLT)
+
+## Turn on PAC entries with the --pac-plt command line option. There are no
+## warnings in this case as the choice to use PAC in PLT entries is orthogonal
+## to the choice of using PAC in relocatable objects. The presence of the PAC
+## .note.gnu.property is an indication of preference by the relocatable object.
+
+# RUN: ld.lld %t.o %t2.o --pac-plt %t.so -o %tpacplt.exe
+# RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s
+# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN %s
+# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s
+
+# PACPLT: Disassembly of section .text:
+# PACPLT: 0000000000210000 func1:
+# PACPLT-NEXT:   210000: bl      #48 <func2 at plt>
+# PACPLT-NEXT:   210004: ret
+# PACPLT: 0000000000210008 func3:
+# PACPLT-NEXT:   210008: ret
+# PACPLT: Disassembly of section .plt:
+# PACPLT: 0000000000210010 .plt:
+# PACPLT-NEXT:   210010: stp     x16, x30, [sp, #-16]!
+# PACPLT-NEXT:   210014: adrp    x16, #131072
+# PACPLT-NEXT:   210018: ldr     x17, [x16, #16]
+# PACPLT-NEXT:   21001c: add     x16, x16, #16
+# PACPLT-NEXT:   210020: br      x17
+# PACPLT-NEXT:   210024: nop
+# PACPLT-NEXT:   210028: nop
+# PACPLT-NEXT:   21002c: nop
+# PACPLT: 0000000000210030 func2 at plt:
+# PACPLT-NEXT:   210030: adrp    x16, #131072
+# PACPLT-NEXT:   210034: ldr     x17, [x16, #24]
+# PACPLT-NEXT:   210038: add     x16, x16, #24
+# PACPLT-NEXT:   21003c: autia1716
+# PACPLT-NEXT:   210040: br      x17
+# PACPLT-NEXT:   210044: nop
+
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 2          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+.long 0
+
+.text
+.globl _start
+.type func1,%function
+func1:
+  bl func2
+  ret

Added: lld/trunk/test/ELF/aarch64-ifunc-bti.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-ifunc-bti.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-ifunc-bti.s (added)
+++ lld/trunk/test/ELF/aarch64-ifunc-bti.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,65 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %p/Inputs/aarch64-addrifunc.s -o %lib.o
+
+# RUN: ld.lld --shared %lib.o -o %lib.so
+# RUN: ld.lld --pie %lib.so %t.o -o %t
+# RUN: llvm-objdump -d -mattr=+bti -triple=aarch64-linux-gnu %t | FileCheck %s
+
+# When the address of an ifunc is taken using a non-got reference which clang
+# can do, LLD exports a canonical PLT entry that may have its address taken so
+# we must use bti c.
+
+# CHECK: Disassembly of section .plt:
+# CHECK: 0000000000010020 .plt:
+# CHECK-NEXT:    10020: 5f 24 03 d5                     bti     c
+# CHECK-NEXT:    10024: f0 7b bf a9                     stp     x16, x30, [sp, #-16]!
+# CHECK-NEXT:    10028: 10 01 00 90                     adrp    x16, #131072
+# CHECK-NEXT:    1002c: 11 0a 40 f9                     ldr     x17, [x16, #16]
+# CHECK-NEXT:    10030: 10 42 00 91                     add     x16, x16, #16
+# CHECK-NEXT:    10034: 20 02 1f d6                     br      x17
+# CHECK-NEXT:    10038: 1f 20 03 d5                     nop
+# CHECK-NEXT:    1003c: 1f 20 03 d5                     nop
+# CHECK: 0000000000010040 func1 at plt:
+# CHECK-NEXT:    10040: 5f 24 03 d5                     bti     c
+# CHECK-NEXT:    10044: 10 01 00 90                     adrp    x16, #131072
+# CHECK-NEXT:    10048: 11 0e 40 f9                     ldr     x17, [x16, #24]
+# CHECK-NEXT:    1004c: 10 62 00 91                     add     x16, x16, #24
+# CHECK-NEXT:    10050: 20 02 1f d6                     br      x17
+# CHECK-NEXT:    10054: 1f 20 03 d5                     nop
+# CHECK-NEXT:           ...
+# CHECK: 0000000000010060 myfunc:
+# CHECK-NEXT:    10060: 5f 24 03 d5                     bti     c
+# CHECK-NEXT:    10064: 10 01 00 90                     adrp    x16, #131072
+# CHECK-NEXT:    10068: 11 12 40 f9                     ldr     x17, [x16, #32]
+# CHECK-NEXT:    1006c: 10 82 00 91                     add     x16, x16, #32
+# CHECK-NEXT:    10070: 20 02 1f d6                     br      x17
+# CHECK-NEXT:    10074: 1f 20 03 d5                     nop
+
+.section ".note.gnu.property", "a"
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 1          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+.long 0
+
+.text
+.globl myfunc
+.type myfunc, at gnu_indirect_function
+myfunc:
+ ret
+
+.globl func1
+
+.text
+.globl _start
+.type _start, %function
+_start:
+  bl func1
+  adrp x8, myfunc
+  add x8, x8, :lo12:myfunc
+  ret

Added: lld/trunk/test/ELF/aarch64-property-relocatable.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-property-relocatable.s?rev=362793&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-property-relocatable.s (added)
+++ lld/trunk/test/ELF/aarch64-property-relocatable.s Fri Jun  7 06:00:17 2019
@@ -0,0 +1,36 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+# RUN: ld.lld -r %t.o -o %t2.o
+# RUN: llvm-readelf -n %t2.o | FileCheck -match-full-lines %s
+
+## Test that .note.gnu.property is passed through -r, and that we can handle
+## more than one FEATURE_AND in the same object file. This is logically the
+## same as if the features were combined in a single FEATURE_AND as the rule
+## states that the bit in the output pr_data field if it is set in all
+.text
+ret
+
+.section ".note.gnu.property", "a"
+.p2align 3
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 1          // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+.long 0
+
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
+.long 4
+.long 2          // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+.long 0
+
+# CHECK:   Owner                 Data size	Description
+# CHECK-NEXT:   GNU                   0x00000010	NT_GNU_PROPERTY_TYPE_0 (property note)
+# CHECK-NEXT:     Properties:    aarch64 feature: BTI, PAC




More information about the llvm-commits mailing list