[llvm] [llvm-readobj][AArch64][ELF][PAC] Support ELF AUTH constants (PR #72713)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 5 16:49:25 PST 2023


https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/72713

>From 647aa46d708b5ffe89a5393e09c92f6c8227b621 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 4 Dec 2023 13:04:10 +0300
Subject: [PATCH 1/2] [llvm-readobj][AArch64][ELF][PAC] Support ELF AUTH
 constants

This patch adds llvm-readobj support for:

- Dynamic R_AARCH64_AUTH_* relocations (including RELR compressed AUTH
  relocations) as described here:
  https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#auth-variant-dynamic-relocations

- .note.AARCH64-PAUTH-ABI-tag section as defined here
  https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking
---
 .../include/llvm/BinaryFormat/DynamicTags.def |   6 +
 llvm/include/llvm/BinaryFormat/ELF.h          |   8 ++
 .../llvm/BinaryFormat/ELFRelocs/AArch64.def   |   1 +
 llvm/lib/Object/ELF.cpp                       |   1 +
 llvm/lib/ObjectYAML/ELFYAML.cpp               |   1 +
 .../ELF/AArch64/aarch64-feature-pauth.s       |  98 +++++++++++++++
 .../ELF/broken-dynamic-reloc.test             |  40 ++++++
 .../ELF/dynamic-tags-machine-specific.test    |  32 +++--
 .../tools/llvm-readobj/ELF/relr-relocs.test   |  22 +++-
 .../tools/llvm-readobj/ELF/section-types.test |   5 +
 llvm/tools/llvm-readobj/ELFDumper.cpp         | 114 +++++++++++++++---
 11 files changed, 302 insertions(+), 26 deletions(-)
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s

diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def
index f393b82406b41..1502d375f5c45 100644
--- a/llvm/include/llvm/BinaryFormat/DynamicTags.def
+++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def
@@ -132,6 +132,12 @@ AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_STACK, 0x7000000c)
 AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALS, 0x7000000d)
 AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALSSZ, 0x7000000f)
 
+// AArch64 specific dynamic table entries for RELR auth relocations as described here:
+// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#dynamic-section
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRSZ, 0x70000011)
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELR, 0x70000012)
+AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRENT, 0x70000013)
+
 // Hexagon specific dynamic table entries
 HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000)
 HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index d1ce8e20b4be7..40c795410f95a 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1060,6 +1060,9 @@ enum : unsigned {
   SHT_ARM_ATTRIBUTES = 0x70000003U,
   SHT_ARM_DEBUGOVERLAY = 0x70000004U,
   SHT_ARM_OVERLAYSECTION = 0x70000005U,
+  // Special aarch64-specific section for MTE support, as described in:
+  // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types
+  SHT_AARCH64_AUTH_RELR = 0x70000004U,
   // Special aarch64-specific sections for MTE support, as described in:
   // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#7section-types
   SHT_AARCH64_MEMTAG_GLOBALS_STATIC = 0x70000007U,
@@ -1647,6 +1650,11 @@ enum {
   NT_ANDROID_TYPE_MEMTAG = 4,
 };
 
+// ARM note types.
+enum {
+  NT_ARM_TYPE_PAUTH_ABI_TAG = 1,
+};
+
 // Memory tagging values used in NT_ANDROID_TYPE_MEMTAG notes.
 enum {
   // Enumeration to determine the tagging mode. In Android-land, 'SYNC' means
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
index b507109b19e1b..b8ab5113bedf8 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
@@ -135,6 +135,7 @@ ELF_RELOC(R_AARCH64_TLS_TPREL64,                     0x406)
 ELF_RELOC(R_AARCH64_TLSDESC,                         0x407)
 ELF_RELOC(R_AARCH64_IRELATIVE,                       0x408)
 ELF_RELOC(R_AARCH64_AUTH_ABS64,                      0xe100)
+ELF_RELOC(R_AARCH64_AUTH_RELATIVE,                   0xe200)
 
 // ELF_RELOC(R_AARCH64_P32_NONE,                         0)
 ELF_RELOC(R_AARCH64_P32_ABS32,                       0x001)
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 1d73a6ffa73f5..66e03e2c7a2e2 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -299,6 +299,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
     STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
     STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
     STRINGIFY_ENUM_CASE(ELF, SHT_RELR);
+    STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_AUTH_RELR);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
     STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR);
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 1da4ea4e3edc9..38926368d2d23 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -672,6 +672,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
   ECase(SHT_GROUP);
   ECase(SHT_SYMTAB_SHNDX);
   ECase(SHT_RELR);
