]> granicus.if.org Git - llvm/commitdiff
[AArch64][ELF][llvm-readobj] Add support for BTI and PAC dynamic tags
authorPeter Smith <peter.smith@linaro.org>
Tue, 4 Jun 2019 11:44:33 +0000 (11:44 +0000)
committerPeter Smith <peter.smith@linaro.org>
Tue, 4 Jun 2019 11:44:33 +0000 (11:44 +0000)
ELF for the 64-bit Arm Architecture defines two processor-specific dynamic
tags:
DT_AARCH64_BTI_PLT 0x70000001, d_val
DT_AARCH64_PAC_PLT 0x70000003, d_val

These presence of these tags indicate that PLT sequences have been
protected using Branch Target Identification and Pointer Authentication
respectively. The presence of both indicates that the PLT sequences have
been protected with both Branch Target Identification and Pointer
Authentication.

This patch adds the tags and tests for llvm-readobj and yaml2obj.

As some of the processor specific dynamic tags overlap, this patch splits
them up, keeping their original default value if they were not previously
mentioned explicitly in a switch case.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362493 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/BinaryFormat/DynamicTags.def
lib/Object/ELF.cpp
lib/ObjectYAML/ELFYAML.cpp
test/tools/llvm-readobj/Inputs/elf-dynamic-tags-machine-specific.yaml
test/tools/llvm-readobj/elf-dynamic-tags-machine-specific.test
test/tools/obj2yaml/dynamic-section-arch-tags.test
tools/llvm-readobj/ELFDumper.cpp

index 82fe72eefade13cd7275ecfcd98b32ad8a179392..c884badab3603b6c56aa6306fe1883521f43c78a 100644 (file)
@@ -6,6 +6,11 @@
 // such as DT_HIOS, etc. to allow using this file to in other contexts.
 // For example we can use it to generate a stringification switch statement.
 
+#ifndef AARCH64_DYNAMIC_TAG
+#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#define AARCH64_DYNAMIC_TAG_DEFINED
+#endif
+
 #ifndef HEXAGON_DYNAMIC_TAG
 #define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
 #define HEXAGON_DYNAMIC_TAG_DEFINED
@@ -107,6 +112,10 @@ DYNAMIC_TAG(VERNEED, 0X6FFFFFFE)    // The address of the version dependency
                                     // table.
 DYNAMIC_TAG(VERNEEDNUM, 0X6FFFFFFF) // The number of entries in DT_VERNEED.
 
+// AArch64 specific dynamic table entries
+AARCH64_DYNAMIC_TAG(AARCH64_BTI_PLT, 0x70000001)
+AARCH64_DYNAMIC_TAG(AARCH64_PAC_PLT, 0x70000003)
+
 // Hexagon specific dynamic table entries
 HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000)
 HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001)
@@ -204,6 +213,10 @@ DYNAMIC_TAG(FILTER, 0x7FFFFFFF)    // Shared object to get values from
 #undef DYNAMIC_TAG_MARKER
 #undef DYNAMIC_TAG_MARKER_DEFINED
 #endif
+#ifdef AARCH64_DYNAMIC_TAG_DEFINED
+#undef AARCH64_DYNAMIC_TAG
+#undef AARCH64_DYNAMIC_TAG_DEFINED
+#endif
 #ifdef MIPS_DYNAMIC_TAG_DEFINED
 #undef MIPS_DYNAMIC_TAG
 #undef MIPS_DYNAMIC_TAG_DEFINED
