Skip to content

[compiler-rt] Implement address sanitizer on AIX #130028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions compiler-rt/cmake/Modules/AddCompilerRT.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,23 @@ macro(add_compiler_rt_script name)
DESTINATION ${COMPILER_RT_INSTALL_BINARY_DIR})
endmacro(add_compiler_rt_script src name)

macro(add_compiler_rt_cfg target_name file_name component)
set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}")
get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir)
set(dst_file "${output_dir}/${file_name}")
add_custom_command(OUTPUT ${dst_file}
DEPENDS ${src_file}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file}
COMMENT "Copying ${file_name}...")
add_custom_target(${target_name} DEPENDS ${dst_file})
install(FILES ${file_name}
DESTINATION ${COMPILER_RT_INSTALL_LIBRARY_DIR}
COMPONENT ${component})
add_dependencies(${component} ${target_name})

set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc")
endmacro()

# Builds custom version of libc++ and installs it in <prefix>.
# Can be used to build sanitized versions of libc++ for running unit tests.
# add_custom_libcxx(<name> <prefix>
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ if(WIN32)
set(ARM32 ${ARM32} armv7)
endif()

set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64}
set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC32} ${PPC64} ${RISCV64}
${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}
${HEXAGON} ${LOONGARCH64})
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${MIPS32} ${MIPS64} ${PPC32} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${LOONGARCH64})
set(ALL_ASAN_ABI_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM64_32})
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64})
Expand Down
6 changes: 5 additions & 1 deletion compiler-rt/cmake/base-config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ include(CompilerRTDarwinUtils)
check_include_file(unwind.h HAVE_UNWIND_H)

# Used by sanitizer_common and tests.
check_include_file(rpc/xdr.h HAVE_RPC_XDR_H)
if (${CMAKE_SYSTEM_NAME} MATCHES AIX)
check_include_file(tirpc/rpc/xdr.h HAVE_RPC_XDR_H)
else()
check_include_file(rpc/xdr.h HAVE_RPC_XDR_H)
endif()
if (NOT HAVE_RPC_XDR_H)
set(HAVE_RPC_XDR_H 0)
endif()
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/cmake/config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ check_cxx_compiler_flag("-Werror -Wgnu" COMPILER_RT_HAS_WGNU_FLAG
check_cxx_compiler_flag("-Werror -Wgnu-anonymous-struct" COMPILER_RT_HAS_WGNU_ANONYMOUS_STRUCT_FLAG)
check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG)
check_cxx_compiler_flag("-Werror -Wunused-parameter" COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG)
check_cxx_compiler_flag("-Werror -Watomic-alignment" COMPILER_RT_HAS_WATOMIC_ALIGNMENT_FLAG)
check_cxx_compiler_flag("-Werror -Wcovered-switch-default" COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG)
check_cxx_compiler_flag("-Werror -Wsuggest-override" COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG)
check_cxx_compiler_flag("-Werror -Wthread-safety" COMPILER_RT_HAS_WTHREAD_SAFETY_FLAG)
Expand Down Expand Up @@ -760,7 +761,7 @@ set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING
list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}")

