[compiler-rt] [asan] Implement address sanitizer on AIX: memory mapping (6/6) (PR #136874)

Jake Egan via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 11:42:23 PDT 2025


https://github.com/jakeegan updated https://github.com/llvm/llvm-project/pull/136874

>From c712440d503f2f7ff3e0ee7bc4add042cfee2c8b Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Sun, 20 Apr 2025 22:48:23 -0400
Subject: [PATCH 1/4] asan2

---
 compiler-rt/lib/asan/asan_allocator.h         |   4 +
 compiler-rt/lib/asan/asan_descriptions.cpp    |  21 +-
 compiler-rt/lib/asan/asan_mapping.h           |  10 +-
 compiler-rt/lib/asan/asan_mapping_aix64.h     | 184 ++++++++++++++++++
 compiler-rt/lib/asan/asan_poisoning.h         |   4 +-
 compiler-rt/lib/asan/asan_rtl.cpp             |  45 ++++-
 compiler-rt/lib/asan/asan_shadow_setup.cpp    |  22 ++-
 .../test/asan/TestCases/AIX/aix64_mapping.cpp |  19 ++
 .../test/asan/TestCases/AIX/lit.local.cfg.py  |  10 +
 9 files changed, 303 insertions(+), 16 deletions(-)
 create mode 100644 compiler-rt/lib/asan/asan_mapping_aix64.h
 create mode 100644 compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/AIX/lit.local.cfg.py

diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h
index db8dc3bebfc62..46cd7b118cd9a 100644
--- a/compiler-rt/lib/asan/asan_allocator.h
+++ b/compiler-rt/lib/asan/asan_allocator.h
@@ -197,7 +197,11 @@ const uptr kAllocatorSpace = ~(uptr)0;
 #    endif  // SANITIZER_APPLE
 
 #    if defined(__powerpc64__)
+#if SANITIZER_AIX
+const uptr kAllocatorSize  =  1ULL << 38;  // 256G.
+#else
 const uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
+#endif
 typedef DefaultSizeClassMap SizeClassMap;
 #    elif defined(__aarch64__) && SANITIZER_ANDROID
 // Android needs to support 39, 42 and 48 bit VMA.
diff --git a/compiler-rt/lib/asan/asan_descriptions.cpp b/compiler-rt/lib/asan/asan_descriptions.cpp
index c9f3e4d682d95..6488d51b89a14 100644
--- a/compiler-rt/lib/asan/asan_descriptions.cpp
+++ b/compiler-rt/lib/asan/asan_descriptions.cpp
@@ -211,10 +211,10 @@ bool GetStackAddressInformation(uptr addr, uptr access_size,
   descr->frame_pc = access.frame_pc;
   descr->frame_descr = access.frame_descr;
 
-#if SANITIZER_PPC64V1
-  // On PowerPC64 ELFv1, the address of a function actually points to a
-  // three-doubleword data structure with the first field containing
-  // the address of the function's code.
+#if SANITIZER_PPC64V1 || SANITIZER_AIX
+  // On PowerPC64 ELFv1 or AIX, the address of a function actually points to a
+  // three-doubleword (or three-word for 32-bit AIX) data structure with the
+  // first field containing the address of the function's code.
   descr->frame_pc = *reinterpret_cast<uptr *>(descr->frame_pc);
 #endif
   descr->frame_pc += 16;
@@ -444,6 +444,15 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size,
     data.kind = kAddressKindShadow;
     return;
   }
+
+  // Check global first. On AIX, some global data defined in shared libraries
+  // are put to the STACK region for unknown reasons. Check global first can
+  // workaround this issue.
+  if (GetGlobalAddressInformation(addr, access_size, &data.global)) {
+    data.kind = kAddressKindGlobal;
+    return;
+  }
+
   if (GetHeapAddressInformation(addr, access_size, &data.heap)) {
     data.kind = kAddressKindHeap;
     return;
@@ -461,10 +470,6 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size,
     return;
   }
 
-  if (GetGlobalAddressInformation(addr, access_size, &data.global)) {
-    data.kind = kAddressKindGlobal;
-    return;
-  }
   data.kind = kAddressKindWild;
   data.wild.addr = addr;
   data.wild.access_size = access_size;
diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index 91fe60db6329a..ecd196e2a021e 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -178,6 +178,8 @@
 #    define ASAN_SHADOW_OFFSET_CONST 0x30000000
 #  elif SANITIZER_IOS
 #    define ASAN_SHADOW_OFFSET_DYNAMIC
+#  elif SANITIZER_AIX
+#    define ASAN_SHADOW_OFFSET_CONST 0x40000000
 #  else
 #    define ASAN_SHADOW_OFFSET_CONST 0x20000000
 #  endif
@@ -193,7 +195,11 @@
 #  elif defined(__aarch64__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
 #  elif defined(__powerpc64__)
-#    define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
+#    if SANITIZER_AIX
+#      define ASAN_SHADOW_OFFSET_CONST 0x0a01000000000000
+#    else
+#      define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
+#    endif
 #  elif defined(__s390x__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
 #  elif SANITIZER_FREEBSD
@@ -272,6 +278,8 @@ extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;  // Initialized in __asan_init.
 
 #  if defined(__sparc__) && SANITIZER_WORDSIZE == 64
 #    include "asan_mapping_sparc64.h"
+#  elif SANITIZER_WORDSIZE == 64 && SANITIZER_AIX
+#    include "asan_mapping_aix64.h"
 #  else
 #    define MEM_TO_SHADOW(mem) \
       (((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
diff --git a/compiler-rt/lib/asan/asan_mapping_aix64.h b/compiler-rt/lib/asan/asan_mapping_aix64.h
new file mode 100644
index 0000000000000..38b97482ec1f4
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_mapping_aix64.h
@@ -0,0 +1,184 @@
+//===-- asan_mapping_aix64.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// AIX64-specific definitions for ASan memory mapping.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_MAPPING_AIX64_H
+#define ASAN_MAPPING_AIX64_H
+
+// https://www.ibm.com/docs/en/aix/7.3?topic=concepts-system-memory-allocation-using-malloc-subsystem
+//
+// For 64-bit on AIX,
+// - Data, heap, bss region is from 0x0000 0001 0000 0000 to
+//   0x07ff ffff ffff ffff (1ULL << 59).
+// - Shared library regions is from:
+//      0x0900 0000 0000 0000 to 0x09ff ffff ffff ffff
+//   or 0x0800 0000 0000 0000 to 0x08ff ffff ffff ffff ((1ULL << 52) * 2)
+// - mmap region is from 0x0a00 0000 0000 0000 to 0x0aff ffff ffff ffff
+//   (1ULL << 52).
+// - Initial stack region is from 0x0f00 0000 0000 0000 to
+//   0x0fff ffff ffff ffff (1ULL << 56).
+//
+// All above ranges are too big. And after verifying on AIX,(these datas are
+// from experiments on AIX72, AIX OS may change this layout in future)
+// - the biggest heap size is 1ULL << 47.
+// - the biggest global variable size is 1ULL << 29. (Which may be put in shared
+//   library data regions because global variables may be compiled to shared
+//   libraries.)
+//     the related address range for shared library data regions is:
+//          0x0900 1000 0000 0000 to 0x0900 1001 0000 0000
+//       or 0x0800 1000 0000 0000 to 0x0800 1001 0000 0000 (when above range is
+//          used by system libraries.)
+// - the biggest mmap size is 1ULL << 46.
+// - the biggest stack size is 1ULL << 32.
+//
+// We don't need so big heap and mmap, calling mmap for shadow memory for such
+// big heap and mmap is quite slow on AIX, so to balance runtime and examinable
+// memory size, we use 1ULL << 39(512GB) as size for each region except mmap
+// region. For mmap region, aix system mmap function may return a big range
+// address, we allocate 1ULL << 41(2TB).
+//
+// So the reasonable user space region size is:
+// - Data, heap, bss is from 0x0 to 0x0000 007f ffff ffff
+// - Shared library data is from:
+//        0x0900 1000 0000 0000 to 0x0900 107f ffff ffff
+//     or 0x0800 1000 0000 0000 to 0x0800 107f ffff ffff
+// - mmap is from 0x0a00 0000 0000 0000 to 0x0a00 01ff ffff ffff
+// - Stack is from 0x0fff ff80 0000 0000 to 0x0fff ffff ffff ffff
+//
+// AIX64 set ASAN_SHADOW_OFFSET_CONST at 0x0a01000000000000 because mmap
+// memory starts at 0x0a00000000000000 and shadow memory should be allocated
+// there. And we keep 0x0a00000000000000 to 0x0a01000000000000 For user mmap
+// usage.
+
+// NOTE: Users are not expected to use `mmap` specifying fixed address which is
+// inside the shadow memory ranges.
+
+// Default AIX64 mapping:
+// || `[0x0fffff8000000000, 0x0fffffffffffffff]` || HighMem    ||
+// || `[0x0a80fff000000000, 0x0a80ffffffffffff]` || HighShadow ||
+// || `[0x0a41000000000000, 0x0a41003fffffffff]` || MidShadow  ||
+// || `[0x0a21020000000000, 0x0a21020fffffffff]` || Mid2Shadow ||
+// || `[0x0a01020000000000, 0x0a01020fffffffff]` || Mid3Shadow ||
+// || `[0x0a01000000000000, 0x0a01000fffffffff]` || LowShadow  ||
+// || `[0x0a00000000000000, 0x0a0001ffffffffff]` || MidMem     ||
+// || `[0x0900100000000000, 0x0900107fffffffff]` || Mid2Mem    ||
+// || `[0x0800100000000000, 0x0800107fffffffff]` || Mid3Mem    ||
+// || `[0x0000000000000000, 0x0000007fffffffff]` || LowMem     ||
+
+#define VMA_BITS 58
+#define HIGH_BITS (64 - VMA_BITS)
+
+#define MEM_TO_SHADOW(mem)                                       \
+  ((((mem) << HIGH_BITS) >> (HIGH_BITS + (ASAN_SHADOW_SCALE))) + \
+   ASAN_SHADOW_OFFSET)
+
+#define SHADOW_TO_MEM(ptr) (__asan::ShadowToMemAIX64(ptr))
+
+#define kLowMemBeg 0ULL
+#define kLowMemEnd 0x0000007fffffffffULL
+
+#define kLowShadowBeg ASAN_SHADOW_OFFSET
+#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
+
+#define kHighMemBeg 0x0fffff8000000000ULL
+
+#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
+#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
+
+#define kMidMemBeg 0x0a00000000000000ULL
+#define kMidMemEnd 0x0a0001ffffffffffULL
+
+#define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
+#define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
+
+#define kMid2MemBeg 0x0900100000000000ULL
+#define kMid2MemEnd 0x0900107fffffffffULL
+
+#define kMid2ShadowBeg MEM_TO_SHADOW(kMid2MemBeg)
+#define kMid2ShadowEnd MEM_TO_SHADOW(kMid2MemEnd)
+
+#define kMid3MemBeg 0x0800100000000000ULL
+#define kMid3MemEnd 0x0800107fffffffffULL
+
+#define kMid3ShadowBeg MEM_TO_SHADOW(kMid3MemBeg)
+#define kMid3ShadowEnd MEM_TO_SHADOW(kMid3MemEnd)
+
+// AIX does not care about the gaps.
+#define kZeroBaseShadowStart 0
+#define kZeroBaseMaxShadowStart 0
+
+#define kShadowGapBeg 0
+#define kShadowGapEnd 0
+
+#define kShadowGap2Beg 0
+#define kShadowGap2End 0
+
+#define kShadowGap3Beg 0
+#define kShadowGap3End 0
+
+#define kShadowGap4Beg 0
+#define kShadowGap4End 0
+
+namespace __asan {
+
+static inline bool AddrIsInLowMem(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return a <= kLowMemEnd;
+}
+
+static inline bool AddrIsInLowShadow(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return a >= kLowShadowBeg && a <= kLowShadowEnd;
+}
+
+static inline bool AddrIsInMidMem(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return (a >= kMidMemBeg && a <= kMidMemEnd) ||
+         (a >= kMid2MemBeg && a <= kMid2MemEnd) ||
+         (a >= kMid3MemBeg && a <= kMid3MemEnd);
+}
+
+static inline bool AddrIsInMidShadow(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return (a >= kMidShadowBeg && a <= kMidShadowEnd) ||
+         (a >= kMid2ShadowBeg && a <= kMid2ShadowEnd) ||
+         (a >= kMid3ShadowBeg && a <= kMid3ShadowEnd);
+}
+
+static inline bool AddrIsInHighMem(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd;
+}
+
+static inline bool AddrIsInHighShadow(uptr a) {
+  PROFILE_ASAN_MAPPING();
+  return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd;
+}
+
+static inline bool AddrIsInShadowGap(uptr a) { return false; }
+
+static inline constexpr uptr ShadowToMemAIX64(uptr p) {
+  PROFILE_ASAN_MAPPING();
+  p -= ASAN_SHADOW_OFFSET;
+  p <<= ASAN_SHADOW_SCALE;
+  if (p >= 0x3ffff8000000000ULL) {
+    // HighMem
+    p |= (0x03ULL << VMA_BITS);
+  } else if (p >= 0x100000000000ULL) {
+    // MidShadow/Mid2Shadow/Mid2Shadow
+    p |= (0x02ULL << VMA_BITS);
+  }
+  return p;
+}
+
+}  // namespace __asan
+
+#endif  // ASAN_MAPPING_AIX64_H
diff --git a/compiler-rt/lib/asan/asan_poisoning.h b/compiler-rt/lib/asan/asan_poisoning.h
index b68af1086e17d..18b741e8bad3f 100644
--- a/compiler-rt/lib/asan/asan_poisoning.h
+++ b/compiler-rt/lib/asan/asan_poisoning.h
@@ -53,7 +53,9 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
   // for mapping shadow and zeroing out pages doesn't "just work", so we should
   // probably provide higher-level interface for these operations.
   // For now, just memset on Windows.
-  if (value || SANITIZER_WINDOWS == 1 ||
+  // On AIX, calling ReserveShadowMemoryRange() is not allowed to remap the
+  // memory, so just memset the memory.
+  if (value || SANITIZER_WINDOWS == 1 || SANITIZER_AIX == 1 ||
       shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
     REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
   } else {
diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp
index b3f6677a99cfb..c857a5a0bae12 100644
--- a/compiler-rt/lib/asan/asan_rtl.cpp
+++ b/compiler-rt/lib/asan/asan_rtl.cpp
@@ -55,13 +55,24 @@ static void AsanDie() {
   WaitForDebugger(flags()->sleep_before_dying, "before dying");
 
   if (flags()->unmap_shadow_on_exit) {
+#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
+    UnmapOrDie((void *)kHighShadowBeg, kHighShadowEnd - kHighShadowBeg);
+    UnmapOrDie((void *)kMidShadowBeg, kMidShadowEnd - kMidShadowBeg);
+
+    UnmapOrDie((void *)kMid2ShadowBeg, kMid2ShadowEnd - kMid2ShadowBeg);
+    UnmapOrDie((void *)kMid3ShadowBeg, kMid3ShadowEnd - kMid3ShadowBeg);
+
+    UnmapOrDie((void *)kLowShadowBeg, kLowShadowEnd - kLowShadowBeg);
+#else
     if (kMidMemBeg) {
-      UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
-      UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
+      UnmapOrDie((void *)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
+      UnmapOrDie((void *)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
     } else {
       if (kHighShadowEnd)
-        UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
+        UnmapOrDie((void *)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
+
     }
+#endif
   }
 }
 
@@ -85,7 +96,11 @@ bool AsanInited() {
 bool replace_intrin_cached;
 
 #if !ASAN_FIXED_MAPPING
+#if !(SANITIZER_AIX && __powerpc64__)
 uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
+#else
+uptr kHighMemEnd;
+#endif
 #endif
 
 // -------------------------- Misc ---------------- {{{1
@@ -341,17 +356,29 @@ void PrintAddressSpaceLayout() {
            (void*)kHighShadowBeg, (void*)kHighShadowEnd);
   }
   if (kMidMemBeg) {
+ // AIX shadowgap is always set to 0 for 64-bit.
+#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64
     Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
            (void*)kShadowGap3Beg, (void*)kShadowGap3End);
+#endif
     Printf("|| `[%p, %p]` || MidMem     ||\n",
            (void*)kMidMemBeg, (void*)kMidMemEnd);
+#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64
     Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
            (void*)kShadowGap2Beg, (void*)kShadowGap2End);
+#endif
     Printf("|| `[%p, %p]` || MidShadow  ||\n",
            (void*)kMidShadowBeg, (void*)kMidShadowEnd);
   }
+#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
+  Printf("|| `[%p, %p]` || Mid2Shadow  ||\n",
+         (void*)kMid2ShadowBeg, (void*)kMid2ShadowEnd);
+  Printf("|| `[%p, %p]` || Mid3Shadow  ||\n",
+         (void*)kMid3ShadowBeg, (void*)kMid3ShadowEnd);
+#else
   Printf("|| `[%p, %p]` || ShadowGap  ||\n",
          (void*)kShadowGapBeg, (void*)kShadowGapEnd);
+#endif
   if (kLowShadowBeg) {
     Printf("|| `[%p, %p]` || LowShadow  ||\n",
            (void*)kLowShadowBeg, (void*)kLowShadowEnd);
@@ -371,6 +398,15 @@ void PrintAddressSpaceLayout() {
            (void*)MEM_TO_SHADOW(kMidShadowBeg),
            (void*)MEM_TO_SHADOW(kMidShadowEnd));
   }
+// On AIX, for 64-bit, there are totally 3 mid memory regions.
+#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
+    Printf(" %p %p",
+           (void*)MEM_TO_SHADOW(kMid2ShadowBeg),
+           (void*)MEM_TO_SHADOW(kMid2ShadowEnd));
+    Printf(" %p %p",
+           (void*)MEM_TO_SHADOW(kMid3ShadowBeg),
+           (void*)MEM_TO_SHADOW(kMid3ShadowEnd));
+#endif
   Printf("\n");
   Printf("redzone=%zu\n", (uptr)flags()->redzone);
   Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone);
@@ -386,7 +422,10 @@ void PrintAddressSpaceLayout() {
   CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7);
   if (kMidMemBeg)
     CHECK(kMidShadowBeg > kLowShadowEnd &&
+// On AIX 64-bit, we have a highly customized memory layout.
+#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64
           kMidMemBeg > kMidShadowEnd &&
+#endif
           kHighShadowBeg > kMidMemEnd);
 }
 
diff --git a/compiler-rt/lib/asan/asan_shadow_setup.cpp b/compiler-rt/lib/asan/asan_shadow_setup.cpp
index 5b3591da067bd..9e3103c31bd24 100644
--- a/compiler-rt/lib/asan/asan_shadow_setup.cpp
+++ b/compiler-rt/lib/asan/asan_shadow_setup.cpp
@@ -91,9 +91,25 @@ void InitializeShadowMemory() {
       ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
     // mmap the high shadow.
     ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
-    // protect the gap.
-    ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
-    CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
+#  if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
+    // Fox 64-bit AIX, there is a very customized memory layout, we don't have
+    // the ability to protect all the shadow gaps. But we need to reserve
+    // shadow memory for middle memory.
+    if (kMidShadowBeg)
+      ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
+
+    if (kMid2ShadowBeg)
+      ReserveShadowMemoryRange(kMid2ShadowBeg, kMid2ShadowEnd, "mid2 shadow");
+
+    if (kMid3ShadowBeg)
+      ReserveShadowMemoryRange(kMid3ShadowBeg, kMid3ShadowEnd, "mid3 shadow");
+#  else
+    if (kShadowGapBeg) {
+      // protect the gap.
+      ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+      CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
+    }
+#  endif
   } else if (kMidMemBeg &&
              MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
              MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
diff --git a/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp b/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
new file mode 100644
index 0000000000000..ee37fa7376fdf
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_asan -O0 %s -o %t
+// RUN: %env_asan_opts=verbosity=2 %run %t 2>&1 | FileCheck %s
+// REQUIRES: powerpc64-target-arch
+
+#include <stdio.h>
+
+int main() {
+// CHECK: || `[0xfffff8000000000, 0xfffffffffffffff]` || HighMem    ||
+// CHECK: || `[0xa80fff000000000, 0xa80ffffffffffff]` || HighShadow ||
+// CHECK: || `[0xa00000000000000, 0xa0001ffffffffff]` || MidMem     ||
+// CHECK: || `[0xa41000000000000, 0xa41003fffffffff]` || MidShadow  ||
+// CHECK: || `[0xa21020000000000, 0xa21020fffffffff]` || Mid2Shadow  ||
+// CHECK: || `[0xa01020000000000, 0xa01020fffffffff]` || Mid3Shadow  ||
+// CHECK: || `[0xa01000000000000, 0xa01000fffffffff]` || LowShadow  ||
+// CHECK: || `[0x000000000000, 0x007fffffffff]` || LowMem     ||
+
+  return 0;
+}
+
diff --git a/compiler-rt/test/asan/TestCases/AIX/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/AIX/lit.local.cfg.py
new file mode 100644
index 0000000000000..55462708e3b6c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/AIX/lit.local.cfg.py
@@ -0,0 +1,10 @@
+def getRoot(config):
+    if not config.parent:
+        return config
+    return getRoot(config.parent)
+
+
+root = getRoot(config)
+
+if root.host_os not in ["AIX"]:
+    config.unsupported = True

>From 49f1189d8a445ab929005bfbcef6d96783d189fe Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Wed, 23 Apr 2025 11:18:42 -0400
Subject: [PATCH 2/4] Fix formatting

---
 compiler-rt/lib/asan/asan_allocator.h         |  8 +++---
 compiler-rt/lib/asan/asan_rtl.cpp             | 27 +++++++++----------
 .../test/asan/TestCases/AIX/aix64_mapping.cpp | 17 ++++++------
 3 files changed, 24 insertions(+), 28 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h
index 46cd7b118cd9a..6fb533423580d 100644
--- a/compiler-rt/lib/asan/asan_allocator.h
+++ b/compiler-rt/lib/asan/asan_allocator.h
@@ -197,11 +197,11 @@ const uptr kAllocatorSpace = ~(uptr)0;
 #    endif  // SANITIZER_APPLE
 
 #    if defined(__powerpc64__)
-#if SANITIZER_AIX
-const uptr kAllocatorSize  =  1ULL << 38;  // 256G.
-#else
+#      if SANITIZER_AIX
+const uptr kAllocatorSize = 1ULL << 38;  // 256G.
+#      else
 const uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
-#endif
+#      endif
 typedef DefaultSizeClassMap SizeClassMap;
 #    elif defined(__aarch64__) && SANITIZER_ANDROID
 // Android needs to support 39, 42 and 48 bit VMA.
diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp
index c857a5a0bae12..bcef3269fd03c 100644
--- a/compiler-rt/lib/asan/asan_rtl.cpp
+++ b/compiler-rt/lib/asan/asan_rtl.cpp
@@ -70,7 +70,6 @@ static void AsanDie() {
     } else {
       if (kHighShadowEnd)
         UnmapOrDie((void *)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
-
     }
 #endif
   }
@@ -96,11 +95,11 @@ bool AsanInited() {
 bool replace_intrin_cached;
 
 #if !ASAN_FIXED_MAPPING
-#if !(SANITIZER_AIX && __powerpc64__)
+#  if !(SANITIZER_AIX && __powerpc64__)
 uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
-#else
+#  else
 uptr kHighMemEnd;
-#endif
+#  endif
 #endif
 
 // -------------------------- Misc ---------------- {{{1
@@ -356,7 +355,7 @@ void PrintAddressSpaceLayout() {
            (void*)kHighShadowBeg, (void*)kHighShadowEnd);
   }
   if (kMidMemBeg) {
- // AIX shadowgap is always set to 0 for 64-bit.
+    // AIX shadowgap is always set to 0 for 64-bit.
 #if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64
     Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
            (void*)kShadowGap3Beg, (void*)kShadowGap3End);
@@ -371,10 +370,10 @@ void PrintAddressSpaceLayout() {
            (void*)kMidShadowBeg, (void*)kMidShadowEnd);
   }
 #if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
-  Printf("|| `[%p, %p]` || Mid2Shadow  ||\n",
-         (void*)kMid2ShadowBeg, (void*)kMid2ShadowEnd);
-  Printf("|| `[%p, %p]` || Mid3Shadow  ||\n",
-         (void*)kMid3ShadowBeg, (void*)kMid3ShadowEnd);
+  Printf("|| `[%p, %p]` || Mid2Shadow  ||\n", (void *)kMid2ShadowBeg,
+         (void *)kMid2ShadowEnd);
+  Printf("|| `[%p, %p]` || Mid3Shadow  ||\n", (void *)kMid3ShadowBeg,
+         (void *)kMid3ShadowEnd);
 #else
   Printf("|| `[%p, %p]` || ShadowGap  ||\n",
          (void*)kShadowGapBeg, (void*)kShadowGapEnd);
@@ -400,12 +399,10 @@ void PrintAddressSpaceLayout() {
   }
 // On AIX, for 64-bit, there are totally 3 mid memory regions.
 #if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64
-    Printf(" %p %p",
-           (void*)MEM_TO_SHADOW(kMid2ShadowBeg),
-           (void*)MEM_TO_SHADOW(kMid2ShadowEnd));
-    Printf(" %p %p",
-           (void*)MEM_TO_SHADOW(kMid3ShadowBeg),
-           (void*)MEM_TO_SHADOW(kMid3ShadowEnd));
+  Printf(" %p %p", (void *)MEM_TO_SHADOW(kMid2ShadowBeg),
+         (void *)MEM_TO_SHADOW(kMid2ShadowEnd));
+  Printf(" %p %p", (void *)MEM_TO_SHADOW(kMid3ShadowBeg),
+         (void *)MEM_TO_SHADOW(kMid3ShadowEnd));
 #endif
   Printf("\n");
   Printf("redzone=%zu\n", (uptr)flags()->redzone);
diff --git a/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp b/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
index ee37fa7376fdf..932c47c30bf50 100644
--- a/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/aix64_mapping.cpp
@@ -5,15 +5,14 @@
 #include <stdio.h>
 
 int main() {
-// CHECK: || `[0xfffff8000000000, 0xfffffffffffffff]` || HighMem    ||
-// CHECK: || `[0xa80fff000000000, 0xa80ffffffffffff]` || HighShadow ||
-// CHECK: || `[0xa00000000000000, 0xa0001ffffffffff]` || MidMem     ||
-// CHECK: || `[0xa41000000000000, 0xa41003fffffffff]` || MidShadow  ||
-// CHECK: || `[0xa21020000000000, 0xa21020fffffffff]` || Mid2Shadow  ||
-// CHECK: || `[0xa01020000000000, 0xa01020fffffffff]` || Mid3Shadow  ||
-// CHECK: || `[0xa01000000000000, 0xa01000fffffffff]` || LowShadow  ||
-// CHECK: || `[0x000000000000, 0x007fffffffff]` || LowMem     ||
+  // CHECK: || `[0xfffff8000000000, 0xfffffffffffffff]` || HighMem    ||
+  // CHECK: || `[0xa80fff000000000, 0xa80ffffffffffff]` || HighShadow ||
+  // CHECK: || `[0xa00000000000000, 0xa0001ffffffffff]` || MidMem     ||
+  // CHECK: || `[0xa41000000000000, 0xa41003fffffffff]` || MidShadow  ||
+  // CHECK: || `[0xa21020000000000, 0xa21020fffffffff]` || Mid2Shadow  ||
+  // CHECK: || `[0xa01020000000000, 0xa01020fffffffff]` || Mid3Shadow  ||
+  // CHECK: || `[0xa01000000000000, 0xa01000fffffffff]` || LowShadow  ||
+  // CHECK: || `[0x000000000000, 0x007fffffffff]` || LowMem     ||
 
   return 0;
 }
-

>From b700788f779cf211adf00f748848531e16e2e6fc Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Sun, 27 Apr 2025 21:15:43 -0400
Subject: [PATCH 3/4] Fix undeclared identifier

---
 compiler-rt/lib/asan/asan_poisoning.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_poisoning.h b/compiler-rt/lib/asan/asan_poisoning.h
index 18b741e8bad3f..2324fdf78dca4 100644
--- a/compiler-rt/lib/asan/asan_poisoning.h
+++ b/compiler-rt/lib/asan/asan_poisoning.h
@@ -55,8 +55,10 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
   // For now, just memset on Windows.
   // On AIX, calling ReserveShadowMemoryRange() is not allowed to remap the
   // memory, so just memset the memory.
-  if (value || SANITIZER_WINDOWS == 1 || SANITIZER_AIX == 1 ||
-      shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+#if SANITIZER_WINDOWS || SANITIZER_AIX
+    REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+#else
+  if (value || shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
     REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
   } else {
     uptr page_size = GetPageSizeCached();
@@ -75,6 +77,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
       ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
     }
   }
+#endif
 #endif // SANITIZER_FUCHSIA
 }
 

>From 80e591402373a052c0d5851688d7ec42f395be6b Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 29 Apr 2025 14:42:10 -0400
Subject: [PATCH 4/4] Fix formatting

---
 compiler-rt/lib/asan/asan_poisoning.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_poisoning.h b/compiler-rt/lib/asan/asan_poisoning.h
index 2324fdf78dca4..f45a60077af09 100644
--- a/compiler-rt/lib/asan/asan_poisoning.h
+++ b/compiler-rt/lib/asan/asan_poisoning.h
@@ -55,10 +55,11 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
   // For now, just memset on Windows.
   // On AIX, calling ReserveShadowMemoryRange() is not allowed to remap the
   // memory, so just memset the memory.
-#if SANITIZER_WINDOWS || SANITIZER_AIX
-    REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
-#else
-  if (value || shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+#  if SANITIZER_WINDOWS || SANITIZER_AIX
+  REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+#  else
+  if (value ||
+      shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
     REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
   } else {
     uptr page_size = GetPageSizeCached();
@@ -77,7 +78,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
       ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
     }
   }
-#endif
+#  endif
 #endif // SANITIZER_FUCHSIA
 }
 



More information about the llvm-commits mailing list