[lld] c574e93 - [lld] [MTE] Add DT_AARCH64_MEMTAG_* dynamic entries, and small cleanup

Mitch Phillips via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 1 11:14:21 PST 2023


Author: Mitch Phillips
Date: 2023-03-01T11:14:05-08:00
New Revision: c574e93afd2e5f7986abeece88449c84ebd2e76d

URL: https://github.com/llvm/llvm-project/commit/c574e93afd2e5f7986abeece88449c84ebd2e76d
DIFF: https://github.com/llvm/llvm-project/commit/c574e93afd2e5f7986abeece88449c84ebd2e76d.diff

LOG: [lld] [MTE] Add DT_AARCH64_MEMTAG_* dynamic entries, and small cleanup

Adds the new AArch64-ABI dynamic entry generation to LLD. This will
allow Android to move from the Android-specific ELF note onto the
dynamic entries.

Change the behaviour of an unspecified --android-memtag-mode. Now, when
unspecified, this will print a warning that you're doing a no-op, rather
than implicitly turning on sync mode. This is important for MTE globals
later, where a binary containing static tagged global descriptors
shouldn't have MTE turned on without specific intent being passed to the
linker.

For now, continue to emit the Android ELF note by default. In future, we
can probably make it only emit the note when provided a flag.

Do a quick NFC-cleanup of the ELF note while we're here. It doesn't
change anything about the ELF note itself, but makes it more clear to
the reader of the code what alignment requirements are being (previously
implicitly) met.

Reviewed By: fmayer, MaskRay

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

Added: 
    