+  ECase(SHT_AARCH64_AUTH_RELR);
   ECase(SHT_ANDROID_REL);
   ECase(SHT_ANDROID_RELA);
   ECase(SHT_ANDROID_RELR);
diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s
new file mode 100644
index 0000000000000..1bbc6729bc702
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s
@@ -0,0 +1,98 @@
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag.s       -o tag.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o tag-short.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s  -o tag-long.o
+
+# RUN: llvm-readelf --notes tag.o       | FileCheck --check-prefix NORMAL %s
+# RUN: llvm-readelf --notes tag-short.o | FileCheck --check-prefix SHORT  %s
+# RUN: llvm-readelf --notes tag-long.o  | FileCheck --check-prefix LONG   %s
+
+# NORMAL: AArch64 PAuth ABI tag: platform 0x2a, version 0x1
+# SHORT:  AArch64 PAuth ABI tag: <corrupted size: expected at least 16, got 12>
+# LONG:   AArch64 PAuth ABI tag: platform 0x2a, version 0x1, additional info 0xEFCDAB8967452301
+
+# RUN: llvm-readobj --notes tag.o       | FileCheck --check-prefix LLVM-NORMAL %s
+# RUN: llvm-readobj --notes tag-short.o | FileCheck --check-prefix LLVM-SHORT %s
+# RUN: llvm-readobj --notes tag-long.o  | FileCheck --check-prefix LLVM-LONG %s
+
+// LLVM-SHORT:      Notes [
+// LLVM-SHORT-NEXT:   NoteSection {
+// LLVM-SHORT-NEXT:     Name: .note.AARCH64-PAUTH-ABI-tag
+// LLVM-SHORT-NEXT:     Offset: 0x40
+// LLVM-SHORT-NEXT:     Size: 0x1C
+// LLVM-SHORT-NEXT:     Note {
+// LLVM-SHORT-NEXT:       Owner: ARM
+// LLVM-SHORT-NEXT:       Data size: 0xC
+// LLVM-SHORT-NEXT:       Type: NT_ARM_TYPE_PAUTH_ABI_TAG
+// LLVM-SHORT-NEXT:       Description data (
+// LLVM-SHORT-NEXT:         0000: 2A000000 00000000 01000000
+// LLVM-SHORT-NEXT:       )
+// LLVM-SHORT-NEXT:     }
+// LLVM-SHORT-NEXT:   }
+// LLVM-SHORT-NEXT: ]
+
+// LLVM-NORMAL:      Notes [
+// LLVM-NORMAL-NEXT:   NoteSection {
+// LLVM-NORMAL-NEXT:     Name: .note.AARCH64-PAUTH-ABI-tag
+// LLVM-NORMAL-NEXT:     Offset: 0x40
+// LLVM-NORMAL-NEXT:     Size: 0x20
+// LLVM-NORMAL-NEXT:     Note {
+// LLVM-NORMAL-NEXT:       Owner: ARM
+// LLVM-NORMAL-NEXT:       Data size: 0x10
+// LLVM-NORMAL-NEXT:       Type: NT_ARM_TYPE_PAUTH_ABI_TAG
+// LLVM-NORMAL-NEXT:       Platform: 42
+// LLVM-NORMAL-NEXT:       Version: 1
+// LLVM-NORMAL-NEXT:     }
+// LLVM-NORMAL-NEXT:   }
+// LLVM-NORMAL-NEXT: ]
+
+// LLVM-LONG:      Notes [
+// LLVM-LONG-NEXT:   NoteSection {
+// LLVM-LONG-NEXT:     Name: .note.AARCH64-PAUTH-ABI-tag
+// LLVM-LONG-NEXT:     Offset: 0x40
+// LLVM-LONG-NEXT:     Size: 0x28
+// LLVM-LONG-NEXT:     Note {
+// LLVM-LONG-NEXT:       Owner: ARM
+// LLVM-LONG-NEXT:       Data size: 0x18
+// LLVM-LONG-NEXT:       Type: NT_ARM_TYPE_PAUTH_ABI_TAG
+// LLVM-LONG-NEXT:       Platform: 42
+// LLVM-LONG-NEXT:       Version: 1
+// LLVM-LONG-NEXT:       Additional info: EFCDAB8967452301
+// LLVM-LONG-NEXT:     }
+// LLVM-LONG-NEXT:   }
+// LLVM-LONG-NEXT: ]
+
+#--- abi-tag.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 16
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 1          // version
+
+#--- abi-tag-short.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 12
+.long 1
+.asciz "ARM"
+
+.quad 42
+.word 1
+
+#--- abi-tag-long.s
+
+.section ".note.AARCH64-PAUTH-ABI-tag", "a"
+.long 4
+.long 24
+.long 1
+.asciz "ARM"
+
+.quad 42         // platform
+.quad 1          // version
+.quad 0x0123456789ABCDEF // extra data
diff --git a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
index 1a1c6dd4d0d1c..f4899f6df6513 100644
--- a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
+++ b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
@@ -459,3 +459,43 @@ ProgramHeaders:
   - Type:     PT_DYNAMIC
     FirstSec: .dynamic
     LastSec:  .dynamic