if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
(OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS" OR
(OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS|AIX" OR
(OS_NAME MATCHES "Windows" AND NOT CYGWIN AND
(NOT MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"))))
set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE)
Expand Down
12 changes: 12 additions & 0 deletions compiler-rt/lib/asan/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Build for the AddressSanitizer runtime support library.

set(ASAN_SOURCES
asan_aix.cpp
asan_allocator.cpp
asan_activation.cpp
asan_debugging.cpp
Expand Down Expand Up @@ -281,6 +282,9 @@ else()
PARENT_TARGET asan)
endif()

# On AIX, we only need the static libraries.
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX")

foreach(arch ${ASAN_SUPPORTED_ARCH})
if (COMPILER_RT_HAS_VERSION_SCRIPT)
if(WIN32)
Expand Down Expand Up @@ -382,10 +386,18 @@ else()
endif()
endif()
endforeach()
endif()
endif()

add_compiler_rt_resource_file(asan_ignorelist asan_ignorelist.txt asan)

# On AIX, we need to put asan.link_with_main_exec.txt and asan_cxx.link_with_main_exec.txt
# to the build and install dir.
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX")
add_compiler_rt_cfg(asan_symbols asan.link_with_main_exec.txt asan)
add_compiler_rt_cfg(asan_cxx_symbols asan_cxx.link_with_main_exec.txt asan)
endif()

add_subdirectory(scripts)

if(COMPILER_RT_INCLUDE_TESTS)
Expand Down
115 changes: 115 additions & 0 deletions compiler-rt/lib/asan/asan.link_with_main_exec.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#! .
__asan_report_load_n
__asan_loadN
__asan_report_load1
__asan_load1
__asan_report_load2
__asan_load2
__asan_report_load4
__asan_load4
__asan_report_load8
__asan_load8
__asan_report_load16
__asan_load16
__asan_report_store_n
__asan_storeN
__asan_report_store1
__asan_store1
__asan_report_store2
__asan_store2
__asan_report_store4
__asan_store4
__asan_report_store8
__asan_store8
__asan_report_store16
__asan_store16
__asan_report_exp_load_n
__asan_exp_loadN
__asan_report_exp_load1
__asan_exp_load1
__asan_report_exp_load2
__asan_exp_load2
__asan_report_exp_load4
__asan_exp_load4
__asan_report_exp_load8
__asan_exp_load8
__asan_report_exp_load16
__asan_exp_load16
__asan_report_exp_store_n
__asan_exp_storeN
__asan_report_exp_store1
__asan_exp_store1
__asan_report_exp_store2
__asan_exp_store2
__asan_report_exp_store4
__asan_exp_store4
__asan_report_exp_store8
__asan_exp_store8
__asan_report_exp_store16
__asan_exp_store16
__asan_memmove
__asan_memcpy
__asan_memset
__asan_handle_no_return
__sanitizer_ptr_cmp
__sanitizer_ptr_sub
__asan_before_dynamic_init
__asan_after_dynamic_init
__asan_register_globals
__asan_unregister_globals
__asan_register_image_globals
__asan_unregister_image_globals
__asan_register_elf_globals
__asan_unregister_elf_globals
__asan_init
__asan_version_mismatch_check_v8
__asan_stack_malloc_0
__asan_stack_malloc_1
__asan_stack_malloc_2
__asan_stack_malloc_3
__asan_stack_malloc_4
__asan_stack_malloc_5
__asan_stack_malloc_6
__asan_stack_malloc_7
__asan_stack_malloc_8
__asan_stack_malloc_9
__asan_stack_malloc_10
__asan_stack_malloc_always_0
__asan_stack_malloc_always_1
__asan_stack_malloc_always_2
__asan_stack_malloc_always_3
__asan_stack_malloc_always_4
__asan_stack_malloc_always_5
__asan_stack_malloc_always_6
__asan_stack_malloc_always_7
__asan_stack_malloc_always_8
__asan_stack_malloc_always_9
__asan_stack_malloc_always_10
__asan_stack_free_0
__asan_stack_free_1
__asan_stack_free_2
__asan_stack_free_3
__asan_stack_free_4
__asan_stack_free_5
__asan_stack_free_6
__asan_stack_free_7
__asan_stack_free_8
__asan_stack_free_9
__asan_stack_free_10
__asan_set_shadow_00
__asan_set_shadow_01
__asan_set_shadow_02
__asan_set_shadow_03
__asan_set_shadow_04
__asan_set_shadow_05
__asan_set_shadow_06
__asan_set_shadow_07
__asan_set_shadow_f1
__asan_set_shadow_f2
__asan_set_shadow_f3
__asan_set_shadow_f5
__asan_set_shadow_f8
__asan_poison_stack_memory
__asan_unpoison_stack_memory
__asan_option_detect_stack_use_after_return
__asan_shadow_memory_dynamic_address
44 changes: 44 additions & 0 deletions compiler-rt/lib/asan/asan_aix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//===-- asan_aix.cpp ------------------------------------------------------===//
//
// 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.
//
// AIX-specific details.
//===----------------------------------------------------------------------===//

#include "sanitizer_common/sanitizer_platform.h"

#if SANITIZER_AIX
# include "asan_mapping.h"
# include "sanitizer_common/sanitizer_internal_defs.h"

namespace __asan {

void AsanCheckIncompatibleRT() {}

void AsanCheckDynamicRTPrereqs() {}

void InitializePlatformExceptionHandlers() {}

void *AsanDoesNotSupportStaticLinkage() { return 0; }

void InitializePlatformInterceptors() {}
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {}

uptr FindDynamicShadowStart() {
UNREACHABLE("AIX does not use dynamic shadow offset!");
return 0;
}

void FlushUnneededASanShadowMemory(uptr p, uptr size) {
ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
}

} // namespace __asan

#endif // SANITIZER_AIX
13 changes: 10 additions & 3 deletions compiler-rt/lib/asan/asan_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,16 @@ struct Allocator {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
ReportInvalidFree(old_ptr, chunk_state, stack);
CHECK_NE(REAL(memcpy), nullptr);
uptr memcpy_size = Min(new_size, m->UsedSize());
// If realloc() races with free(), we may start copying freed memory.
// However, we will report racy double-free later anyway.
#if !SANITIZER_AIX
CHECK_NE(REAL(memcpy), nullptr);
REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
#else
// AIX does not intercept memcpy, we have to use internal_memcpy here.
internal_memcpy(new_ptr, old_ptr, memcpy_size);
#endif
Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC);
}
return new_ptr;
Expand All @@ -797,8 +802,10 @@ struct Allocator {
void ReportInvalidFree(void *ptr, u8 chunk_state, BufferedStackTrace *stack) {
if (chunk_state == CHUNK_QUARANTINE)
ReportDoubleFree((uptr)ptr, stack);
else
ReportFreeNotMalloced((uptr)ptr, stack);
else {
if (common_flags()->enable_unmalloced_free_check)
ReportFreeNotMalloced((uptr)ptr, stack);
}
}

void CommitBack(AsanThreadLocalMallocStorage *ms, BufferedStackTrace *stack) {
Expand Down
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: 21 additions & 0 deletions compiler-rt/lib/asan/asan_cxx.link_with_main_exec.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#! .
_ZdaPv
_ZdaPvRKSt9nothrow_t
_ZdaPvSt11align_val_t
_ZdaPvSt11align_val_tRKSt9nothrow_t
_ZdaPvm
_ZdaPvmSt11align_val_t
_ZdlPv
_ZdlPvRKSt9nothrow_t
_ZdlPvSt11align_val_t
_ZdlPvSt11align_val_tRKSt9nothrow_t
_ZdlPvm
_ZdlPvmSt11align_val_t
_Znam
_ZnamRKSt9nothrow_t
_ZnamSt11align_val_t
_ZnamSt11align_val_tRKSt9nothrow_t
_Znwm
_ZnwmRKSt9nothrow_t
_ZnwmSt11align_val_t
_ZnwmSt11align_val_tRKSt9nothrow_t
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
Loading