Skip to content

Commit a6a50e7

Browse files
committed
[llvm] Implement address sanitizer on AIX (2/3)
1 parent 8e6fa15 commit a6a50e7

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff900000000000;
119119
static const uint64_t kPS_ShadowOffset64 = 1ULL << 40;
120120
static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
121121
static const uint64_t kEmscriptenShadowOffset = 0;
122+
static const uint64_t kAIXShadowOffset32 = 0x40000000;
123+
// 64-BIT AIX is not yet ready.
124+
static const uint64_t kAIXShadowOffset64 = 0x0a01000000000000ULL;
122125

123126
// The shadow memory space is dynamically allocated.
124127
static const uint64_t kWindowsShadowOffset64 = kDynamicShadowSentinel;
@@ -128,6 +131,8 @@ static const size_t kMaxStackMallocSize = 1 << 16; // 64K
128131
static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
129132
static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E;
130133

134+
static const uint32_t kAIXHighBits = 6;
135+
131136
const char kAsanModuleCtorName[] = "asan.module_ctor";
132137
const char kAsanModuleDtorName[] = "asan.module_dtor";
133138
static const uint64_t kAsanCtorAndDtorPriority = 1;
@@ -463,11 +468,14 @@ namespace {
463468

464469
/// This struct defines the shadow mapping using the rule:
465470
/// shadow = (mem >> Scale) ADD-or-OR Offset.
471+
/// However, on 64-bit AIX, we use HighBits to reduce the mapped address space:
472+
/// shadow = ((mem << HighBits) >> (HighBits + Scale)) + Offset
466473
/// If InGlobal is true, then
467474
/// extern char __asan_shadow[];
468475
/// shadow = (mem >> Scale) + &__asan_shadow
469476
struct ShadowMapping {
470477
int Scale;
478+
int HighBits;
471479
uint64_t Offset;
472480
bool OrShadowOffset;
473481
bool InGlobal;
@@ -487,6 +495,7 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
487495
bool IsLinux = TargetTriple.isOSLinux();
488496
bool IsPPC64 = TargetTriple.getArch() == Triple::ppc64 ||
489497
TargetTriple.getArch() == Triple::ppc64le;
498+
bool IsAIX = TargetTriple.isOSAIX();
490499
bool IsSystemZ = TargetTriple.getArch() == Triple::systemz;
491500
bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
492501
bool IsMIPSN32ABI = TargetTriple.isABIN32();
@@ -526,14 +535,18 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
526535
Mapping.Offset = kWindowsShadowOffset32;
527536
else if (IsEmscripten)
528537
Mapping.Offset = kEmscriptenShadowOffset;
538+
else if (IsAIX)
539+
Mapping.Offset = kAIXShadowOffset32;
529540
else
530541
Mapping.Offset = kDefaultShadowOffset32;
531542
} else { // LongSize == 64
532543
// Fuchsia is always PIE, which means that the beginning of the address
533544
// space is always available.
534545
if (IsFuchsia)
535546
Mapping.Offset = 0;
536-
else if (IsPPC64)
547+
else if (IsAIX)
548+
Mapping.Offset = kAIXShadowOffset64;
549+
else if (IsPPC64 && !IsAIX)
537550
Mapping.Offset = kPPC64_ShadowOffset64;
538551
else if (IsSystemZ)
539552
Mapping.Offset = kSystemZ_ShadowOffset64;
@@ -592,13 +605,16 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
592605
// SystemZ, we could OR the constant in a single instruction, but it's more
593606
// efficient to load it once and use indexed addressing.
594607
Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS &&
595-
!IsRISCV64 && !IsLoongArch64 &&
608+
!IsRISCV64 && !IsLoongArch64 && !IsAIX &&
596609
!(Mapping.Offset & (Mapping.Offset - 1)) &&
597610
Mapping.Offset != kDynamicShadowSentinel;
598611
bool IsAndroidWithIfuncSupport =
599612
IsAndroid && !TargetTriple.isAndroidVersionLT(21);
600613
Mapping.InGlobal = ClWithIfunc && IsAndroidWithIfuncSupport && IsArmOrThumb;
601614

615+
if (IsAIX && LongSize == 64)
616+
Mapping.HighBits = kAIXHighBits;
617+
602618
return Mapping;
603619
}
604620

@@ -1326,7 +1342,11 @@ static bool isUnsupportedAMDGPUAddrspace(Value *Addr) {
13261342

13271343
Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
13281344
// Shadow >> scale
1329-
Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
1345+
if (TargetTriple.isOSAIX() && TargetTriple.getArch() == Triple::ppc64)
1346+
Shadow = IRB.CreateLShr(IRB.CreateShl(Shadow, Mapping.HighBits),
1347+
Mapping.Scale + Mapping.HighBits);
1348+
else
1349+
Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
13301350
if (Mapping.Offset == 0) return Shadow;
13311351
// (Shadow >> scale) | offset
13321352
Value *ShadowBase;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; Test shadow memory mapping on AIX
2+
3+
; RUN: opt -passes=asan -mtriple=powerpc64-ibm-aix -S < %s | FileCheck %s -check-prefix=CHECK-64
4+
; RUN: opt -passes=asan -mtriple=powerpc-ibm-aix -S < %s | FileCheck %s -check-prefix=CHECK-32
5+
6+
; CHECK: @test
7+
; On 64-bit AIX, we expect a left shift of 6 (HIGH_BITS) followed by a right shift of 9 (HIGH_BITS
8+
; + ASAN_SHADOW_SCALE) and an offset of 0x0a01000000000000.
9+
; CHECK-64: shl {{.*}} 6
10+
; CHECK-64-NEXT: lshr {{.*}} 9
11+
; CHECK-64-NEXT: add {{.*}} 720857415355990016
12+
; On 32-bit AIX, we expect just a right shift of 3 and an offset of 0x40000000.
13+
; CHECK-32: lshr {{.*}} 3
14+
; CHECK-32-NEXT: add {{.*}} 1073741824
15+
; CHECK: ret
16+
17+
define i32 @test(i32* %a) sanitize_address {
18+
entry:
19+
%tmp1 = load i32, i32* %a, align 4
20+
ret i32 %tmp1
21+
}

0 commit comments

Comments
 (0)