[compiler-rt] [sanitizer_common] Add AIX specific functionality (PR #131868)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 24 04:59:24 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Jake Egan (jakeegan)
<details>
<summary>Changes</summary>
Implements AIX specific process memory mapping, stack unwinding, and symbolization. Some AIX differences that influenced these changes:
- `procmap` returns incomplete paths to libraries, so the full path has to be constructed.
- The environment variable `LIBPATH` is used for shared library paths.
- Instructions in shared libraries start at non-zero addresses.
- Internal libc functions may be called before interceptor initialization, so need to call the real libc function via function pointer
Builds on the effort to support AIX in sanitizer_common/asan.
---
Patch is 47.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131868.diff
21 Files Affected:
- (modified) compiler-rt/lib/sanitizer_common/CMakeLists.txt (+4)
- (added) compiler-rt/lib/sanitizer_common/sanitizer_aix.cpp (+500)
- (added) compiler-rt/lib/sanitizer_common/sanitizer_aix.h (+47)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_common.cpp (+6)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_common.h (+6-1)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_file.cpp (+2-2)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_file.h (+2-1)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_posix.h (+5)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp (+26-3)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h (+9-9)
- (added) compiler-rt/lib/sanitizer_common/sanitizer_procmaps_aix.cpp (+212)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp (+10-5)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp (+5-4)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.cpp (+4-1)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp (+3)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp (+33-6)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp (+1-1)
- (added) compiler-rt/lib/sanitizer_common/sanitizer_unwind_aix.cpp (+66)
- (modified) compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp (+6-6)
- (added) compiler-rt/test/sanitizer_common/TestCases/Inputs/sanitizer_default_arch/llvm-symbolizer (+7)
- (added) compiler-rt/test/sanitizer_common/TestCases/symbolizer_default_arch_ppc64.cpp (+18)
``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
index 09391e4f5f370..8789e02780050 100644
--- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
@@ -2,6 +2,7 @@
# These components are shared between AddressSanitizer and ThreadSanitizer.
set(SANITIZER_SOURCES_NOTERMINATION
+ sanitizer_aix.cpp
sanitizer_allocator.cpp
sanitizer_common.cpp
sanitizer_deadlock_detector1.cpp
@@ -25,6 +26,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
sanitizer_platform_limits_solaris.cpp
sanitizer_posix.cpp
sanitizer_printf.cpp
+ sanitizer_procmaps_aix.cpp
sanitizer_procmaps_common.cpp
sanitizer_procmaps_bsd.cpp
sanitizer_procmaps_fuchsia.cpp
@@ -95,6 +97,7 @@ set(SANITIZER_SYMBOLIZER_SOURCES
sanitizer_symbolizer_report_fuchsia.cpp
sanitizer_symbolizer_win.cpp
sanitizer_thread_history.cpp
+ sanitizer_unwind_aix.cpp
sanitizer_unwind_linux_libcdep.cpp
sanitizer_unwind_fuchsia.cpp
sanitizer_unwind_win.cpp
@@ -107,6 +110,7 @@ set(SANITIZER_IMPL_HEADERS
sancov_flags.h
sancov_flags.inc
sanitizer_addrhashmap.h
+ sanitizer_aix.h
sanitizer_allocator.h
sanitizer_allocator_checks.h
sanitizer_allocator_combined.h
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_aix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_aix.cpp
new file mode 100644
index 0000000000000..b45ce619d7098
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_aix.cpp
@@ -0,0 +1,500 @@
+//===-- sanitizer_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 shared between various sanitizers' runtime libraries and
+// implements AIX-specific functions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_AIX
+# include <dlfcn.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <pthread.h>
+# include <sched.h>
+# include <signal.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/errno.h>
+# include <sys/mman.h>
+# include <sys/procfs.h>
+# include <sys/stat.h>
+# include <sys/thread.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/ucontext.h>
+# include <unistd.h>
+
+# include "interception/interception.h"
+# include "sanitizer_aix.h"
+# include "sanitizer_common.h"
+# include "sanitizer_file.h"
+# include "sanitizer_libc.h"
+# include "sanitizer_procmaps.h"
+
+extern char **environ;
+extern char **p_xargv;
+
+namespace __sanitizer {
+
+# include "sanitizer_syscall_generic.inc"
+
+static void *GetFuncAddr(const char *name) {
+ // FIXME: if we are going to ship dynamic asan library, we may need to search
+ // all the loaded modules with RTLD_DEFAULT if RTLD_NEXT failed.
+ void *addr = dlsym(RTLD_NEXT, name);
+ return addr;
+}
+
+// Internal implementation for the libc functions are also calling to the same
+// name function in libc. However because the same name function to libc may be
+// intercepted, and in the interceptor function, it may call REAL(func). But the
+// REAL(func) may be not assigned at this time, because internal_func may be
+// called before interceptor init functions are called. So we need to call to
+// libc function via function pointer.
+
+# define _REAL(func, ...) real##_##func(__VA_ARGS__)
+
+# define DEFINE__REAL(ret_type, func, ...) \
+ static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
+ if (!real_##func) { \
+ real_##func = (ret_type(*)(__VA_ARGS__))GetFuncAddr(#func); \
+ } \
+ CHECK(real_##func);
+
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+ u64 offset) {
+ DEFINE__REAL(uptr, mmap, void *addr, uptr length, int prot, int flags, int fd,
+ u64 offset);
+ return _REAL(mmap, addr, length, prot, flags, fd, offset);
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+ DEFINE__REAL(uptr, munmap, void *addr, uptr length);
+ return _REAL(munmap, addr, length);
+}
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+ DEFINE__REAL(int, mprotect, void *addr, uptr length, int prot);
+ return _REAL(mprotect, addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+ char *raddr = reinterpret_cast<char *>(addr);
+ DEFINE__REAL(int, madvise, char *raddr, uptr length, int advice)
+ return _REAL(madvise, raddr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+ DEFINE__REAL(uptr, close, fd_t fd);
+ return _REAL(close, fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+ DEFINE__REAL(uptr, open, const char *filename, int flags);
+ return _REAL(open, filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+ DEFINE__REAL(uptr, open, const char *filename, int flags, u32 mode);
+ return _REAL(open, filename, flags, mode);
+}
+
+__sanitizer_FILE *internal_popen(const char *command, const char *type) {
+ DEFINE__REAL(__sanitizer_FILE *, popen, const char *command,
+ const char *type);
+ return _REAL(popen, command, type);
+}
+
+int internal_pclose(__sanitizer_FILE *file) {
+ FILE *rfile = reinterpret_cast<FILE *>(file);
+ DEFINE__REAL(int, pclose, FILE *file);
+ return _REAL(pclose, rfile);
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+ DEFINE__REAL(uptr, read, fd_t fd, void *buf, uptr count);
+ return _REAL(read, fd, buf, count);
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+ DEFINE__REAL(uptr, write, fd_t fd, const void *buf, uptr count);
+ return _REAL(write, fd, buf, count);
+}
+
+uptr internal_stat(const char *path, void *buf) {
+ DEFINE__REAL(uptr, stat, const char *path, void *buf);
+ return _REAL(stat, path, buf);
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+ DEFINE__REAL(uptr, lstat, const char *path, void *buf);
+ return _REAL(lstat, path, buf);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+ DEFINE__REAL(uptr, fstat, fd_t fd, void *buf);
+ return _REAL(fstat, fd, buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+ struct stat st;
+ if (internal_fstat(fd, &st))
+ return -1;
+ return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+ DEFINE__REAL(uptr, dup, int oldfd);
+ return _REAL(dup, oldfd);
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+ DEFINE__REAL(uptr, dup2, int oldfd, int newfd);
+ return _REAL(dup2, oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+ DEFINE__REAL(uptr, readlink, const char *path, char *buf, uptr bufsize);
+ return _REAL(readlink, path, buf, bufsize);
+}
+
+uptr internal_unlink(const char *path) {
+ DEFINE__REAL(uptr, unlink, const char *path);
+ return _REAL(unlink, path);
+}
+
+uptr internal_sched_yield() {
+ DEFINE__REAL(uptr, sched_yield);
+ return _REAL(sched_yield);
+}
+
+void FutexWait(atomic_uint32_t *p, u32 cmp) { internal_sched_yield(); }
+
+void FutexWake(atomic_uint32_t *p, u32 count) {}
+
+void internal__exit(int exitcode) {
+ DEFINE__REAL(void, _exit, int exitcode);
+ _REAL(_exit, exitcode);
+ Die(); // Unreachable.
+}
+
+void internal_usleep(u64 useconds) {
+ DEFINE__REAL(void, usleep, u64 useconds);
+ _REAL(usleep, useconds);
+}
+
+uptr internal_getpid() {
+ DEFINE__REAL(uptr, getpid);
+ return _REAL(getpid);
+}
+
+int internal_dlinfo(void *handle, int request, void *p) { return 0; }
+
+int internal_sigaction(int signum, const void *act, void *oldact) {
+ DEFINE__REAL(int, sigaction, int signum, const void *act, void *oldact);
+ return _REAL(sigaction, signum, act, oldact);
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) {
+ sigset_t *rset = reinterpret_cast<sigset_t *>(set);
+ DEFINE__REAL(void, sigfillset, sigset_t *rset);
+ _REAL(sigfillset, rset);
+}
+
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ sigset_t *rset = reinterpret_cast<sigset_t *>(set);
+ sigset_t *roldset = reinterpret_cast<sigset_t *>(oldset);
+ DEFINE__REAL(uptr, sigprocmask, int how, sigset_t *rset, sigset_t *roldset);
+ return _REAL(sigprocmask, how, rset, roldset);
+}
+
+char *internal_getcwd(char *buf, uptr size) {
+ DEFINE__REAL(char *, getcwd, char *buf, uptr size);
+ return _REAL(getcwd, buf, size);
+}
+
+int internal_fork() {
+ DEFINE__REAL(int, fork);
+ return _REAL(fork);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]) {
+ DEFINE__REAL(uptr, execve, const char *filename, char *const argv[],
+ char *const envp[]);
+ return _REAL(execve, filename, argv, envp);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+ DEFINE__REAL(uptr, waitpid, int pid, int *status, int options);
+ return _REAL(waitpid, pid, status, options);
+}
+
+int internal_pthread_join(pthread_t thread, void **status) {
+ DEFINE__REAL(int, pthread_join, pthread_t thread, void **status);
+ return _REAL(pthread_join, thread, status);
+}
+
+int internal_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+ void *(*start_routine)(void *), void *arg) {
+ DEFINE__REAL(int, pthread_create, pthread_t *thread,
+ const pthread_attr_t *attr, void *(*start_routine)(void *),
+ void *arg);
+ return _REAL(pthread_create, thread, attr, start_routine, arg);
+}
+
+void *internal_start_thread(void *(*func)(void *arg), void *arg) {
+ // Start the thread with signals blocked, otherwise it can steal user signals.
+ __sanitizer_sigset_t set, old;
+ internal_sigfillset(&set);
+ internal_sigprocmask(SIG_SETMASK, &set, &old);
+ pthread_t th;
+ internal_pthread_create(&th, 0, func, arg);
+ internal_sigprocmask(SIG_SETMASK, &old, 0);
+ // pthread_t is unsinged int on AIX
+ return reinterpret_cast<void *>(th);
+}
+
+void internal_join_thread(void *th) {
+ internal_pthread_join((pthread_t)(reinterpret_cast<uptr>(th)), nullptr);
+}
+
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+ clock_t rclk_id = reinterpret_cast<clock_t>(clk_id);
+ struct timespec *rtp = reinterpret_cast<struct timespec *>(tp);
+ DEFINE__REAL(uptr, clock_gettime, clock_t rclk_id, struct timespec *rtp);
+ return _REAL(clock_gettime, rclk_id, rtp);
+}
+
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom) {
+ CHECK(stack_top);
+ CHECK(stack_bottom);
+ if (at_initialization) {
+ // This is the main thread. Libpthread may not be initialized yet.
+ struct rlimit rl;
+ CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+
+ // Find the mapping that contains a stack variable.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
+ if (proc_maps.Error()) {
+ *stack_top = *stack_bottom = 0;
+ return;
+ }
+ MemoryMappedSegment segment;
+ uptr prev_end = 0;
+ while (proc_maps.Next(&segment)) {
+ if ((uptr)&rl < segment.end)
+ break;
+ prev_end = segment.end;
+ }
+
+ CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);
+
+ // Get stacksize from rlimit, but clip it so that it does not overlap
+ // with other mappings.
+ uptr stacksize = rl.rlim_cur;
+ if (stacksize > segment.end - prev_end)
+ stacksize = segment.end - prev_end;
+ // When running with unlimited stack size, we still want to set some limit.
+ // The unlimited stack size is caused by 'ulimit -s unlimited'.
+ // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
+ if (stacksize > kMaxThreadStackSize)
+ stacksize = kMaxThreadStackSize;
+ *stack_top = segment.end;
+ *stack_bottom = segment.end - stacksize;
+ return;
+ }
+ uptr stacksize = 0;
+ void *stackaddr = nullptr;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
+ internal_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
+ pthread_attr_destroy(&attr);
+
+ *stack_top = (uptr)stackaddr;
+ *stack_bottom = (uptr)stackaddr - stacksize;
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
+ uptr *tls_begin, uptr *tls_end) {
+ // FIXME: handle TLS related flag
+ *tls_begin = 0;
+ *tls_end = 0;
+
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_begin = stack_bottom;
+ *stk_end = stack_top;
+}
+
+const char *GetEnv(const char *name) { return getenv(name); }
+
+tid_t GetTid() { return thread_self(); }
+
+uptr ReadBinaryName(char *buf, uptr buf_len) {
+ struct stat statData;
+ struct psinfo psinfoData;
+
+ char FilePsinfo[100] = {};
+ internal_snprintf(FilePsinfo, 100, "/proc/%d/psinfo", internal_getpid());
+ CHECK_EQ(internal_stat(FilePsinfo, &statData), 0);
+
+ const int fd = internal_open(FilePsinfo, O_RDONLY);
+ ssize_t readNum = internal_read(fd, &psinfoData, sizeof(psinfoData));
+ CHECK_GE(readNum, 0);
+
+ internal_close(fd);
+ char *binary_name = (reinterpret_cast<char ***>(psinfoData.pr_argv))[0][0];
+
+ // This is an absulate path.
+ if (binary_name[0] == '/')
+ return internal_snprintf(buf, buf_len, "%s", binary_name);
+
+ // This is a relative path to the binary, starts with ./ or ../
+ if (binary_name[0] == '.') {
+ char *path = nullptr;
+ if ((path = internal_getcwd(buf, buf_len)) != nullptr)
+ return internal_snprintf(buf + internal_strlen(path),
+ buf_len - internal_strlen(path), "/%s",
+ binary_name) +
+ internal_strlen(path);
+ }
+
+ // This is running a raw binary in the dir where it is from.
+ char *path = nullptr;
+ if ((path = internal_getcwd(buf, buf_len)) != nullptr) {
+ char fullName[kMaxPathLength] = {};
+ internal_snprintf(fullName, kMaxPathLength, "%s/%s", path, binary_name);
+ if (FileExists(fullName))
+ return internal_snprintf(buf + internal_strlen(path),
+ buf_len - internal_strlen(path), "/%s",
+ binary_name) +
+ internal_strlen(path);
+ }
+
+ // Find the binary in the env PATH.
+ if ((path = FindPathToBinaryOrLibrary(binary_name)) != nullptr)
+ return internal_snprintf(buf, buf_len, "%s", path);
+
+ return 0;
+}
+
+// https://www.ibm.com/docs/en/aix/7.3?topic=concepts-system-memory-allocation-using-malloc-subsystem
+uptr GetMaxVirtualAddress() {
+# if SANITIZER_WORDSIZE == 64
+ return (1ULL << 60) - 1;
+# else
+ return 0xffffffff;
+# endif
+}
+
+uptr GetMaxUserVirtualAddress() { return GetMaxVirtualAddress(); }
+
+uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
+ return ReadBinaryName(buf, buf_len);
+}
+
+void InitializePlatformCommonFlags(CommonFlags *cf) {}
+
+void InitializePlatformEarly() {
+ // Do nothing.
+}
+
+uptr GetPageSize() { return getpagesize(); }
+
+void CheckASLR() {
+ // Do nothing
+}
+
+HandleSignalMode GetHandleSignalMode(int signum) {
+ switch (signum) {
+ case SIGABRT:
+ return common_flags()->handle_abort;
+ case SIGILL:
+ return common_flags()->handle_sigill;
+ case SIGTRAP:
+ return common_flags()->handle_sigtrap;
+ case SIGFPE:
+ return common_flags()->handle_sigfpe;
+ case SIGSEGV:
+ return common_flags()->handle_segv;
+ case SIGBUS:
+ return common_flags()->handle_sigbus;
+ }
+ return kHandleSignalNo;
+}
+
+void InitTlsSize() {}
+
+bool FileExists(const char *filename) {
+ struct stat st;
+ if (internal_stat(filename, &st))
+ return false;
+ // Sanity check: filename is a regular file.
+ return S_ISREG(st.st_mode);
+}
+
+bool DirExists(const char *path) {
+ struct stat st;
+ if (internal_stat(path, &st))
+ return false;
+ return S_ISDIR(st.st_mode);
+}
+
+uptr GetTlsSize() {
+ // FIXME: implement this interface.
+ return 0;
+}
+
+SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
+ return SignalContext::Unknown;
+}
+
+bool SignalContext::IsTrueFaultingAddress() const { return true; }
+
+void SignalContext::InitPcSpBp() {
+ ucontext_t *ucontext = (ucontext_t *)context;
+ pc = ucontext->uc_mcontext.jmp_context.iar;
+ sp = ucontext->uc_mcontext.jmp_context.gpr[1];
+ // The powerpc{,64} ABIs do not specify r31 as the frame pointer, but compiler
+ // always uses r31 when we need a frame pointer.
+ bp = ucontext->uc_mcontext.jmp_context.gpr[31];
+}
+
+void SignalContext::DumpAllRegisters(void *context) {}
+
+char **GetEnviron() { return environ; }
+
+char **GetArgv() { return p_xargv; }
+
+void ListOfModules::init() {
+ clearOrInit();
+ MemoryMappingLayout memory_mapping(false);
+ memory_mapping.DumpListOfModules(&modules_);
+}
+
+void ListOfModules::fallbackInit() { clear(); }
+
+u64 MonotonicNanoTime() {
+ timespec ts;
+ internal_clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
+}
+
+// FIXME implement on this platform.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_AIX
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_aix.h b/compiler-rt/lib/sanitizer_common/sanitizer_aix.h
new file mode 100644
index 0000000000000..8854db9d3b259
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_aix.h
@@ -0,0 +1,47 @@
+//===-- sanitizer_aix.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 shared between various sanitizers' runtime libraries and
+// provides definitions for AIX-specific functions.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_AIX_H
+#define SANITIZER_AIX_H
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_AIX
+# include "sanitizer_common.h"
+# include "sanitizer_posix.h"
+
+namespace __sanitizer {
+
+# if SANITIZER_WORDSIZE == 32
+static const uptr InstructionStart = 0x10000000;
+# else
+static const uptr InstructionStart = 0x100000000;
+# endif
+
+struct ProcSelfMapsBuff {
+ char *data;
+ uptr mmaped_size;
+ uptr len;
+};
+
+struct MemoryMappingLayoutData {
+ ProcSelfMapsBuff proc_self_maps;
+ const char *current;
+};
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
+
+char *internal_getcwd(char *buf, uptr size);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_AIX
+#endif // SANITIZER_AIX_H
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
index 6cd69a53093e7..3b5286bcf9be9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
@@ -275,6 +275,12 @@ const char *GetProcessName() {
return process_name_cache_str;
}
+const char *GetBinaryName() {
+ if (binary_name_cache_str[0] == '\0')
+ ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str));
+ return binary_name_cache_str;
+}
+
static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) {
ReadLongProcessName(buf, buf_len);
char *s = const_cast<char *>(StripModuleName(buf));
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index d9e7ded593feb..466790d335ac0 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -290,6 +290,7 @@ uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len);
uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
const char *GetProcessName();
+const char *GetBinaryName();
void UpdateProcessName();
void CacheBinaryName();
void DisableCoreDumperIfNecessary();
@@ -835,7 +8...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/131868
More information about the llvm-commits
mailing list