+
+## Show we print a warning for an invalid relocation table size stored in a DT_AARCH64_AUTH_RELRSZ entry.
+# RUN: yaml2obj --docnum=8 -DRELTYPE=RELR -DTAG1=DT_AARCH64_AUTH_RELRSZ -DTAG1VAL=0xFF -DTAG2=DT_AARCH64_AUTH_RELRENT %s -o %t14
+# RUN: llvm-readobj --dyn-relocations %t14 2>&1 | FileCheck %s -DFILE=%t14 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRSZ
+# RUN: llvm-readelf --dyn-relocations %t14 2>&1 | FileCheck %s -DFILE=%t14 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRSZ
+
+# INVALID-DT-AARCH64-AUTH-RELRSZ: warning: '[[FILE]]': invalid DT_AARCH64_AUTH_RELRSZ value (0xff) or DT_AARCH64_AUTH_RELRENT value (0x18)
+
+## Show we print a warning for an invalid relocation table entry size stored in a DT_AARCH64_AUTH_RELRENT entry.
+# RUN: yaml2obj --docnum=8 -DRELTYPE=RELR -DTAG1=DT_AARCH64_AUTH_RELRSZ -DTAG2=DT_AARCH64_AUTH_RELRENT -DTAG2VAL=0xFF %s -o %t15
+# RUN: llvm-readobj --dyn-relocations %t15 2>&1 | FileCheck %s -DFILE=%t15 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRENT
+# RUN: llvm-readelf --dyn-relocations %t15 2>&1 | FileCheck %s -DFILE=%t15 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRENT
+
+# INVALID-DT-AARCH64-AUTH-RELRENT: invalid DT_AARCH64_AUTH_RELRSZ value (0x18) or DT_AARCH64_AUTH_RELRENT value (0xff)
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_DYN
+  Machine: EM_AARCH64
+Sections:
+  - Name:  .relx.dyn
+    Type:  SHT_[[RELTYPE]]
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_[[RELTYPE]]
+        Value: 0x0
+      - Tag:   [[TAG1]]
+        Value: [[TAG1VAL=0x18]]
+      - Tag:   [[TAG2]]
+        Value: [[TAG2VAL=0x18]]
+      - Tag:   DT_NULL
+        Value: 0x0
+DynamicSymbols: []
+ProgramHeaders:
+  - Type:     PT_LOAD
+    FirstSec: .relx.dyn
+    LastSec:  .dynamic
diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
index c32ea33b9b3cb..e7bd9cf9b48b2 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
@@ -355,20 +355,26 @@ ProgramHeaders:
 # 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 [ (4 entries)