index a9c90e01551eaa1e39f5c35307f8f436f0f1cd3b..f0ef53d244455a5571bac16c76bb8dc4ed1dd2ec 100644 (file)
@@ -434,6 +434,14 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
 
 #define DYNAMIC_TAG(n, v)
   switch (Arch) {
+  case ELF::EM_AARCH64:
+    switch (Type) {
+#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef AARCH64_DYNAMIC_TAG
+    }
+    break;
+
   case ELF::EM_HEXAGON:
     switch (Type) {
 #define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
@@ -461,6 +469,7 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
 #undef DYNAMIC_TAG
   switch (Type) {
 // Now handle all dynamic tags except the architecture specific ones
+#define AARCH64_DYNAMIC_TAG(name, value)
 #define MIPS_DYNAMIC_TAG(name, value)
 #define HEXAGON_DYNAMIC_TAG(name, value)
 #define PPC64_DYNAMIC_TAG(name, value)
@@ -469,6 +478,7 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
 #define DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
 #include "llvm/BinaryFormat/DynamicTags.def"
 #undef DYNAMIC_TAG
+#undef AARCH64_DYNAMIC_TAG
 #undef MIPS_DYNAMIC_TAG
 #undef HEXAGON_DYNAMIC_TAG
 #undef PPC64_DYNAMIC_TAG
index 39e59efe00f60e04ea2288f1b2d49feffb47796e..1d230700f4471fcabdd295441bda819412d74703 100644 (file)
@@ -680,6 +680,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG>::enumeration(
   assert(Object && "The IO context is not initialized");
 
 // Disable architecture specific tags by default. We might enable them below.
+#define AARCH64_DYNAMIC_TAG(name, value)
 #define MIPS_DYNAMIC_TAG(name, value)
 #define HEXAGON_DYNAMIC_TAG(name, value)
 #define PPC64_DYNAMIC_TAG(name, value)
@@ -689,6 +690,13 @@ void ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG>::enumeration(
 #define STRINGIFY(X) (#X)
 #define DYNAMIC_TAG(X, Y) IO.enumCase(Value, STRINGIFY(DT_##X), ELF::DT_##X);
   switch (Object->Header.Machine) {
+  case ELF::EM_AARCH64:
+#undef AARCH64_DYNAMIC_TAG
+#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef AARCH64_DYNAMIC_TAG
+#define AARCH64_DYNAMIC_TAG(name, value)
+    break;
   case ELF::EM_MIPS:
 #undef MIPS_DYNAMIC_TAG
 #define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
@@ -714,7 +722,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG>::enumeration(
 #include "llvm/BinaryFormat/DynamicTags.def"
     break;
   }
-
+#undef AARCH64_DYNAMIC_TAG
 #undef MIPS_DYNAMIC_TAG
 #undef HEXAGON_DYNAMIC_TAG
 #undef PPC64_DYNAMIC_TAG
index e60034afc80a22346f008371171e15470993cd6e..653a7e9eeb0dd5c4955fa6f337c851b05d7cae95 100644 (file)
@@ -200,3 +200,41 @@ ProgramHeaders:
     VAddr: 0x1010
     Sections:
       - Section: .dynamic
+
+# Fourth document: AARCH64
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_AARCH64
+Sections:
+  - Name:    .dynstr
+    Type:    SHT_STRTAB
+    Address: 0x1000
+    Size:    0x10
+    Content: "004400550066007700"
+  - Name:    .dynamic
+    Type:    SHT_DYNAMIC
+    Address: 0x1010
+    Entries:
+      - Tag:   DT_HASH
+        Value: 0x1000
+      - Tag:   DT_AARCH64_BTI_PLT
+        Value: 0
+      - Tag:   DT_AARCH64_PAC_PLT
+        Value: 0
+      - Tag:   0x1234abcd
+        Value: 0x1
+      - Tag:   DT_NULL
+        Value: 0
+ProgramHeaders:
+  - Type: PT_LOAD
+    VAddr: 0x1000
+    Sections:
+      - Section: .dynstr
+      - Section: .dynamic
+  - Type: PT_DYNAMIC
+    VAddr: 0x1010
+    Sections:
+      - Section: .dynamic
index 06c8b6d3fbe70c732007248a1bd96470fb627c9d..1d6c3b33b88c09849e5bfae2409916e40e9e78ab 100644 (file)
 # GNU-PPC-NEXT:   0x0000000070000000 (PPC64_GLINK)        0x1000
 # GNU-PPC-NEXT:   0x000000001234abcd (unknown)            0x1
 # GNU-PPC-NEXT:   0x0000000000000000 (NULL)               0x0
+
+# Test that AARCH64 machine-specific tags can be dumped.
+# RUN: yaml2obj --docnum=4 %S/Inputs/elf-dynamic-tags-machine-specific.yaml -o %t.aarch64
+# RUN: llvm-readobj --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=LLVM-AARCH64
+# RUN: llvm-readelf --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=GNU-AARCH64
+
+# LLVM-AARCH64:     DynamicSection [ (5 entries)
+# LLVM-AARCH64-NEXT:  Tag                Type                 Name/Value
+# LLVM-AARCH64-NEXT:  0x0000000000000004 HASH                 0x1000
+# LLVM-AARCH64-NEXT:  0x0000000070000001 AARCH64_BTI_PLT      0
+# LLVM-AARCH64-NEXT:  0x0000000070000003 AARCH64_PAC_PLT      0
+# LLVM-AARCH64-NEXT:  0x000000001234ABCD unknown              0x1
+# LLVM-AARCH64-NEXT:  0x0000000000000000 NULL                 0x0
+# LLVM-AARCH64-NEXT:]
+
+# GNU-AARCH64:      Dynamic section at offset {{.*}} contains 5 entries:
+# GNU-AARCH64-NEXT:  Tag                Type                 Name/Value
+# GNU-AARCH64-NEXT:  0x0000000000000004 (HASH)               0x1000
+# GNU-AARCH64-NEXT:  0x0000000070000001 (AARCH64_BTI_PLT)    0
+# GNU-AARCH64-NEXT:  0x0000000070000003 (AARCH64_PAC_PLT)    0
+# GNU-AARCH64-NEXT:  0x000000001234abcd (unknown)            0x1
+# GNU-AARCH64-NEXT:  0x0000000000000000 (NULL)               0x0
index bc9323712660167c43b5f0364200683811a564f2..badb9cc3edd6d2dbb98f15dde0d9f3e7e9e0aafe 100644 (file)
@@ -249,12 +249,36 @@ Sections:
       - Tag:             DT_PPC64_GLINK
         Value:           0x0000000000000001
 
+## Check we can handle AARCH64 specific tags.
+# RUN: yaml2obj -docnum=4 %s -o %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=AARCH64
+
+# AARCH64:      - Tag:             DT_AARCH64_BTI_PLT
+# AARCH64-NEXT:   Value:           0x0000000000000000
+# AARCH64-NEXT: - Tag:             DT_AARCH64_PAC_PLT
+# AARCH64-NEXT:   Value:           0x0000000000000000
+
+--- !ELF
+FileHeader:
+  Class:             ELFCLASS64
+  Data:              ELFDATA2LSB
+  Type:              ET_REL
+  Machine:           EM_AARCH64
+Sections:
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Entries:
+      - Tag:             DT_AARCH64_BTI_PLT
+        Value:           0x0000000000000000
+      - Tag:             DT_AARCH64_PAC_PLT
+        Value:           0x0000000000000000
+
 ## Check we can't use a tag from a different architecture,
 ## even if it has the same numeric value as a valid tag.
 ## Here for EM_PPC64 we are trying to use DT_HEXAGON_SYMSZ
 ## instead of DT_PPC64_GLINK. They both have value of 0x70000000.
 
-# RUN: not yaml2obj -docnum=4 %s 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj -docnum=5 %s 2>&1 | FileCheck %s --check-prefix=ERR
 # ERR:      error: invalid hex64 number
 # ERR-NEXT: - Tag: DT_HEXAGON_SYMSZ
 
index f87be61046e0bec94f7a2562d34160fb09afeec1..f41adaeaed6b5d4b81da6015ea10f73ca0403153 100644 (file)
@@ -1463,6 +1463,17 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
 static const char *getTypeString(unsigned Arch, uint64_t Type) {
 #define DYNAMIC_TAG(n, v)
   switch (Arch) {
+
+  case EM_AARCH64:
+    switch (Type) {
+#define AARCH64_DYNAMIC_TAG(name, value)                                       \
+    case DT_##name:                                                            \
+      return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef AARCH64_DYNAMIC_TAG
+    }
+    break;
+
   case EM_HEXAGON:
     switch (Type) {
 #define HEXAGON_DYNAMIC_TAG(name, value)                                       \
@@ -1496,6 +1507,7 @@ static const char *getTypeString(unsigned Arch, uint64_t Type) {
 #undef DYNAMIC_TAG
   switch (Type) {
 // Now handle all dynamic tags except the architecture specific ones
+#define AARCH64_DYNAMIC_TAG(name, value)
 #define MIPS_DYNAMIC_TAG(name, value)
 #define HEXAGON_DYNAMIC_TAG(name, value)
 #define PPC64_DYNAMIC_TAG(name, value)
@@ -1506,6 +1518,7 @@ static const char *getTypeString(unsigned Arch, uint64_t Type) {
     return #name;
 #include "llvm/BinaryFormat/DynamicTags.def"
 #undef DYNAMIC_TAG
+#undef AARCH64_DYNAMIC_TAG
 #undef MIPS_DYNAMIC_TAG
 #undef HEXAGON_DYNAMIC_TAG
 #undef PPC64_DYNAMIC_TAG
@@ -1783,6 +1796,93 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
                                         uint64_t Value) const {
   const char *ConvChar =
       (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
+
+  // Handle custom printing of architecture specific tags
+  switch (ObjF->getELFFile()->getHeader()->e_machine) {
+  case EM_AARCH64:
+    switch (Type) {
+    case DT_AARCH64_BTI_PLT:
+    case DT_AARCH64_PAC_PLT:
+      OS << Value;
+      return;
+    default:
+      break;
+    }
+    break;
+  case EM_HEXAGON:
+    switch (Type) {
+    case DT_HEXAGON_VER:
+      OS << Value;
+      return;
+    case DT_HEXAGON_SYMSZ:
+    case DT_HEXAGON_PLT:
+      OS << format(ConvChar, Value);
+      return;
+    default:
+      break;
+    }
+    break;
+  case EM_MIPS:
+    switch (Type) {
+    case DT_MIPS_RLD_VERSION:
+    case DT_MIPS_LOCAL_GOTNO:
+    case DT_MIPS_SYMTABNO:
+    case DT_MIPS_UNREFEXTNO:
+      OS << Value;
+      return;
+    case DT_MIPS_TIME_STAMP:
+    case DT_MIPS_ICHECKSUM:
+    case DT_MIPS_IVERSION:
+    case DT_MIPS_BASE_ADDRESS:
+    case DT_MIPS_MSYM:
+    case DT_MIPS_CONFLICT:
+    case DT_MIPS_LIBLIST:
+    case DT_MIPS_CONFLICTNO:
+    case DT_MIPS_LIBLISTNO:
+    case DT_MIPS_GOTSYM:
+    case DT_MIPS_HIPAGENO:
+    case DT_MIPS_RLD_MAP:
+    case DT_MIPS_DELTA_CLASS:
+    case DT_MIPS_DELTA_CLASS_NO:
+    case DT_MIPS_DELTA_INSTANCE:
+    case DT_MIPS_DELTA_RELOC:
+    case DT_MIPS_DELTA_RELOC_NO:
+    case DT_MIPS_DELTA_SYM:
+    case DT_MIPS_DELTA_SYM_NO:
+    case DT_MIPS_DELTA_CLASSSYM:
+    case DT_MIPS_DELTA_CLASSSYM_NO:
+    case DT_MIPS_CXX_FLAGS:
+    case DT_MIPS_PIXIE_INIT:
+    case DT_MIPS_SYMBOL_LIB:
+    case DT_MIPS_LOCALPAGE_GOTIDX:
+    case DT_MIPS_LOCAL_GOTIDX:
+    case DT_MIPS_HIDDEN_GOTIDX:
+    case DT_MIPS_PROTECTED_GOTIDX:
+    case DT_MIPS_OPTIONS:
+    case DT_MIPS_INTERFACE:
+    case DT_MIPS_DYNSTR_ALIGN:
+    case DT_MIPS_INTERFACE_SIZE:
+    case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
+    case DT_MIPS_PERF_SUFFIX:
+    case DT_MIPS_COMPACT_SIZE:
+    case DT_MIPS_GP_VALUE:
+    case DT_MIPS_AUX_DYNAMIC:
+    case DT_MIPS_PLTGOT:
+    case DT_MIPS_RWPLT:
+    case DT_MIPS_RLD_MAP_REL:
+      OS << format(ConvChar, Value);
+      return;
+    case DT_MIPS_FLAGS:
+      printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
+      return;
+    default:
+      break;
+    }
+    break;
+  default:
+    break;
+  }
+
   switch (Type) {
   case DT_PLTREL:
     if (Value == DT_REL) {
@@ -1811,22 +1911,12 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case DT_VERSYM:
   case DT_GNU_HASH:
   case DT_NULL:
-  case DT_MIPS_BASE_ADDRESS:
-  case DT_MIPS_GOTSYM:
-  case DT_MIPS_RLD_MAP:
-  case DT_MIPS_RLD_MAP_REL:
-  case DT_MIPS_PLTGOT:
-  case DT_MIPS_OPTIONS:
     OS << format(ConvChar, Value);
     break;
   case DT_RELACOUNT:
   case DT_RELCOUNT:
   case DT_VERDEFNUM:
   case DT_VERNEEDNUM:
-  case DT_MIPS_RLD_VERSION:
-  case DT_MIPS_LOCAL_GOTNO:
-  case DT_MIPS_SYMTABNO:
-  case DT_MIPS_UNREFEXTNO:
     OS << Value;
     break;
   case DT_PLTRELSZ:
@@ -1862,9 +1952,6 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case DT_RUNPATH:
     OS << getDynamicString(Value);
     break;
-  case DT_MIPS_FLAGS:
-    printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
-    break;
   case DT_FLAGS:
     printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
     break;