Modified: 
    lld/ELF/Driver.cpp
    lld/ELF/SyntheticSections.cpp
    lld/test/ELF/aarch64-memtag-android-abi.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 93caf755196f9..d9915be8ca881 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -736,15 +736,24 @@ static StringRef getDynamicLinker(opt::InputArgList &args) {
 
 static int getMemtagMode(opt::InputArgList &args) {
   StringRef memtagModeArg = args.getLastArgValue(OPT_android_memtag_mode);
+  if (memtagModeArg.empty()) {
+    if (config->androidMemtagStack)
+      warn("--android-memtag-mode is unspecified, leaving "
+           "--android-memtag-stack a no-op");
+    else if (config->androidMemtagHeap)
+      warn("--android-memtag-mode is unspecified, leaving "
+           "--android-memtag-heap a no-op");
+    return ELF::NT_MEMTAG_LEVEL_NONE;
+  }
+
   if (!config->androidMemtagHeap && !config->androidMemtagStack) {
-    if (!memtagModeArg.empty())
-      error("when using --android-memtag-mode, at least one of "
-            "--android-memtag-heap or "
-            "--android-memtag-stack is required");
+    error("when using --android-memtag-mode, at least one of "
+          "--android-memtag-heap or "
+          "--android-memtag-stack is required");
     return ELF::NT_MEMTAG_LEVEL_NONE;
   }
 
-  if (memtagModeArg == "sync" || memtagModeArg.empty())
+  if (memtagModeArg == "sync")
     return ELF::NT_MEMTAG_LEVEL_SYNC;
   if (memtagModeArg == "async")
     return ELF::NT_MEMTAG_LEVEL_ASYNC;

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 24c8b1f7772d3..277ed39319732 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1441,6 +1441,12 @@ DynamicSection<ELFT>::computeContents() {
       addInt(DT_AARCH64_BTI_PLT, 0);
     if (config->zPacPlt)
       addInt(DT_AARCH64_PAC_PLT, 0);
+
+    if (config->androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE) {
+      addInt(DT_AARCH64_MEMTAG_MODE, config->androidMemtagMode == NT_MEMTAG_LEVEL_ASYNC);
+      addInt(DT_AARCH64_MEMTAG_HEAP, config->androidMemtagHeap);
+      addInt(DT_AARCH64_MEMTAG_STACK, config->androidMemtagStack);
+    }
   }
 
   addInSec(DT_SYMTAB, *part.dynSymTab);
@@ -3835,16 +3841,16 @@ void InStruct::reset() {
 
 constexpr char kMemtagAndroidNoteName[] = "Android";
 void MemtagAndroidNote::writeTo(uint8_t *buf) {
-  static_assert(sizeof(kMemtagAndroidNoteName) == 8,
-                "ABI check for Android 11 & 12.");
-  assert((config->androidMemtagStack || config->androidMemtagHeap) &&
-         "Should only be synthesizing a note if heap || stack is enabled.");
+  static_assert(
+      sizeof(kMemtagAndroidNoteName) == 8,
+      "Android 11 & 12 have an ABI that the note name is 8 bytes long. Keep it "
+      "that way for backwards compatibility.");
 
   write32(buf, sizeof(kMemtagAndroidNoteName));
   write32(buf + 4, sizeof(uint32_t));
   write32(buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
   memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName));
-  buf += 12 + sizeof(kMemtagAndroidNoteName);
+  buf += 12 + alignTo(sizeof(kMemtagAndroidNoteName), 4);
 
   uint32_t value = 0;
   value |= config->androidMemtagMode;
@@ -3859,7 +3865,7 @@ void MemtagAndroidNote::writeTo(uint8_t *buf) {
 
 size_t MemtagAndroidNote::getSize() const {
   return sizeof(llvm::ELF::Elf64_Nhdr) +
-         /*namesz=*/sizeof(kMemtagAndroidNoteName) +
+         /*namesz=*/alignTo(sizeof(kMemtagAndroidNoteName), 4) +
          /*descsz=*/sizeof(uint32_t);
 }
 

diff  --git a/lld/test/ELF/aarch64-memtag-android-abi.s b/lld/test/ELF/aarch64-memtag-android-abi.s
index 8d7c87b51e850..0e1d5deddbb2f 100644
--- a/lld/test/ELF/aarch64-memtag-android-abi.s
+++ b/lld/test/ELF/aarch64-memtag-android-abi.s
@@ -6,56 +6,60 @@
 ## can be run on these versions of Android.
 
 # RUN: llvm-mc --filetype=obj -triple=aarch64-none-linux-android %s -o %t.o
-# RUN: ld.lld --android-memtag-mode=async --android-memtag-heap %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,NOSTACK,ASYNC
+# RUN: ld.lld -shared --android-memtag-mode=async --android-memtag-heap %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,NOSTACK,ASYNC
 
-# RUN: ld.lld --android-memtag-mode=sync --android-memtag-heap %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,NOSTACK,SYNC
+# RUN: ld.lld -shared --android-memtag-mode=sync --android-memtag-heap %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,NOSTACK,SYNC
 
-# RUN: ld.lld --android-memtag-mode=async --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,NOHEAP,STACK,ASYNC
+# RUN: ld.lld -shared --android-memtag-mode=async --android-memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,NOHEAP,STACK,ASYNC
 
-# RUN: ld.lld --android-memtag-mode=sync --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,NOHEAP,STACK,SYNC
+# RUN: ld.lld -shared --android-memtag-mode=sync --android-memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,NOHEAP,STACK,SYNC
 
-# RUN: ld.lld --android-memtag-mode=async --android-memtag-heap \
+# RUN: ld.lld -shared --android-memtag-mode=async --android-memtag-heap \
 # RUN:    --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,STACK,ASYNC
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,STACK,ASYNC
 
-# RUN: ld.lld --android-memtag-mode=sync --android-memtag-heap \
+# RUN: ld.lld -shared --android-memtag-mode=sync --android-memtag-heap \
 # RUN:    --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,STACK,SYNC
+# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,STACK,SYNC
 
-# RUN: ld.lld --android-memtag-heap %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,NOSTACK,SYNC
+# RUN: ld.lld -shared --android-memtag-heap %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# RUN: ld.lld -shared --android-memtag-stack %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# RUN: ld.lld -shared --android-memtag-heap --android-memtag-stack %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# MISSING-MODE: warning: --android-memtag-mode is unspecified, leaving
+# MISSING-MODE: --android-memtag-{{(heap|stack)}} a no-op
 
-# RUN: ld.lld --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,NOHEAP,STACK,SYNC
+# CHECK: Memtag Dynamic Entries
+# SYNC:    AARCH64_MEMTAG_MODE: Synchronous (0)
+# ASYNC:   AARCH64_MEMTAG_MODE: Asynchronous (1)
+# HEAP:    AARCH64_MEMTAG_HEAP: Enabled (1)
+# NOHEAP:  AARCH64_MEMTAG_HEAP: Disabled (0)
+# STACK:   AARCH64_MEMTAG_STACK: Enabled (1)
+# NOSTACK: AARCH64_MEMTAG_STACK: Disabled (0)
 
-# RUN: ld.lld --android-memtag-heap --android-memtag-stack %t.o -o %t
-# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,HEAP,STACK,SYNC
-
-# NOTE: .note.android.memtag
-# NOTE-NEXT: Owner
-# NOTE-NEXT: Android 0x00000004 NT_ANDROID_TYPE_MEMTAG (Android memory tagging
-# NOTE-SAME: information)
-# ASYNC-NEXT: Tagging Mode: ASYNC
-# SYNC-NEXT: Tagging Mode: SYNC
-# HEAP-NEXT: Heap: Enabled
+# CHECK:       Memtag Android Note
+# ASYNC-NEXT:  Tagging Mode: ASYNC
+# SYNC-NEXT:   Tagging Mode: SYNC
+# HEAP-NEXT:   Heap: Enabled
 # NOHEAP-NEXT: Heap: Disabled
-## As of Android 12, stack MTE is unimplemented. However, we pre-emptively emit
-## a bit that signifies to the dynamic loader to map the primary and thread
-## stacks as PROT_MTE, in preparation for the bionic support.
 # STACK-NEXT:   Stack: Enabled
 # NOSTACK-NEXT: Stack: Disabled
 
-# RUN: not ld.lld --android-memtag-mode=asymm --android-memtag-heap 2>&1 | \
+# RUN: not ld.lld -shared --android-memtag-mode=asymm --android-memtag-heap 2>&1 | \
 # RUN:    FileCheck %s --check-prefix=BAD-MODE
-# BAD-MODE: unknown --android-memtag-mode value: "asymm", should be one of {async, sync, none}
+# BAD-MODE: error: unknown --android-memtag-mode value: "asymm", should be one of
+# BAD-MODE: {async, sync, none}
 
-# RUN: not ld.lld --android-memtag-mode=async 2>&1 | \
+# RUN: not ld.lld -shared --android-memtag-mode=async 2>&1 | \
 # RUN:    FileCheck %s --check-prefix=MISSING-STACK-OR-HEAP
-# MISSING-STACK-OR-HEAP: when using --android-memtag-mode, at least one of --android-memtag-heap or --android-memtag-stack is required
+# MISSING-STACK-OR-HEAP: error: when using --android-memtag-mode, at least one of
+# MISSING-STACK-OR-HEAP: --android-memtag-heap or --android-memtag-stack is required
 
 .globl _start
 _start:


        


More information about the llvm-commits mailing list