+# LLVM-AARCH64:     DynamicSection [ (7 entries)
 # LLVM-AARCH64-NEXT:  Tag                Type                Name/Value
-# LLVM-AARCH64-NEXT:  0x0000000070000001 AARCH64_BTI_PLT     1
-# LLVM-AARCH64-NEXT:  0x0000000070000003 AARCH64_PAC_PLT     2
-# LLVM-AARCH64-NEXT:  0x0000000070000005 AARCH64_VARIANT_PCS 3
-# LLVM-AARCH64-NEXT:  0x0000000000000000 NULL                0x0
+# LLVM-AARCH64-NEXT:  0x0000000070000001 AARCH64_BTI_PLT      1
+# LLVM-AARCH64-NEXT:  0x0000000070000003 AARCH64_PAC_PLT      2
+# LLVM-AARCH64-NEXT:  0x0000000070000005 AARCH64_VARIANT_PCS  3
+# LLVM-AARCH64-NEXT:  0x0000000070000012 AARCH64_AUTH_RELR    0x4
+# LLVM-AARCH64-NEXT:  0x0000000070000011 AARCH64_AUTH_RELRSZ  5
+# LLVM-AARCH64-NEXT:  0x0000000070000013 AARCH64_AUTH_RELRENT 6
+# LLVM-AARCH64-NEXT:  0x0000000000000000 NULL                 0x0
 # LLVM-AARCH64-NEXT:]
 
-# GNU-AARCH64:      Dynamic section at offset {{.*}} contains 4 entries:
+# GNU-AARCH64:      Dynamic section at offset {{.*}} contains 7 entries:
 # GNU-AARCH64-NEXT:  Tag                Type                  Name/Value
-# GNU-AARCH64-NEXT:  0x0000000070000001 (AARCH64_BTI_PLT)     1
-# GNU-AARCH64-NEXT:  0x0000000070000003 (AARCH64_PAC_PLT)     2
-# GNU-AARCH64-NEXT:  0x0000000070000005 (AARCH64_VARIANT_PCS) 3
-# GNU-AARCH64-NEXT:  0x0000000000000000 (NULL)                0x0
+# GNU-AARCH64-NEXT:  0x0000000070000001 (AARCH64_BTI_PLT)      1
+# GNU-AARCH64-NEXT:  0x0000000070000003 (AARCH64_PAC_PLT)      2
+# GNU-AARCH64-NEXT:  0x0000000070000005 (AARCH64_VARIANT_PCS)  3
+# GNU-AARCH64-NEXT:  0x0000000070000012 (AARCH64_AUTH_RELR)    0x4
+# GNU-AARCH64-NEXT:  0x0000000070000011 (AARCH64_AUTH_RELRSZ)  5
+# GNU-AARCH64-NEXT:  0x0000000070000013 (AARCH64_AUTH_RELRENT) 6
+# GNU-AARCH64-NEXT:  0x0000000000000000 (NULL)                 0x0
 
 --- !ELF
 FileHeader:
@@ -386,6 +392,12 @@ Sections:
         Value: 2
       - Tag:   DT_AARCH64_VARIANT_PCS
         Value: 3
+      - Tag:   DT_AARCH64_AUTH_RELR
+        Value: 4
+      - Tag:   DT_AARCH64_AUTH_RELRSZ
+        Value: 5
+      - Tag:   DT_AARCH64_AUTH_RELRENT
+        Value: 6
       - Tag:   DT_NULL
         Value: 0
 ProgramHeaders:
diff --git a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
index 3bb54b1adc1f4..704676b60f012 100644
--- a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
+++ b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
@@ -158,7 +158,7 @@ Sections:
     Link:    [[LINK=<none>]]
 
 ## Check we report a warning when we are unable to dump relocations
