Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler-rt/lib/asan/asan_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 13 additions & 8 deletions compiler-rt/lib/asan/asan_descriptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion compiler-rt/lib/asan/asan_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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))
Expand Down
184 changes: 184 additions & 0 deletions compiler-rt/lib/asan/asan_mapping_aix64.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 7 additions & 1 deletion compiler-rt/lib/asan/asan_poisoning.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ 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 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 {
Expand All @@ -73,6 +78,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
}
}
# endif
#endif // SANITIZER_FUCHSIA
}

Expand Down
42 changes: 39 additions & 3 deletions compiler-rt/lib/asan/asan_rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,23 @@ 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
}
}

Expand All @@ -85,7 +95,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
Expand Down Expand Up @@ -341,17 +355,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);
Expand All @@ -371,6 +397,13 @@ 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);
Expand All @@ -386,7 +419,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);
}

Expand Down
Loading
Loading