-## for a SHT_RELR/SHT_ANDROID_RELR section.
+## for a SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section.
 
 ## Case A: check the case when relocations can't be read from an SHT_RELR section.
 # RUN: yaml2obj --docnum=2 -DENTSIZE=1 %s -o %t2.broken
@@ -186,7 +186,25 @@ Sections:
 # RUN: llvm-readelf --relocations %t2.broken.android 2>&1 | \
 # RUN:   FileCheck -DFILE=%t2.broken.android --check-prefix=BROKEN-GNU %s -DSECNAME=SHT_ANDROID_RELR
 
-## Check the behavior when the sh_link field of the SHT_RELR/SHT_ANDROID_RELR section
+## Case C: check the case when relocations can't be read from an SHT_AARCH64_AUTH_RELR section.
+##         SHT_AARCH64_AUTH_RELR = 0x70000004.
+# RUN: yaml2obj --docnum=2 -DENTSIZE=1 -DSHTYPE=0x70000004 %s -o %t2.broken.aarch64auth
+# RUN: llvm-readobj --relocations %t2.broken.aarch64auth 2>&1 | \
+# RUN:   FileCheck -DFILE=%t2.broken.aarch64auth --check-prefix=BROKEN-LLVM-AARCH64-AUTH %s -DSECNAME=SHT_AARCH64_AUTH_RELR
+# RUN: llvm-readelf --relocations %t2.broken.aarch64auth 2>&1 | \
+# RUN:   FileCheck -DFILE=%t2.broken.aarch64auth --check-prefix=BROKEN-GNU-AARCH64-AUTH %s -DSECNAME=SHT_AARCH64_AUTH_RELR
+
+# BROKEN-LLVM-AARCH64-AUTH:      Relocations [
+# BROKEN-LLVM-AARCH64-AUTH-NEXT:   Section (1) .relr.dyn {
+# BROKEN-LLVM-AARCH64-AUTH-NEXT: warning: '[[FILE]]': SHT_AARCH64_AUTH_RELR section in non-AArch64 ELF found, skipping
+# BROKEN-LLVM-AARCH64-AUTH-NEXT:   }
+# BROKEN-LLVM-AARCH64-AUTH-NEXT: ]
+
+# BROKEN-GNU-AARCH64-AUTH:      Relocation section '.relr.dyn' at offset 0x34 contains <?> entries:
+# BROKEN-GNU-AARCH64-AUTH-NEXT:  Offset     Info    Type                Sym. Value  Symbol's Name
+# BROKEN-GNU-AARCH64-AUTH-NEXT: warning: '[[FILE]]': SHT_AARCH64_AUTH_RELR section in non-AArch64 ELF found, skipping
+
+## Check the behavior when the sh_link field of the SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section
 ## is set to an arbitrary value. Normally, it is set to 0, because such sections contains
 ## only relative relocations and do not have an associated symbol table, like other
 ## relocation sections.
diff --git a/llvm/test/tools/llvm-readobj/ELF/section-types.test b/llvm/test/tools/llvm-readobj/ELF/section-types.test
index 071ca80575849..910ca9e9b98fe 100644
--- a/llvm/test/tools/llvm-readobj/ELF/section-types.test
+++ b/llvm/test/tools/llvm-readobj/ELF/section-types.test
@@ -43,6 +43,8 @@
 # LLVM: Type: SHT_ANDROID_RELA
 # LLVM: Name: android_relr
 # LLVM: Type: SHT_ANDROID_RELR
+# LLVM: Name: aarch64_auth_relr
+# LLVM: Type: SHT_AARCH64_AUTH_RELR
 # LLVM: Name: llvm_odrtab
 # LLVM: Type: SHT_LLVM_ODRTAB
 # LLVM: Name: linker_options
@@ -113,6 +115,7 @@
 # GNU-NEXT: android_rel             ANDROID_REL
 # GNU-NEXT: android_rela            ANDROID_RELA
 # GNU-NEXT: android_relr            ANDROID_RELR
+# GNU-NEXT: aarch64_auth_relr       AARCH64_AUTH_RELR
 # GNU-NEXT: llvm_odrtab             LLVM_ODRTAB
 # GNU-NEXT: linker_options          LLVM_LINKER_OPTIONS
 # GNU-NEXT: llvm_call_graph_profile LLVM_CALL_GRAPH_PROFILE
@@ -191,6 +194,8 @@ Sections:
     Type: SHT_ANDROID_RELA
   - Name: android_relr
     Type: SHT_ANDROID_RELR
+  - Name: aarch64_auth_relr
+    Type: SHT_AARCH64_AUTH_RELR
   - Name: llvm_odrtab
     Type: SHT_LLVM_ODRTAB
   - Name: linker_options
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index d6d0ea35044ab..1e7fe3a7f713f 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -2090,21 +2090,34 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
       break;
     case ELF::DT_RELR:
     case ELF::DT_ANDROID_RELR:
+    case ELF::DT_AARCH64_AUTH_RELR:
       DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELRSZ:
     case ELF::DT_ANDROID_RELRSZ:
+    case ELF::DT_AARCH64_AUTH_RELRSZ:
       DynRelrRegion.Size = Dyn.getVal();
-      DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ
-                                        ? "DT_RELRSZ value"
-                                        : "DT_ANDROID_RELRSZ value";
+      if (Dyn.d_tag == ELF::DT_RELRSZ)
+        DynRelrRegion.SizePrintName = "DT_RELRSZ value";
+      else if (Dyn.d_tag == ELF::DT_ANDROID_RELRSZ)
+        DynRelrRegion.SizePrintName = "DT_ANDROID_RELRSZ value";
+      else if (Dyn.d_tag == ELF::DT_AARCH64_AUTH_RELRSZ)
+        DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";
+      else
+        llvm_unreachable("unexpected Dyn.d_tag value");
       break;
     case ELF::DT_RELRENT:
     case ELF::DT_ANDROID_RELRENT:
+    case ELF::DT_AARCH64_AUTH_RELRENT:
       DynRelrRegion.EntSize = Dyn.getVal();
-      DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT
-                                           ? "DT_RELRENT value"
-                                           : "DT_ANDROID_RELRENT value";
+      if (Dyn.d_tag == ELF::DT_RELRENT)
+        DynRelrRegion.EntSizePrintName = "DT_RELRENT value";
+      else if (Dyn.d_tag == ELF::DT_ANDROID_RELRENT)
+        DynRelrRegion.EntSizePrintName = "DT_ANDROID_RELRENT value";
+      else if (Dyn.d_tag == ELF::DT_AARCH64_AUTH_RELRENT)
+        DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";
+      else
+        llvm_unreachable("unexpected Dyn.d_tag value");
       break;
     case ELF::DT_PLTREL:
       if (Dyn.getVal() == DT_REL)
@@ -2467,6 +2480,8 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
   case DT_PREINIT_ARRAYSZ:
   case DT_RELRSZ:
   case DT_RELRENT:
+  case DT_AARCH64_AUTH_RELRSZ:
+  case DT_AARCH64_AUTH_RELRENT:
   case DT_ANDROID_RELSZ:
   case DT_ANDROID_RELASZ:
     return std::to_string(Value) + " (bytes)";
@@ -3801,7 +3816,8 @@ void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
 template <class ELFT>
 static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType) {
   bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
-  bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR;
+  bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR ||
+                SType == ELF::SHT_AARCH64_AUTH_RELR;
   if (ELFT::Is64Bits)
     OS << "    ";
   else
@@ -3834,7 +3850,8 @@ static bool isRelocationSec(const typename ELFT::Shdr &Sec) {
   return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||
          Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL ||
          Sec.sh_type == ELF::SHT_ANDROID_RELA ||
-         Sec.sh_type == ELF::SHT_ANDROID_RELR;
+         Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR;
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
@@ -3850,8 +3867,9 @@ template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
       return RelasOrErr->size();
     }
 
-    if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
-                           Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
+    if (!opts::RawRelr &&
+        (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {
       Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
       if (!RelrsOrErr)
         return RelrsOrErr.takeError();
@@ -5312,6 +5330,31 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,
   return true;
 }
 
+template <class ELFT>
+static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType,
+                             ArrayRef<uint8_t> Desc) {
+  if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    return false;
+
+  OS << "    AArch64 PAuth ABI tag: ";
+  if (Desc.size() < 16) {
+    OS << format("<corrupted size: expected at least 16, got %d>", Desc.size());
+    return false;
+  }
+
+  uint64_t platform =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
+  uint64_t version =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
+  OS << format("platform 0x%x, version 0x%x", platform, version);
+
+  if (Desc.size() > 16)
+    OS << ", additional info 0x"
+       << toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16));
+
+  return true;
+}
+
 template <class ELFT>
 void GNUELFDumper<ELFT>::printMemtag(
     const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
@@ -5711,6 +5754,10 @@ const NoteType AndroidNoteTypes[] = {
      "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"},
 };
 
+const NoteType ARMNoteTypes[] = {
+    {ELF::NT_ARM_TYPE_PAUTH_ABI_TAG, "NT_ARM_TYPE_PAUTH_ABI_TAG"},
+};
+
 const NoteType CoreNoteTypes[] = {
     {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},
     {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},
@@ -5829,6 +5876,8 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
     return FindNote(LLVMOMPOFFLOADNoteTypes);
   if (Name == "Android")
     return FindNote(AndroidNoteTypes);
+  if (Name == "ARM")
+    return FindNote(ARMNoteTypes);
 
   if (ELFType == ELF::ET_CORE)
     return FindNote(CoreNoteTypes);
@@ -5984,6 +6033,9 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
     } else if (Name == "Android") {
       if (printAndroidNote(OS, Type, Descriptor))
         return Error::success();
+    } else if (Name == "ARM") {
+      if (printAArch64Note<ELFT>(OS, Type, Descriptor))
+        return Error::success();
     }
     if (!Descriptor.empty()) {
       OS << "   description data:";
@@ -6176,11 +6228,12 @@ void ELFDumper<ELFT>::forEachRelocationDo(
                               toString(std::move(E)));
   };
 
-  // SHT_RELR/SHT_ANDROID_RELR sections do not have an associated symbol table.
-  // For them we should not treat the value of the sh_link field as an index of
-  // a symbol table.
+  // SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an
+  // associated symbol table. For them we should not treat the value of the
+  // sh_link field as an index of a symbol table.
   const Elf_Shdr *SymTab;
-  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR) {
+  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&
+      Sec.sh_type != ELF::SHT_AARCH64_AUTH_RELR) {
     Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);
     if (!SymTabOrErr) {
       Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");
@@ -6208,6 +6261,13 @@ void ELFDumper<ELFT>::forEachRelocationDo(
       Warn(RangeOrErr.takeError());
     }
     break;
+  case ELF::SHT_AARCH64_AUTH_RELR:
+    if (Obj.getHeader().e_machine != EM_AARCH64) {
+      this->reportUniqueWarning(
+          "SHT_AARCH64_AUTH_RELR section in non-AArch64 ELF found, skipping");
+      break;
+    }
+    [[fallthrough]];
   case ELF::SHT_RELR:
   case ELF::SHT_ANDROID_RELR: {
     Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);
@@ -7545,6 +7605,29 @@ static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
   return true;
 }
 
+template <class ELFT>
+static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
+                                      ScopedPrinter &W) {
+  if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    return false;
+
+  if (Desc.size() < 16)
+    return false;
+
+  uint64_t platform =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
+  uint64_t version =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
+  W.printNumber("Platform", platform);
+  W.printNumber("Version", version);
+
+  if (Desc.size() > 16)
+    W.printString("Additional info",
+                  toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16)));
+
+  return true;
+}
+
 template <class ELFT>
 void LLVMELFDumper<ELFT>::printMemtag(
     const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
@@ -7681,6 +7764,9 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
     } else if (Name == "Android") {
       if (printAndroidNoteLLVMStyle(Type, Descriptor, W))
         return Error::success();
+    } else if (Name == "ARM") {
+      if (printAarch64NoteLLVMStyle<ELFT>(Type, Descriptor, W))
+        return Error::success();
     }
     if (!Descriptor.empty()) {
       W.printBinaryBlock("Description data", Descriptor);

>From 8d7ee46a6bd46bacde19e4524ec7a33705ac3f7f Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 6 Dec 2023 03:43:03 +0300
Subject: [PATCH 2/2] Address review comments

---
 llvm/tools/llvm-readobj/ELFDumper.cpp | 40 ++++++++++++++-------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 1e7fe3a7f713f..f33076e804daa 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -2027,6 +2027,18 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
   uint64_t StringTableSize = 0;
   std::optional<DynRegionInfo> DynSymFromTable;
   for (const Elf_Dyn &Dyn : dynamic_table()) {
+    if (Obj.getHeader().e_machine == EM_AARCH64) {
+      switch (Dyn.d_tag) {
+      case ELF::DT_AARCH64_AUTH_RELRSZ:
+        DynRelrRegion.Size = Dyn.getVal();
+        DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";
+        continue;
+      case ELF::DT_AARCH64_AUTH_RELRENT:
+        DynRelrRegion.EntSize = Dyn.getVal();
+        DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";
+        continue;
+      }
+    }
     switch (Dyn.d_tag) {
     case ELF::DT_HASH:
       HashTable = reinterpret_cast<const Elf_Hash *>(
@@ -2097,27 +2109,17 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
     case ELF::DT_ANDROID_RELRSZ:
     case ELF::DT_AARCH64_AUTH_RELRSZ:
       DynRelrRegion.Size = Dyn.getVal();
-      if (Dyn.d_tag == ELF::DT_RELRSZ)
-        DynRelrRegion.SizePrintName = "DT_RELRSZ value";
-      else if (Dyn.d_tag == ELF::DT_ANDROID_RELRSZ)
-        DynRelrRegion.SizePrintName = "DT_ANDROID_RELRSZ value";
-      else if (Dyn.d_tag == ELF::DT_AARCH64_AUTH_RELRSZ)
-        DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";
-      else
-        llvm_unreachable("unexpected Dyn.d_tag value");
+      DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ
+                                        ? "DT_RELRSZ value"
+                                        : "DT_ANDROID_RELRSZ value";
       break;
     case ELF::DT_RELRENT:
     case ELF::DT_ANDROID_RELRENT:
     case ELF::DT_AARCH64_AUTH_RELRENT:
       DynRelrRegion.EntSize = Dyn.getVal();
-      if (Dyn.d_tag == ELF::DT_RELRENT)
-        DynRelrRegion.EntSizePrintName = "DT_RELRENT value";
-      else if (Dyn.d_tag == ELF::DT_ANDROID_RELRENT)
-        DynRelrRegion.EntSizePrintName = "DT_ANDROID_RELRENT value";
-      else if (Dyn.d_tag == ELF::DT_AARCH64_AUTH_RELRENT)
-        DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";
-      else
-        llvm_unreachable("unexpected Dyn.d_tag value");
+      DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT
+                                           ? "DT_RELRENT value"
+                                           : "DT_ANDROID_RELRENT value";
       break;
     case ELF::DT_PLTREL:
       if (Dyn.getVal() == DT_REL)
@@ -5342,11 +5344,11 @@ static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType,
     return false;
   }
 
-  uint64_t platform =
+  uint64_t Platform =
       support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
-  uint64_t version =
+  uint64_t Version =
       support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
-  OS << format("platform 0x%x, version 0x%x", platform, version);
+  OS << format("platform 0x%x, version 0x%x", Platform, Version);
 
   if (Desc.size() > 16)
     OS << ", additional info 0x"



More information about the llvm-commits mailing list