2874 lines · cpp
1//===-- sanitizer_linux.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is shared between AddressSanitizer and ThreadSanitizer10// run-time libraries and implements linux-specific functions from11// sanitizer_libc.h.12//===----------------------------------------------------------------------===//13 14#include "sanitizer_platform.h"15 16#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \17 SANITIZER_SOLARIS || SANITIZER_HAIKU18 19# include "sanitizer_common.h"20# include "sanitizer_flags.h"21# include "sanitizer_getauxval.h"22# include "sanitizer_internal_defs.h"23# include "sanitizer_libc.h"24# include "sanitizer_linux.h"25# include "sanitizer_mutex.h"26# include "sanitizer_placement_new.h"27# include "sanitizer_procmaps.h"28 29# if SANITIZER_LINUX && !SANITIZER_GO30# include <asm/param.h>31# endif32 33// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'34// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To35// access stat from asm/stat.h, without conflicting with definition in36// sys/stat.h, we use this trick. sparc64 is similar, using37// syscall(__NR_stat64) and struct kernel_stat64.38# if SANITIZER_LINUX && (SANITIZER_MIPS64 || SANITIZER_SPARC64)39# include <asm/unistd.h>40# include <sys/types.h>41# define stat kernel_stat42# if SANITIZER_SPARC6443# define stat64 kernel_stat6444# endif45# if SANITIZER_GO46# undef st_atime47# undef st_mtime48# undef st_ctime49# define st_atime st_atim50# define st_mtime st_mtim51# define st_ctime st_ctim52# endif53# include <asm/stat.h>54# undef stat55# undef stat6456# endif57 58# include <dlfcn.h>59# include <errno.h>60# include <fcntl.h>61# include <link.h>62# include <pthread.h>63# include <sched.h>64# include <signal.h>65# include <sys/mman.h>66# if !SANITIZER_SOLARIS && !SANITIZER_HAIKU67# include <sys/ptrace.h>68# endif69# include <sys/resource.h>70# include <sys/stat.h>71# if !SANITIZER_HAIKU72# include <sys/syscall.h>73# include <ucontext.h>74# endif75# include <sys/time.h>76# include <sys/types.h>77# include <unistd.h>78 79# if SANITIZER_LINUX80# include <sys/utsname.h>81# endif82 83# if SANITIZER_LINUX && !SANITIZER_ANDROID84# include <sys/personality.h>85# endif86 87# if SANITIZER_ANDROID && __ANDROID_API__ < 3588// The weak `strerrorname_np` (introduced in API level 35) definition,89// allows for checking the API level at runtime.90extern "C" SANITIZER_WEAK_ATTRIBUTE const char *strerrorname_np(int);91# endif92 93# if SANITIZER_LINUX && defined(__loongarch__)94# include <sys/sysmacros.h>95# endif96 97# if SANITIZER_LINUX && defined(__powerpc64__)98# include <asm/ptrace.h>99# endif100 101# if SANITIZER_FREEBSD102# include <machine/atomic.h>103# include <sys/exec.h>104# include <sys/procctl.h>105# include <sys/sysctl.h>106extern "C" {107// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on108// FreeBSD 9.2 and 10.0.109# include <sys/umtx.h>110}111# include <sys/thr.h>112# endif // SANITIZER_FREEBSD113 114# if SANITIZER_NETBSD115# include <limits.h> // For NAME_MAX116# include <sys/exec.h>117# include <sys/sysctl.h>118extern struct ps_strings *__ps_strings;119# endif // SANITIZER_NETBSD120 121# if SANITIZER_SOLARIS122# include <stddef.h>123# include <stdlib.h>124# include <sys/frame.h>125# include <thread.h>126# define environ _environ127# endif128 129# if SANITIZER_HAIKU130# include <OS.h>131# include <elf.h>132# include <image.h>133extern "C" char **__libc_argv;134# endif135 136extern char **environ;137 138# if SANITIZER_LINUX139// <linux/time.h>140struct kernel_timeval {141 long tv_sec;142 long tv_usec;143};144 145// <linux/futex.h> is broken on some linux distributions.146const int FUTEX_WAIT = 0;147const int FUTEX_WAKE = 1;148const int FUTEX_PRIVATE_FLAG = 128;149const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;150const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;151# endif // SANITIZER_LINUX152 153// Are we using 32-bit or 64-bit Linux syscalls?154// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32155// but it still needs to use 64-bit syscalls.156# if SANITIZER_LINUX && \157 (defined(__x86_64__) || defined(__powerpc64__) || \158 SANITIZER_WORDSIZE == 64 || \159 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32))160# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1161# else162# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0163# endif164 165// Note : FreeBSD implemented both Linux and OpenBSD apis.166# if SANITIZER_LINUX && defined(__NR_getrandom)167# if !defined(GRND_NONBLOCK)168# define GRND_NONBLOCK 1169# endif170# define SANITIZER_USE_GETRANDOM 1171# else172# define SANITIZER_USE_GETRANDOM 0173# endif // SANITIZER_LINUX && defined(__NR_getrandom)174 175# if SANITIZER_FREEBSD176# define SANITIZER_USE_GETENTROPY 1177extern "C" void *__sys_mmap(void *addr, size_t len, int prot, int flags, int fd,178 off_t offset);179# endif180 181namespace __sanitizer {182 183void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {184 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));185}186 187# if SANITIZER_LINUX188// Deletes the specified signal from newset, if it is not present in oldset189// Equivalently: newset[signum] = newset[signum] & oldset[signum]190static void KeepUnblocked(__sanitizer_sigset_t &newset,191 __sanitizer_sigset_t &oldset, int signum) {192 // FIXME: https://github.com/google/sanitizers/issues/1816193 if (SANITIZER_ANDROID || !internal_sigismember(&oldset, signum))194 internal_sigdelset(&newset, signum);195}196# endif197 198// Block asynchronous signals199void BlockSignals(__sanitizer_sigset_t *oldset) {200 __sanitizer_sigset_t newset;201 internal_sigfillset(&newset);202 203# if SANITIZER_LINUX204 __sanitizer_sigset_t currentset;205 206# if !SANITIZER_ANDROID207 // FIXME: https://github.com/google/sanitizers/issues/1816208 SetSigProcMask(NULL, ¤tset);209 210 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked211 // on any thread, setuid call hangs.212 // See test/sanitizer_common/TestCases/Linux/setuid.c.213 KeepUnblocked(newset, currentset, 33);214# endif // !SANITIZER_ANDROID215 216 // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.217 // If this signal is blocked, such calls cannot be handled and the process may218 // hang.219 KeepUnblocked(newset, currentset, 31);220 221# if !SANITIZER_ANDROID222 // Don't block synchronous signals223 // but also don't unblock signals that the user had deliberately blocked.224 // FIXME: https://github.com/google/sanitizers/issues/1816225 KeepUnblocked(newset, currentset, SIGSEGV);226 KeepUnblocked(newset, currentset, SIGBUS);227 KeepUnblocked(newset, currentset, SIGILL);228 KeepUnblocked(newset, currentset, SIGTRAP);229 KeepUnblocked(newset, currentset, SIGABRT);230 KeepUnblocked(newset, currentset, SIGFPE);231 KeepUnblocked(newset, currentset, SIGPIPE);232# endif //! SANITIZER_ANDROID233 234# endif // SANITIZER_LINUX235 236 SetSigProcMask(&newset, oldset);237}238 239ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {240 BlockSignals(&saved_);241 if (copy)242 internal_memcpy(copy, &saved_, sizeof(saved_));243}244 245ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }246 247# if SANITIZER_LINUX && defined(__x86_64__)248# include "sanitizer_syscall_linux_x86_64.inc"249# elif SANITIZER_LINUX && SANITIZER_RISCV64250# include "sanitizer_syscall_linux_riscv64.inc"251# elif SANITIZER_LINUX && defined(__aarch64__)252# include "sanitizer_syscall_linux_aarch64.inc"253# elif SANITIZER_LINUX && defined(__arm__)254# include "sanitizer_syscall_linux_arm.inc"255# elif SANITIZER_LINUX && defined(__hexagon__)256# include "sanitizer_syscall_linux_hexagon.inc"257# elif SANITIZER_LINUX && SANITIZER_LOONGARCH64258# include "sanitizer_syscall_linux_loongarch64.inc"259# else260# include "sanitizer_syscall_generic.inc"261# endif262 263// --------------- sanitizer_libc.h264# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU265# if !SANITIZER_S390266uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,267 u64 offset) {268# if SANITIZER_FREEBSD269 return (uptr)__sys_mmap(addr, length, prot, flags, fd, offset);270# elif SANITIZER_LINUX_USES_64BIT_SYSCALLS271 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,272 offset);273# else274 // mmap2 specifies file offset in 4096-byte units.275 CHECK(IsAligned(offset, 4096));276 return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,277 (OFF_T)(offset / 4096));278# endif279}280# endif // !SANITIZER_S390281 282uptr internal_munmap(void *addr, uptr length) {283 return internal_syscall(SYSCALL(munmap), (uptr)addr, length);284}285 286# if SANITIZER_LINUX287uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,288 void *new_address) {289 return internal_syscall(SYSCALL(mremap), (uptr)old_address, old_size,290 new_size, flags, (uptr)new_address);291}292# endif293 294int internal_mprotect(void *addr, uptr length, int prot) {295 return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);296}297 298int internal_madvise(uptr addr, uptr length, int advice) {299 return internal_syscall(SYSCALL(madvise), addr, length, advice);300}301 302# if SANITIZER_FREEBSD303uptr internal_close_range(fd_t lowfd, fd_t highfd, int flags) {304 return internal_syscall(SYSCALL(close_range), lowfd, highfd, flags);305}306# endif307uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); }308 309uptr internal_open(const char *filename, int flags) {310# if SANITIZER_LINUX311 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);312# else313 return internal_syscall(SYSCALL(open), (uptr)filename, flags);314# endif315}316 317uptr internal_open(const char *filename, int flags, u32 mode) {318# if SANITIZER_LINUX319 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,320 mode);321# else322 return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);323# endif324}325 326uptr internal_read(fd_t fd, void *buf, uptr count) {327 sptr res;328 HANDLE_EINTR(res,329 (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, count));330 return res;331}332 333uptr internal_write(fd_t fd, const void *buf, uptr count) {334 sptr res;335 HANDLE_EINTR(res,336 (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, count));337 return res;338}339 340uptr internal_ftruncate(fd_t fd, uptr size) {341 sptr res;342 HANDLE_EINTR(res,343 (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size));344 return res;345}346 347# if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX348static void stat64_to_stat(struct stat64 *in, struct stat *out) {349 internal_memset(out, 0, sizeof(*out));350 out->st_dev = in->st_dev;351 out->st_ino = in->st_ino;352 out->st_mode = in->st_mode;353 out->st_nlink = in->st_nlink;354 out->st_uid = in->st_uid;355 out->st_gid = in->st_gid;356 out->st_rdev = in->st_rdev;357 out->st_size = in->st_size;358 out->st_blksize = in->st_blksize;359 out->st_blocks = in->st_blocks;360 out->st_atime = in->st_atime;361 out->st_mtime = in->st_mtime;362 out->st_ctime = in->st_ctime;363}364# endif365 366# if SANITIZER_LINUX && defined(__loongarch__)367static void statx_to_stat(struct statx *in, struct stat *out) {368 internal_memset(out, 0, sizeof(*out));369 out->st_dev = makedev(in->stx_dev_major, in->stx_dev_minor);370 out->st_ino = in->stx_ino;371 out->st_mode = in->stx_mode;372 out->st_nlink = in->stx_nlink;373 out->st_uid = in->stx_uid;374 out->st_gid = in->stx_gid;375 out->st_rdev = makedev(in->stx_rdev_major, in->stx_rdev_minor);376 out->st_size = in->stx_size;377 out->st_blksize = in->stx_blksize;378 out->st_blocks = in->stx_blocks;379 out->st_atime = in->stx_atime.tv_sec;380 out->st_atim.tv_nsec = in->stx_atime.tv_nsec;381 out->st_mtime = in->stx_mtime.tv_sec;382 out->st_mtim.tv_nsec = in->stx_mtime.tv_nsec;383 out->st_ctime = in->stx_ctime.tv_sec;384 out->st_ctim.tv_nsec = in->stx_ctime.tv_nsec;385}386# endif387 388# if SANITIZER_MIPS64 || SANITIZER_SPARC64389# if SANITIZER_MIPS64390typedef struct kernel_stat kstat_t;391# else392typedef struct kernel_stat64 kstat_t;393# endif394// Undefine compatibility macros from <sys/stat.h>395// so that they would not clash with the kernel_stat396// st_[a|m|c]time fields397# if !SANITIZER_GO398# undef st_atime399# undef st_mtime400# undef st_ctime401# endif402# if defined(SANITIZER_ANDROID)403// Bionic sys/stat.h defines additional macros404// for compatibility with the old NDKs and405// they clash with the kernel_stat structure406// st_[a|m|c]time_nsec fields.407# undef st_atime_nsec408# undef st_mtime_nsec409# undef st_ctime_nsec410# endif411static void kernel_stat_to_stat(kstat_t *in, struct stat *out) {412 internal_memset(out, 0, sizeof(*out));413 out->st_dev = in->st_dev;414 out->st_ino = in->st_ino;415 out->st_mode = in->st_mode;416 out->st_nlink = in->st_nlink;417 out->st_uid = in->st_uid;418 out->st_gid = in->st_gid;419 out->st_rdev = in->st_rdev;420 out->st_size = in->st_size;421 out->st_blksize = in->st_blksize;422 out->st_blocks = in->st_blocks;423# if defined(__USE_MISC) || defined(__USE_XOPEN2K8) || \424 defined(SANITIZER_ANDROID)425 out->st_atim.tv_sec = in->st_atime;426 out->st_atim.tv_nsec = in->st_atime_nsec;427 out->st_mtim.tv_sec = in->st_mtime;428 out->st_mtim.tv_nsec = in->st_mtime_nsec;429 out->st_ctim.tv_sec = in->st_ctime;430 out->st_ctim.tv_nsec = in->st_ctime_nsec;431# else432 out->st_atime = in->st_atime;433 out->st_atimensec = in->st_atime_nsec;434 out->st_mtime = in->st_mtime;435 out->st_mtimensec = in->st_mtime_nsec;436 out->st_ctime = in->st_ctime;437 out->st_atimensec = in->st_ctime_nsec;438# endif439}440# endif441 442uptr internal_stat(const char *path, void *buf) {443# if SANITIZER_FREEBSD444 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);445# elif SANITIZER_LINUX446# if defined(__loongarch__)447 struct statx bufx;448 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,449 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);450 statx_to_stat(&bufx, (struct stat *)buf);451 return res;452# elif ( \453 SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \454 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \455 !SANITIZER_SPARC456 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,457 0);458# elif SANITIZER_SPARC64459 kstat_t buf64;460 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,461 (uptr)&buf64, 0);462 kernel_stat_to_stat(&buf64, (struct stat *)buf);463 return res;464# else465 struct stat64 buf64;466 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,467 (uptr)&buf64, 0);468 stat64_to_stat(&buf64, (struct stat *)buf);469 return res;470# endif471# else472 struct stat64 buf64;473 int res = internal_syscall(SYSCALL(stat64), path, &buf64);474 stat64_to_stat(&buf64, (struct stat *)buf);475 return res;476# endif477}478 479uptr internal_lstat(const char *path, void *buf) {480# if SANITIZER_FREEBSD481 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,482 AT_SYMLINK_NOFOLLOW);483# elif SANITIZER_LINUX484# if defined(__loongarch__)485 struct statx bufx;486 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,487 AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,488 STATX_BASIC_STATS, (uptr)&bufx);489 statx_to_stat(&bufx, (struct stat *)buf);490 return res;491# elif ( \492 defined(_LP64) || SANITIZER_X32 || \493 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \494 !SANITIZER_SPARC495 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,496 AT_SYMLINK_NOFOLLOW);497# elif SANITIZER_SPARC64498 kstat_t buf64;499 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,500 (uptr)&buf64, AT_SYMLINK_NOFOLLOW);501 kernel_stat_to_stat(&buf64, (struct stat *)buf);502 return res;503# else504 struct stat64 buf64;505 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,506 (uptr)&buf64, AT_SYMLINK_NOFOLLOW);507 stat64_to_stat(&buf64, (struct stat *)buf);508 return res;509# endif510# else511 struct stat64 buf64;512 int res = internal_syscall(SYSCALL(lstat64), path, &buf64);513 stat64_to_stat(&buf64, (struct stat *)buf);514 return res;515# endif516}517 518uptr internal_fstat(fd_t fd, void *buf) {519# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS520# if SANITIZER_MIPS64521 // For mips64, fstat syscall fills buffer in the format of kernel_stat522 kstat_t kbuf;523 int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);524 kernel_stat_to_stat(&kbuf, (struct stat *)buf);525 return res;526# elif SANITIZER_LINUX && SANITIZER_SPARC64527 // For sparc64, fstat64 syscall fills buffer in the format of kernel_stat64528 kstat_t kbuf;529 int res = internal_syscall(SYSCALL(fstat64), fd, &kbuf);530 kernel_stat_to_stat(&kbuf, (struct stat *)buf);531 return res;532# elif SANITIZER_LINUX && defined(__loongarch__)533 struct statx bufx;534 int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,535 STATX_BASIC_STATS, (uptr)&bufx);536 statx_to_stat(&bufx, (struct stat *)buf);537 return res;538# else539 return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);540# endif541# else542 struct stat64 buf64;543 int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);544 stat64_to_stat(&buf64, (struct stat *)buf);545 return res;546# endif547}548 549uptr internal_filesize(fd_t fd) {550 struct stat st;551 if (internal_fstat(fd, &st))552 return -1;553 return (uptr)st.st_size;554}555 556uptr internal_dup(int oldfd) { return internal_syscall(SYSCALL(dup), oldfd); }557 558uptr internal_dup2(int oldfd, int newfd) {559# if SANITIZER_LINUX560 return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);561# else562 return internal_syscall(SYSCALL(dup2), oldfd, newfd);563# endif564}565 566uptr internal_readlink(const char *path, char *buf, uptr bufsize) {567# if SANITIZER_LINUX568 return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,569 bufsize);570# else571 return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);572# endif573}574 575uptr internal_unlink(const char *path) {576# if SANITIZER_LINUX577 return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);578# else579 return internal_syscall(SYSCALL(unlink), (uptr)path);580# endif581}582 583uptr internal_rename(const char *oldpath, const char *newpath) {584# if (defined(__riscv) || defined(__loongarch__)) && defined(__linux__)585 return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,586 (uptr)newpath, 0);587# elif SANITIZER_LINUX588 return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,589 (uptr)newpath);590# else591 return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);592# endif593}594 595uptr internal_sched_yield() { return internal_syscall(SYSCALL(sched_yield)); }596 597void internal_usleep(u64 useconds) {598 struct timespec ts;599 ts.tv_sec = useconds / 1000000;600 ts.tv_nsec = (useconds % 1000000) * 1000;601 internal_syscall(SYSCALL(nanosleep), &ts, &ts);602}603 604uptr internal_execve(const char *filename, char *const argv[],605 char *const envp[]) {606 return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,607 (uptr)envp);608}609# endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU610 611# if !SANITIZER_NETBSD && !SANITIZER_HAIKU612void internal__exit(int exitcode) {613# if SANITIZER_FREEBSD || SANITIZER_SOLARIS614 internal_syscall(SYSCALL(exit), exitcode);615# else616 internal_syscall(SYSCALL(exit_group), exitcode);617# endif618 Die(); // Unreachable.619}620# endif // !SANITIZER_NETBSD && !SANITIZER_HAIKU621 622// ----------------- sanitizer_common.h623bool FileExists(const char *filename) {624 if (ShouldMockFailureToOpen(filename))625 return false;626 struct stat st;627 if (internal_stat(filename, &st))628 return false;629 // Sanity check: filename is a regular file.630 return S_ISREG(st.st_mode);631}632 633bool DirExists(const char *path) {634 struct stat st;635 if (internal_stat(path, &st))636 return false;637 return S_ISDIR(st.st_mode);638}639 640# if !SANITIZER_NETBSD641ThreadID GetTid() {642# if SANITIZER_FREEBSD643 long Tid;644 thr_self(&Tid);645 return Tid;646# elif SANITIZER_SOLARIS647 return thr_self();648# elif SANITIZER_HAIKU649 return find_thread(NULL);650# else651 return internal_syscall(SYSCALL(gettid));652# endif653}654 655int TgKill(pid_t pid, ThreadID tid, int sig) {656# if SANITIZER_LINUX657 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);658# elif SANITIZER_FREEBSD659 return internal_syscall(SYSCALL(thr_kill2), pid, tid, sig);660# elif SANITIZER_SOLARIS661 (void)pid;662 errno = thr_kill(tid, sig);663 // TgKill is expected to return -1 on error, not an errno.664 return errno != 0 ? -1 : 0;665# elif SANITIZER_HAIKU666 return kill_thread(tid);667# endif668}669# endif670 671# if SANITIZER_GLIBC672u64 NanoTime() {673 kernel_timeval tv;674 internal_memset(&tv, 0, sizeof(tv));675 internal_syscall(SYSCALL(gettimeofday), &tv, 0);676 return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;677}678// Used by real_clock_gettime.679uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {680 return internal_syscall(SYSCALL(clock_gettime), clk_id, tp);681}682# elif !SANITIZER_SOLARIS && !SANITIZER_NETBSD683u64 NanoTime() {684 struct timespec ts;685 clock_gettime(CLOCK_REALTIME, &ts);686 return (u64)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;687}688# endif689 690// Like getenv, but reads env directly from /proc (on Linux) or parses the691// 'environ' array (on some others) and does not use libc. This function692// should be called first inside __asan_init.693const char *GetEnv(const char *name) {694# if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS || \695 SANITIZER_HAIKU696 if (::environ != 0) {697 uptr NameLen = internal_strlen(name);698 for (char **Env = ::environ; *Env != 0; Env++) {699 if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')700 return (*Env) + NameLen + 1;701 }702 }703 return 0; // Not found.704# elif SANITIZER_LINUX705 static char *environ;706 static uptr len;707 static bool inited;708 if (!inited) {709 inited = true;710 uptr environ_size;711 if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))712 environ = nullptr;713 }714 if (!environ || len == 0)715 return nullptr;716 uptr namelen = internal_strlen(name);717 const char *p = environ;718 while (*p != '\0') { // will happen at the \0\0 that terminates the buffer719 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...720 const char *endp = (char *)internal_memchr(p, '\0', len - (p - environ));721 if (!endp) // this entry isn't NUL terminated722 return nullptr;723 else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.724 return p + namelen + 1; // point after =725 p = endp + 1;726 }727 return nullptr; // Not found.728# else729# error "Unsupported platform"730# endif731}732 733# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \734 !SANITIZER_GO735extern "C" {736SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;737}738# endif739 740# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD741static void ReadNullSepFileToArray(const char *path, char ***arr,742 int arr_size) {743 char *buff;744 uptr buff_size;745 uptr buff_len;746 *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");747 if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {748 (*arr)[0] = nullptr;749 return;750 }751 (*arr)[0] = buff;752 int count, i;753 for (count = 1, i = 1;; i++) {754 if (buff[i] == 0) {755 if (buff[i + 1] == 0)756 break;757 (*arr)[count] = &buff[i + 1];758 CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.759 count++;760 }761 }762 (*arr)[count] = nullptr;763}764# endif765 766static void GetArgsAndEnv(char ***argv, char ***envp) {767# if SANITIZER_HAIKU768 *argv = __libc_argv;769 *envp = environ;770# elif SANITIZER_FREEBSD771 // On FreeBSD, retrieving the argument and environment arrays is done via the772 // kern.ps_strings sysctl, which returns a pointer to a structure containing773 // this information. See also <sys/exec.h>.774 ps_strings *pss;775 uptr sz = sizeof(pss);776 if (internal_sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) {777 Printf("sysctl kern.ps_strings failed\n");778 Die();779 }780 *argv = pss->ps_argvstr;781 *envp = pss->ps_envstr;782# elif SANITIZER_NETBSD783 *argv = __ps_strings->ps_argvstr;784 *envp = __ps_strings->ps_envstr;785# else // SANITIZER_FREEBSD786# if !SANITIZER_GO787 if (&__libc_stack_end) {788 uptr *stack_end = (uptr *)__libc_stack_end;789 // Linux/sparc64 needs an adjustment, cf. glibc790 // sysdeps/sparc/sparc{32,64}/dl-machine.h (DL_STACK_END).791# if SANITIZER_LINUX && defined(__sparc__)792 stack_end = &stack_end[16];793# endif794 // Normally argc can be obtained from *stack_end, however, on ARM glibc's795 // _start clobbers it:796 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75797 // Do not special-case ARM and infer argc from argv everywhere.798 int argc = 0;799 while (stack_end[argc + 1]) argc++;800 *argv = (char **)(stack_end + 1);801 *envp = (char **)(stack_end + argc + 2);802 } else {803# endif // !SANITIZER_GO804 static const int kMaxArgv = 2000, kMaxEnvp = 2000;805 ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);806 ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);807# if !SANITIZER_GO808 }809# endif // !SANITIZER_GO810# endif // SANITIZER_HAIKU811}812 813char **GetArgv() {814 char **argv, **envp;815 GetArgsAndEnv(&argv, &envp);816 return argv;817}818 819char **GetEnviron() {820 char **argv, **envp;821 GetArgsAndEnv(&argv, &envp);822 return envp;823}824 825# if !SANITIZER_SOLARIS826void FutexWait(atomic_uint32_t *p, u32 cmp) {827# if SANITIZER_FREEBSD828 _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0);829# elif SANITIZER_NETBSD || SANITIZER_HAIKU830 sched_yield(); /* No userspace futex-like synchronization */831# else832 internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0);833# endif834}835 836void FutexWake(atomic_uint32_t *p, u32 count) {837# if SANITIZER_FREEBSD838 _umtx_op(p, UMTX_OP_WAKE, count, 0, 0);839# elif SANITIZER_NETBSD || SANITIZER_HAIKU840 /* No userspace futex-like synchronization */841# else842 internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);843# endif844}845 846# endif // !SANITIZER_SOLARIS847 848// ----------------- sanitizer_linux.h849// The actual size of this structure is specified by d_reclen.850// Note that getdents64 uses a different structure format. We only provide the851// 32-bit syscall here.852# if SANITIZER_NETBSD853// Not used854# else855struct linux_dirent {856# if SANITIZER_X32 || SANITIZER_LINUX857 u64 d_ino;858 u64 d_off;859# else860 unsigned long d_ino;861 unsigned long d_off;862# endif863 unsigned short d_reclen;864# if SANITIZER_LINUX865 unsigned char d_type;866# endif867 char d_name[256];868};869# endif870 871# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU872// Syscall wrappers.873uptr internal_ptrace(int request, int pid, void *addr, void *data) {874 return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,875 (uptr)data);876}877 878uptr internal_waitpid(int pid, int *status, int options) {879 return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,880 0 /* rusage */);881}882 883uptr internal_getpid() { return internal_syscall(SYSCALL(getpid)); }884 885uptr internal_getppid() { return internal_syscall(SYSCALL(getppid)); }886 887int internal_dlinfo(void *handle, int request, void *p) {888# if SANITIZER_FREEBSD889 return dlinfo(handle, request, p);890# else891 UNIMPLEMENTED();892# endif893}894 895uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {896# if SANITIZER_FREEBSD897 return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);898# elif SANITIZER_LINUX899 return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);900# else901 return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);902# endif903}904 905uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {906 return internal_syscall(SYSCALL(lseek), fd, offset, whence);907}908 909# if SANITIZER_LINUX910uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {911 return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);912}913# if defined(__x86_64__)914# include <asm/unistd_64.h>915// Currently internal_arch_prctl() is only needed on x86_64.916uptr internal_arch_prctl(int option, uptr arg2) {917 return internal_syscall(__NR_arch_prctl, option, arg2);918}919# endif920# endif921 922uptr internal_sigaltstack(const void *ss, void *oss) {923 return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);924}925 926extern "C" pid_t __fork(void);927 928int internal_fork() {929# if SANITIZER_LINUX930# if SANITIZER_S390931 return internal_syscall(SYSCALL(clone), 0, SIGCHLD);932# elif SANITIZER_SPARC933 // The clone syscall interface on SPARC differs massively from the rest,934 // so fall back to __fork.935 return __fork();936# else937 return internal_syscall(SYSCALL(clone), SIGCHLD, 0);938# endif939# else940 return internal_syscall(SYSCALL(fork));941# endif942}943 944# if SANITIZER_FREEBSD945int internal_sysctl(const int *name, unsigned int namelen, void *oldp,946 uptr *oldlenp, const void *newp, uptr newlen) {947 return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp,948 (size_t *)oldlenp, newp, (size_t)newlen);949}950 951int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,952 const void *newp, uptr newlen) {953 // Note: this function can be called during startup, so we need to avoid954 // calling any interceptable functions. On FreeBSD >= 1300045 sysctlbyname()955 // is a real syscall, but for older versions it calls sysctlnametomib()956 // followed by sysctl(). To avoid calling the intercepted version and957 // asserting if this happens during startup, call the real sysctlnametomib()958 // followed by internal_sysctl() if the syscall is not available.959# ifdef SYS___sysctlbyname960 return internal_syscall(SYSCALL(__sysctlbyname), sname,961 internal_strlen(sname), oldp, (size_t *)oldlenp, newp,962 (size_t)newlen);963# else964 static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr;965 if (!real_sysctlnametomib)966 real_sysctlnametomib =967 (decltype(sysctlnametomib) *)dlsym(RTLD_NEXT, "sysctlnametomib");968 CHECK(real_sysctlnametomib);969 970 int oid[CTL_MAXNAME];971 size_t len = CTL_MAXNAME;972 if (real_sysctlnametomib(sname, oid, &len) == -1)973 return (-1);974 return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen);975# endif976}977# endif978 979# if SANITIZER_LINUX980# define SA_RESTORER 0x04000000981// Doesn't set sa_restorer if the caller did not set it, so use with caution982//(see below).983int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {984 __sanitizer_kernel_sigaction_t k_act, k_oldact;985 internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));986 internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));987 const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;988 __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;989 if (u_act) {990 k_act.handler = u_act->handler;991 k_act.sigaction = u_act->sigaction;992 internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,993 sizeof(__sanitizer_kernel_sigset_t));994 // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).995 k_act.sa_flags = u_act->sa_flags | SA_RESTORER;996 // FIXME: most often sa_restorer is unset, however the kernel requires it997 // to point to a valid signal restorer that calls the rt_sigreturn syscall.998 // If sa_restorer passed to the kernel is NULL, the program may crash upon999 // signal delivery or fail to unwind the stack in the signal handler.1000 // libc implementation of sigaction() passes its own restorer to1001 // rt_sigaction, so we need to do the same (we'll need to reimplement the1002 // restorers; for x86_64 the restorer address can be obtained from1003 // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).1004# if !SANITIZER_ANDROID || !SANITIZER_MIPS321005 k_act.sa_restorer = u_act->sa_restorer;1006# endif1007 }1008 1009 uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,1010 (uptr)(u_act ? &k_act : nullptr),1011 (uptr)(u_oldact ? &k_oldact : nullptr),1012 (uptr)sizeof(__sanitizer_kernel_sigset_t));1013 1014 if ((result == 0) && u_oldact) {1015 u_oldact->handler = k_oldact.handler;1016 u_oldact->sigaction = k_oldact.sigaction;1017 internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,1018 sizeof(__sanitizer_kernel_sigset_t));1019 u_oldact->sa_flags = k_oldact.sa_flags;1020# if !SANITIZER_ANDROID || !SANITIZER_MIPS321021 u_oldact->sa_restorer = k_oldact.sa_restorer;1022# endif1023 }1024 return result;1025}1026# endif // SANITIZER_LINUX1027 1028uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,1029 __sanitizer_sigset_t *oldset) {1030# if SANITIZER_FREEBSD1031 return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);1032# else1033 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;1034 __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;1035 return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)k_set,1036 (uptr)k_oldset, sizeof(__sanitizer_kernel_sigset_t));1037# endif1038}1039 1040void internal_sigfillset(__sanitizer_sigset_t *set) {1041 internal_memset(set, 0xff, sizeof(*set));1042}1043 1044void internal_sigemptyset(__sanitizer_sigset_t *set) {1045 internal_memset(set, 0, sizeof(*set));1046}1047 1048# if SANITIZER_LINUX1049void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {1050 signum -= 1;1051 CHECK_GE(signum, 0);1052 CHECK_LT(signum, sizeof(*set) * 8);1053 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;1054 const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);1055 const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);1056 k_set->sig[idx] &= ~((uptr)1 << bit);1057}1058 1059bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {1060 signum -= 1;1061 CHECK_GE(signum, 0);1062 CHECK_LT(signum, sizeof(*set) * 8);1063 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;1064 const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);1065 const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);1066 return k_set->sig[idx] & ((uptr)1 << bit);1067}1068# elif SANITIZER_FREEBSD1069uptr internal_procctl(int type, int id, int cmd, void *data) {1070 return internal_syscall(SYSCALL(procctl), type, id, cmd, data);1071}1072 1073void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {1074 sigset_t *rset = reinterpret_cast<sigset_t *>(set);1075 sigdelset(rset, signum);1076}1077 1078bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {1079 sigset_t *rset = reinterpret_cast<sigset_t *>(set);1080 return sigismember(rset, signum);1081}1082# endif1083# endif // !SANITIZER_SOLARIS1084 1085# if !SANITIZER_NETBSD && !SANITIZER_HAIKU1086// ThreadLister implementation.1087ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {1088 task_path_.AppendF("/proc/%d/task", pid);1089}1090 1091ThreadLister::Result ThreadLister::ListThreads(1092 InternalMmapVector<ThreadID> *threads) {1093 int descriptor = internal_open(task_path_.data(), O_RDONLY | O_DIRECTORY);1094 if (internal_iserror(descriptor)) {1095 Report("Can't open %s for reading.\n", task_path_.data());1096 return Error;1097 }1098 auto cleanup = at_scope_exit([&] { internal_close(descriptor); });1099 threads->clear();1100 1101 Result result = Ok;1102 for (bool first_read = true;; first_read = false) {1103 CHECK_GE(buffer_.size(), 4096);1104 uptr read = internal_getdents(1105 descriptor, (struct linux_dirent *)buffer_.data(), buffer_.size());1106 if (!read)1107 return result;1108 if (internal_iserror(read)) {1109 Report("Can't read directory entries from %s.\n", task_path_.data());1110 return Error;1111 }1112 1113 for (uptr begin = (uptr)buffer_.data(), end = begin + read; begin < end;) {1114 struct linux_dirent *entry = (struct linux_dirent *)begin;1115 begin += entry->d_reclen;1116 if (entry->d_ino == 1) {1117 // Inode 1 is for bad blocks and also can be a reason for early return.1118 // Should be emitted if kernel tried to output terminating thread.1119 // See proc_task_readdir implementation in Linux.1120 result = Incomplete;1121 }1122 if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9')1123 threads->push_back(internal_atoll(entry->d_name));1124 }1125 1126 // Now we are going to detect short-read or early EOF. In such cases Linux1127 // can return inconsistent list with missing alive threads.1128 // Code will just remember that the list can be incomplete but it will1129 // continue reads to return as much as possible.1130 if (!first_read) {1131 // The first one was a short-read by definition.1132 result = Incomplete;1133 } else if (read > buffer_.size() - 1024) {1134 // Read was close to the buffer size. So double the size and assume the1135 // worst.1136 buffer_.resize(buffer_.size() * 2);1137 result = Incomplete;1138 } else if (!threads->empty() && !IsAlive(threads->back())) {1139 // Maybe Linux early returned from read on terminated thread (!pid_alive)1140 // and failed to restore read position.1141 // See next_tid and proc_task_instantiate in Linux.1142 result = Incomplete;1143 }1144 }1145}1146 1147const char *ThreadLister::LoadStatus(ThreadID tid) {1148 status_path_.clear();1149 status_path_.AppendF("%s/%llu/status", task_path_.data(), tid);1150 auto cleanup = at_scope_exit([&] {1151 // Resize back to capacity if it is downsized by `ReadFileToVector`.1152 buffer_.resize(buffer_.capacity());1153 });1154 if (!ReadFileToVector(status_path_.data(), &buffer_) || buffer_.empty())1155 return nullptr;1156 buffer_.push_back('\0');1157 return buffer_.data();1158}1159 1160bool ThreadLister::IsAlive(ThreadID tid) {1161 // /proc/%d/task/%d/status uses same call to detect alive threads as1162 // proc_task_readdir. See task_state implementation in Linux.1163 static const char kPrefix[] = "\nPPid:";1164 const char *status = LoadStatus(tid);1165 if (!status)1166 return false;1167 const char *field = internal_strstr(status, kPrefix);1168 if (!field)1169 return false;1170 field += internal_strlen(kPrefix);1171 return (int)internal_atoll(field) != 0;1172}1173 1174# endif1175 1176# if SANITIZER_WORDSIZE == 321177// Take care of unusable kernel area in top gigabyte.1178static uptr GetKernelAreaSize() {1179# if SANITIZER_LINUX && !SANITIZER_X321180 const uptr gbyte = 1UL << 30;1181 1182 // Firstly check if there are writable segments1183 // mapped to top gigabyte (e.g. stack).1184 MemoryMappingLayout proc_maps(/*cache_enabled*/ true);1185 if (proc_maps.Error())1186 return 0;1187 MemoryMappedSegment segment;1188 while (proc_maps.Next(&segment)) {1189 if ((segment.end >= 3 * gbyte) && segment.IsWritable())1190 return 0;1191 }1192 1193# if !SANITIZER_ANDROID1194 // Even if nothing is mapped, top Gb may still be accessible1195 // if we are running on 64-bit kernel.1196 // Uname may report misleading results if personality type1197 // is modified (e.g. under schroot) so check this as well.1198 struct utsname uname_info;1199 int pers = personality(0xffffffffUL);1200 if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 &&1201 internal_strstr(uname_info.machine, "64"))1202 return 0;1203# endif // SANITIZER_ANDROID1204 1205 // Top gigabyte is reserved for kernel.1206 return gbyte;1207# else1208 return 0;1209# endif // SANITIZER_LINUX && !SANITIZER_X321210}1211# endif // SANITIZER_WORDSIZE == 321212 1213uptr GetMaxVirtualAddress() {1214# if SANITIZER_NETBSD && defined(__x86_64__)1215 return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)1216# elif SANITIZER_WORDSIZE == 641217# if defined(__powerpc64__) || defined(__aarch64__) || \1218 defined(__loongarch__) || SANITIZER_RISCV641219 // On PowerPC64 we have two different address space layouts: 44- and 46-bit.1220 // We somehow need to figure out which one we are using now and choose1221 // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.1222 // Note that with 'ulimit -s unlimited' the stack is moved away from the top1223 // of the address space, so simply checking the stack address is not enough.1224 // This should (does) work for both PowerPC64 Endian modes.1225 // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.1226 // loongarch64 also has multiple address space layouts: default is 47-bit.1227 // RISC-V 64 also has multiple address space layouts: 39, 48 and 57-bit.1228 return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;1229# elif SANITIZER_MIPS641230 return (1ULL << 40) - 1; // 0x000000ffffffffffUL;1231# elif defined(__s390x__)1232 return (1ULL << 53) - 1; // 0x001fffffffffffffUL;1233# elif defined(__sparc__)1234 return ~(uptr)0;1235# else1236 return (1ULL << 47) - 1; // 0x00007fffffffffffUL;1237# endif1238# else // SANITIZER_WORDSIZE == 321239# if defined(__s390__)1240 return (1ULL << 31) - 1; // 0x7fffffff;1241# else1242 return (1ULL << 32) - 1; // 0xffffffff;1243# endif1244# endif // SANITIZER_WORDSIZE1245}1246 1247uptr GetMaxUserVirtualAddress() {1248 uptr addr = GetMaxVirtualAddress();1249# if SANITIZER_WORDSIZE == 32 && !defined(__s390__)1250 if (!common_flags()->full_address_space)1251 addr -= GetKernelAreaSize();1252 CHECK_LT(reinterpret_cast<uptr>(&addr), addr);1253# endif1254 return addr;1255}1256 1257# if !SANITIZER_ANDROID || defined(__aarch64__)1258uptr GetPageSize() {1259# if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \1260 defined(EXEC_PAGESIZE)1261 return EXEC_PAGESIZE;1262# elif SANITIZER_FREEBSD || SANITIZER_NETBSD1263 // Use sysctl as sysconf can trigger interceptors internally.1264 int pz = 0;1265 uptr pzl = sizeof(pz);1266 int mib[2] = {CTL_HW, HW_PAGESIZE};1267 int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);1268 CHECK_EQ(rv, 0);1269 return (uptr)pz;1270# elif SANITIZER_USE_GETAUXVAL1271# if SANITIZER_ANDROID && __ANDROID_API__ < 351272 // The 16 KB page size was introduced in Android 15 (API level 35), while1273 // earlier versions of Android always used a 4 KB page size.1274 // We are checking the weak definition of `strerrorname_np` (introduced in API1275 // level 35) because some earlier API levels crashed when1276 // `getauxval(AT_PAGESZ)` was called from the `.preinit_array`.1277 if (!strerrorname_np)1278 return 4096;1279# endif1280 1281 return getauxval(AT_PAGESZ);1282# else1283 return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.1284# endif1285}1286# endif1287 1288uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {1289# if SANITIZER_HAIKU1290 int cookie = 0;1291 image_info info;1292 const char *argv0 = "<UNKNOWN>";1293 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {1294 if (info.type != B_APP_IMAGE)1295 continue;1296 argv0 = info.name;1297 break;1298 }1299 internal_strncpy(buf, argv0, buf_len);1300 return internal_strlen(buf);1301# elif SANITIZER_SOLARIS1302 const char *default_module_name = getexecname();1303 CHECK_NE(default_module_name, NULL);1304 return internal_snprintf(buf, buf_len, "%s", default_module_name);1305# else1306# if SANITIZER_FREEBSD || SANITIZER_NETBSD1307# if SANITIZER_FREEBSD1308 const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};1309# else1310 const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};1311# endif1312 const char *default_module_name = "kern.proc.pathname";1313 uptr Size = buf_len;1314 bool IsErr =1315 (internal_sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);1316 int readlink_error = IsErr ? errno : 0;1317 uptr module_name_len = Size;1318# else1319 const char *default_module_name = "/proc/self/exe";1320 uptr module_name_len = internal_readlink(default_module_name, buf, buf_len);1321 int readlink_error;1322 bool IsErr = internal_iserror(module_name_len, &readlink_error);1323# endif1324 if (IsErr) {1325 // We can't read binary name for some reason, assume it's unknown.1326 Report(1327 "WARNING: reading executable name failed with errno %d, "1328 "some stack frames may not be symbolized\n",1329 readlink_error);1330 module_name_len =1331 internal_snprintf(buf, buf_len, "%s", default_module_name);1332 CHECK_LT(module_name_len, buf_len);1333 }1334 return module_name_len;1335# endif1336}1337 1338uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {1339# if SANITIZER_LINUX1340 char *tmpbuf;1341 uptr tmpsize;1342 uptr tmplen;1343 if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,1344 1024 * 1024)) {1345 internal_strncpy(buf, tmpbuf, buf_len);1346 UnmapOrDie(tmpbuf, tmpsize);1347 return internal_strlen(buf);1348 }1349# endif1350 return ReadBinaryName(buf, buf_len);1351}1352 1353// Match full names of the form /path/to/base_name{-,.}*1354bool LibraryNameIs(const char *full_name, const char *base_name) {1355 const char *name = full_name;1356 // Strip path.1357 while (*name != '\0') name++;1358 while (name > full_name && *name != '/') name--;1359 if (*name == '/')1360 name++;1361 uptr base_name_length = internal_strlen(base_name);1362 if (internal_strncmp(name, base_name, base_name_length))1363 return false;1364 return (name[base_name_length] == '-' || name[base_name_length] == '.');1365}1366 1367# if !SANITIZER_ANDROID && !SANITIZER_HAIKU1368// Call cb for each region mapped by map.1369void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {1370 CHECK_NE(map, nullptr);1371# if !SANITIZER_FREEBSD && !SANITIZER_HAIKU1372 typedef ElfW(Phdr) Elf_Phdr;1373 typedef ElfW(Ehdr) Elf_Ehdr;1374# endif // !SANITIZER_FREEBSD1375 char *base = (char *)map->l_addr;1376 Elf_Ehdr *ehdr = (Elf_Ehdr *)base;1377 char *phdrs = base + ehdr->e_phoff;1378 char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;1379 1380 // Find the segment with the minimum base so we can "relocate" the p_vaddr1381 // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC1382 // objects have a non-zero base.1383 uptr preferred_base = (uptr)-1;1384 for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {1385 Elf_Phdr *phdr = (Elf_Phdr *)iter;1386 if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)1387 preferred_base = (uptr)phdr->p_vaddr;1388 }1389 1390 // Compute the delta from the real base to get a relocation delta.1391 sptr delta = (uptr)base - preferred_base;1392 // Now we can figure out what the loader really mapped.1393 for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {1394 Elf_Phdr *phdr = (Elf_Phdr *)iter;1395 if (phdr->p_type == PT_LOAD) {1396 uptr seg_start = phdr->p_vaddr + delta;1397 uptr seg_end = seg_start + phdr->p_memsz;1398 // None of these values are aligned. We consider the ragged edges of the1399 // load command as defined, since they are mapped from the file.1400 seg_start = RoundDownTo(seg_start, GetPageSizeCached());1401 seg_end = RoundUpTo(seg_end, GetPageSizeCached());1402 cb((void *)seg_start, seg_end - seg_start);1403 }1404 }1405}1406# endif1407 1408# if SANITIZER_LINUX1409# if defined(__x86_64__)1410// We cannot use glibc's clone wrapper, because it messes with the child1411// task's TLS. It writes the PID and TID of the child task to its thread1412// descriptor, but in our case the child task shares the thread descriptor with1413// the parent (because we don't know how to allocate a new thread1414// descriptor to keep glibc happy). So the stock version of clone(), when1415// used with CLONE_VM, would end up corrupting the parent's thread descriptor.1416uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1417 int *parent_tidptr, void *newtls, int *child_tidptr) {1418 long long res;1419 if (!fn || !child_stack)1420 return -EINVAL;1421 CHECK_EQ(0, (uptr)child_stack % 16);1422 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);1423 ((unsigned long long *)child_stack)[0] = (uptr)fn;1424 ((unsigned long long *)child_stack)[1] = (uptr)arg;1425 register void *r8 __asm__("r8") = newtls;1426 register int *r10 __asm__("r10") = child_tidptr;1427 __asm__ __volatile__(1428 /* %rax = syscall(%rax = SYSCALL(clone),1429 * %rdi = flags,1430 * %rsi = child_stack,1431 * %rdx = parent_tidptr,1432 * %r8 = new_tls,1433 * %r10 = child_tidptr)1434 */1435 "syscall\n"1436 1437 /* if (%rax != 0)1438 * return;1439 */1440 "testq %%rax,%%rax\n"1441 "jnz 1f\n"1442 1443 /* In the child. Terminate unwind chain. */1444 // XXX: We should also terminate the CFI unwind chain1445 // here. Unfortunately clang 3.2 doesn't support the1446 // necessary CFI directives, so we skip that part.1447 "xorq %%rbp,%%rbp\n"1448 1449 /* Call "fn(arg)". */1450 "popq %%rax\n"1451 "popq %%rdi\n"1452 "call *%%rax\n"1453 1454 /* Call _exit(%rax). */1455 "movq %%rax,%%rdi\n"1456 "movq %2,%%rax\n"1457 "syscall\n"1458 1459 /* Return to parent. */1460 "1:\n"1461 : "=a"(res)1462 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), "S"(child_stack), "D"(flags),1463 "d"(parent_tidptr), "r"(r8), "r"(r10)1464 : "memory", "r11", "rcx");1465 return res;1466}1467# elif defined(__mips__)1468uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1469 int *parent_tidptr, void *newtls, int *child_tidptr) {1470 long long res;1471 if (!fn || !child_stack)1472 return -EINVAL;1473 CHECK_EQ(0, (uptr)child_stack % 16);1474 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);1475 ((unsigned long long *)child_stack)[0] = (uptr)fn;1476 ((unsigned long long *)child_stack)[1] = (uptr)arg;1477 register void *a3 __asm__("$7") = newtls;1478 register int *a4 __asm__("$8") = child_tidptr;1479 // We don't have proper CFI directives here because it requires alot of code1480 // for very marginal benefits.1481 __asm__ __volatile__(1482 /* $v0 = syscall($v0 = __NR_clone,1483 * $a0 = flags,1484 * $a1 = child_stack,1485 * $a2 = parent_tidptr,1486 * $a3 = new_tls,1487 * $a4 = child_tidptr)1488 */1489 ".cprestore 16;\n"1490 "move $4,%1;\n"1491 "move $5,%2;\n"1492 "move $6,%3;\n"1493 "move $7,%4;\n"1494 /* Store the fifth argument on stack1495 * if we are using 32-bit abi.1496 */1497# if SANITIZER_WORDSIZE == 321498 "lw %5,16($29);\n"1499# else1500 "move $8,%5;\n"1501# endif1502 "li $2,%6;\n"1503 "syscall;\n"1504 1505 /* if ($v0 != 0)1506 * return;1507 */1508 "bnez $2,1f;\n"1509 1510 /* Call "fn(arg)". */1511# if SANITIZER_WORDSIZE == 321512# ifdef __BIG_ENDIAN__1513 "lw $25,4($29);\n"1514 "lw $4,12($29);\n"1515# else1516 "lw $25,0($29);\n"1517 "lw $4,8($29);\n"1518# endif1519# else1520 "ld $25,0($29);\n"1521 "ld $4,8($29);\n"1522# endif1523 "jal $25;\n"1524 1525 /* Call _exit($v0). */1526 "move $4,$2;\n"1527 "li $2,%7;\n"1528 "syscall;\n"1529 1530 /* Return to parent. */1531 "1:\n"1532 : "=r"(res)1533 : "r"(flags), "r"(child_stack), "r"(parent_tidptr), "r"(a3), "r"(a4),1534 "i"(__NR_clone), "i"(__NR_exit)1535 : "memory", "$29");1536 return res;1537}1538# elif SANITIZER_RISCV641539uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1540 int *parent_tidptr, void *newtls, int *child_tidptr) {1541 if (!fn || !child_stack)1542 return -EINVAL;1543 1544 CHECK_EQ(0, (uptr)child_stack % 16);1545 1546 register int res __asm__("a0");1547 register int __flags __asm__("a0") = flags;1548 register void *__stack __asm__("a1") = child_stack;1549 register int *__ptid __asm__("a2") = parent_tidptr;1550 register void *__tls __asm__("a3") = newtls;1551 register int *__ctid __asm__("a4") = child_tidptr;1552 register int (*__fn)(void *) __asm__("a5") = fn;1553 register void *__arg __asm__("a6") = arg;1554 register int nr_clone __asm__("a7") = __NR_clone;1555 1556 __asm__ __volatile__(1557 "ecall\n"1558 1559 /* if (a0 != 0)1560 * return a0;1561 */1562 "bnez a0, 1f\n"1563 1564 // In the child, now. Call "fn(arg)".1565 "mv a0, a6\n"1566 "jalr a5\n"1567 1568 // Call _exit(a0).1569 "addi a7, zero, %9\n"1570 "ecall\n"1571 "1:\n"1572 1573 : "=r"(res)1574 : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__tls), "r"(__ctid),1575 "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)1576 : "memory");1577 return res;1578}1579# elif defined(__aarch64__)1580uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1581 int *parent_tidptr, void *newtls, int *child_tidptr) {1582 register long long res __asm__("x0");1583 if (!fn || !child_stack)1584 return -EINVAL;1585 CHECK_EQ(0, (uptr)child_stack % 16);1586 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);1587 ((unsigned long long *)child_stack)[0] = (uptr)fn;1588 ((unsigned long long *)child_stack)[1] = (uptr)arg;1589 1590 register int (*__fn)(void *) __asm__("x0") = fn;1591 register void *__stack __asm__("x1") = child_stack;1592 register int __flags __asm__("x2") = flags;1593 register void *__arg __asm__("x3") = arg;1594 register int *__ptid __asm__("x4") = parent_tidptr;1595 register void *__tls __asm__("x5") = newtls;1596 register int *__ctid __asm__("x6") = child_tidptr;1597 1598 __asm__ __volatile__(1599 "mov x0,x2\n" /* flags */1600 "mov x2,x4\n" /* ptid */1601 "mov x3,x5\n" /* tls */1602 "mov x4,x6\n" /* ctid */1603 "mov x8,%9\n" /* clone */1604 1605 "svc 0x0\n"1606 1607 /* if (%r0 != 0)1608 * return %r0;1609 */1610 "cmp x0, #0\n"1611 "bne 1f\n"1612 1613 /* In the child, now. Call "fn(arg)". */1614 "ldp x1, x0, [sp], #16\n"1615 "blr x1\n"1616 1617 /* Call _exit(%r0). */1618 "mov x8, %10\n"1619 "svc 0x0\n"1620 "1:\n"1621 1622 : "=r"(res)1623 : "i"(-EINVAL), "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),1624 "r"(__ptid), "r"(__tls), "r"(__ctid), "i"(__NR_clone), "i"(__NR_exit)1625 : "x30", "memory");1626 return res;1627}1628# elif SANITIZER_LOONGARCH641629uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1630 int *parent_tidptr, void *newtls, int *child_tidptr) {1631 if (!fn || !child_stack)1632 return -EINVAL;1633 1634 CHECK_EQ(0, (uptr)child_stack % 16);1635 1636 register int res __asm__("$a0");1637 register int __flags __asm__("$a0") = flags;1638 register void *__stack __asm__("$a1") = child_stack;1639 register int *__ptid __asm__("$a2") = parent_tidptr;1640 register int *__ctid __asm__("$a3") = child_tidptr;1641 register void *__tls __asm__("$a4") = newtls;1642 register int (*__fn)(void *) __asm__("$a5") = fn;1643 register void *__arg __asm__("$a6") = arg;1644 register int nr_clone __asm__("$a7") = __NR_clone;1645 1646 __asm__ __volatile__(1647 "syscall 0\n"1648 1649 // if ($a0 != 0)1650 // return $a0;1651 "bnez $a0, 1f\n"1652 1653 // In the child, now. Call "fn(arg)".1654 "move $a0, $a6\n"1655 "jirl $ra, $a5, 0\n"1656 1657 // Call _exit($a0).1658 "addi.d $a7, $zero, %9\n"1659 "syscall 0\n"1660 1661 "1:\n"1662 1663 : "=r"(res)1664 : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__ctid), "r"(__tls),1665 "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)1666 : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",1667 "$t8");1668 return res;1669}1670# elif defined(__powerpc64__)1671uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1672 int *parent_tidptr, void *newtls, int *child_tidptr) {1673 long long res;1674// Stack frame structure.1675# if SANITIZER_PPC64V11676 // Back chain == 0 (SP + 112)1677 // Frame (112 bytes):1678 // Parameter save area (SP + 48), 8 doublewords1679 // TOC save area (SP + 40)1680 // Link editor doubleword (SP + 32)1681 // Compiler doubleword (SP + 24)1682 // LR save area (SP + 16)1683 // CR save area (SP + 8)1684 // Back chain (SP + 0)1685# define FRAME_SIZE 1121686# define FRAME_TOC_SAVE_OFFSET 401687# elif SANITIZER_PPC64V21688 // Back chain == 0 (SP + 32)1689 // Frame (32 bytes):1690 // TOC save area (SP + 24)1691 // LR save area (SP + 16)1692 // CR save area (SP + 8)1693 // Back chain (SP + 0)1694# define FRAME_SIZE 321695# define FRAME_TOC_SAVE_OFFSET 241696# else1697# error "Unsupported PPC64 ABI"1698# endif1699 if (!fn || !child_stack)1700 return -EINVAL;1701 CHECK_EQ(0, (uptr)child_stack % 16);1702 1703 register int (*__fn)(void *) __asm__("r3") = fn;1704 register void *__cstack __asm__("r4") = child_stack;1705 register int __flags __asm__("r5") = flags;1706 register void *__arg __asm__("r6") = arg;1707 register int *__ptidptr __asm__("r7") = parent_tidptr;1708 register void *__newtls __asm__("r8") = newtls;1709 register int *__ctidptr __asm__("r9") = child_tidptr;1710 1711 __asm__ __volatile__(1712 /* fn and arg are saved across the syscall */1713 "mr 28, %5\n\t"1714 "mr 27, %8\n\t"1715 1716 /* syscall1717 r0 == __NR_clone1718 r3 == flags1719 r4 == child_stack1720 r5 == parent_tidptr1721 r6 == newtls1722 r7 == child_tidptr */1723 "mr 3, %7\n\t"1724 "mr 5, %9\n\t"1725 "mr 6, %10\n\t"1726 "mr 7, %11\n\t"1727 "li 0, %3\n\t"1728 "sc\n\t"1729 1730 /* Test if syscall was successful */1731 "cmpdi cr1, 3, 0\n\t"1732 "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"1733 "bne- cr1, 1f\n\t"1734 1735 /* Set up stack frame */1736 "li 29, 0\n\t"1737 "stdu 29, -8(1)\n\t"1738 "stdu 1, -%12(1)\n\t"1739 /* Do the function call */1740 "std 2, %13(1)\n\t"1741# if SANITIZER_PPC64V11742 "ld 0, 0(28)\n\t"1743 "ld 2, 8(28)\n\t"1744 "mtctr 0\n\t"1745# elif SANITIZER_PPC64V21746 "mr 12, 28\n\t"1747 "mtctr 12\n\t"1748# else1749# error "Unsupported PPC64 ABI"1750# endif1751 "mr 3, 27\n\t"1752 "bctrl\n\t"1753 "ld 2, %13(1)\n\t"1754 1755 /* Call _exit(r3) */1756 "li 0, %4\n\t"1757 "sc\n\t"1758 1759 /* Return to parent */1760 "1:\n\t"1761 "mr %0, 3\n\t"1762 : "=r"(res)1763 : "0"(-1), "i"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn),1764 "r"(__cstack), "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls),1765 "r"(__ctidptr), "i"(FRAME_SIZE), "i"(FRAME_TOC_SAVE_OFFSET)1766 : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");1767 return res;1768}1769# elif defined(__i386__)1770uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1771 int *parent_tidptr, void *newtls, int *child_tidptr) {1772 int res;1773 if (!fn || !child_stack)1774 return -EINVAL;1775 CHECK_EQ(0, (uptr)child_stack % 16);1776 child_stack = (char *)child_stack - 7 * sizeof(unsigned int);1777 ((unsigned int *)child_stack)[0] = (uptr)flags;1778 ((unsigned int *)child_stack)[1] = (uptr)0;1779 ((unsigned int *)child_stack)[2] = (uptr)fn;1780 ((unsigned int *)child_stack)[3] = (uptr)arg;1781 __asm__ __volatile__(1782 /* %eax = syscall(%eax = SYSCALL(clone),1783 * %ebx = flags,1784 * %ecx = child_stack,1785 * %edx = parent_tidptr,1786 * %esi = new_tls,1787 * %edi = child_tidptr)1788 */1789 1790 /* Obtain flags */1791 "movl (%%ecx), %%ebx\n"1792 /* Do the system call */1793 "pushl %%ebx\n"1794 "pushl %%esi\n"1795 "pushl %%edi\n"1796 /* Remember the flag value. */1797 "movl %%ebx, (%%ecx)\n"1798 "int $0x80\n"1799 "popl %%edi\n"1800 "popl %%esi\n"1801 "popl %%ebx\n"1802 1803 /* if (%eax != 0)1804 * return;1805 */1806 1807 "test %%eax,%%eax\n"1808 "jnz 1f\n"1809 1810 /* terminate the stack frame */1811 "xorl %%ebp,%%ebp\n"1812 /* Call FN. */1813 "call *%%ebx\n"1814# ifdef PIC1815 "call here\n"1816 "here:\n"1817 "popl %%ebx\n"1818 "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"1819# endif1820 /* Call exit */1821 "movl %%eax, %%ebx\n"1822 "movl %2, %%eax\n"1823 "int $0x80\n"1824 "1:\n"1825 : "=a"(res)1826 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), "c"(child_stack),1827 "d"(parent_tidptr), "S"(newtls), "D"(child_tidptr)1828 : "memory");1829 return res;1830}1831# elif defined(__arm__)1832uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,1833 int *parent_tidptr, void *newtls, int *child_tidptr) {1834 unsigned int res;1835 if (!fn || !child_stack)1836 return -EINVAL;1837 child_stack = (char *)child_stack - 2 * sizeof(unsigned int);1838 ((unsigned int *)child_stack)[0] = (uptr)fn;1839 ((unsigned int *)child_stack)[1] = (uptr)arg;1840 register int r0 __asm__("r0") = flags;1841 register void *r1 __asm__("r1") = child_stack;1842 register int *r2 __asm__("r2") = parent_tidptr;1843 register void *r3 __asm__("r3") = newtls;1844 register int *r4 __asm__("r4") = child_tidptr;1845 register int r7 __asm__("r7") = __NR_clone;1846 1847# if __ARM_ARCH > 4 || defined(__ARM_ARCH_4T__)1848# define ARCH_HAS_BX1849# endif1850# if __ARM_ARCH > 41851# define ARCH_HAS_BLX1852# endif1853 1854# ifdef ARCH_HAS_BX1855# ifdef ARCH_HAS_BLX1856# define BLX(R) "blx " #R "\n"1857# else1858# define BLX(R) "mov lr, pc; bx " #R "\n"1859# endif1860# else1861# define BLX(R) "mov lr, pc; mov pc," #R "\n"1862# endif1863 1864 __asm__ __volatile__(1865 /* %r0 = syscall(%r7 = SYSCALL(clone),1866 * %r0 = flags,1867 * %r1 = child_stack,1868 * %r2 = parent_tidptr,1869 * %r3 = new_tls,1870 * %r4 = child_tidptr)1871 */1872 1873 /* Do the system call */1874 "swi 0x0\n"1875 1876 /* if (%r0 != 0)1877 * return %r0;1878 */1879 "cmp r0, #0\n"1880 "bne 1f\n"1881 1882 /* In the child, now. Call "fn(arg)". */1883 "ldr r0, [sp, #4]\n"1884 "ldr ip, [sp], #8\n" BLX(ip)1885 /* Call _exit(%r0). */1886 "mov r7, %7\n"1887 "swi 0x0\n"1888 "1:\n"1889 "mov %0, r0\n"1890 : "=r"(res)1891 : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7), "i"(__NR_exit)1892 : "memory");1893 return res;1894}1895# endif1896# endif // SANITIZER_LINUX1897 1898# if SANITIZER_LINUX1899int internal_uname(struct utsname *buf) {1900 return internal_syscall(SYSCALL(uname), buf);1901}1902# endif1903 1904static HandleSignalMode GetHandleSignalModeImpl(int signum) {1905 switch (signum) {1906 case SIGABRT:1907 return common_flags()->handle_abort;1908 case SIGILL:1909 return common_flags()->handle_sigill;1910 case SIGTRAP:1911 return common_flags()->handle_sigtrap;1912 case SIGFPE:1913 return common_flags()->handle_sigfpe;1914 case SIGSEGV:1915 return common_flags()->handle_segv;1916 case SIGBUS:1917 return common_flags()->handle_sigbus;1918 }1919 return kHandleSignalNo;1920}1921 1922HandleSignalMode GetHandleSignalMode(int signum) {1923 HandleSignalMode result = GetHandleSignalModeImpl(signum);1924 if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)1925 return kHandleSignalExclusive;1926 return result;1927}1928 1929# if !SANITIZER_GO1930void *internal_start_thread(void *(*func)(void *arg), void *arg) {1931 if (&internal_pthread_create == 0)1932 return nullptr;1933 // Start the thread with signals blocked, otherwise it can steal user signals.1934 ScopedBlockSignals block(nullptr);1935 void *th;1936 internal_pthread_create(&th, nullptr, func, arg);1937 return th;1938}1939 1940void internal_join_thread(void *th) {1941 if (&internal_pthread_join)1942 internal_pthread_join(th, nullptr);1943}1944# else1945void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }1946 1947void internal_join_thread(void *th) {}1948# endif1949 1950# if SANITIZER_LINUX && defined(__aarch64__)1951// Android headers in the older NDK releases miss this definition.1952struct __sanitizer_esr_context {1953 struct _aarch64_ctx head;1954 uint64_t esr;1955};1956 1957static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {1958 static const u32 kEsrMagic = 0x45535201;1959 u8 *aux = reinterpret_cast<u8 *>(ucontext->uc_mcontext.__reserved);1960 while (true) {1961 _aarch64_ctx *ctx = (_aarch64_ctx *)aux;1962 if (ctx->size == 0)1963 break;1964 if (ctx->magic == kEsrMagic) {1965 *esr = ((__sanitizer_esr_context *)ctx)->esr;1966 return true;1967 }1968 aux += ctx->size;1969 }1970 return false;1971}1972# elif SANITIZER_FREEBSD && defined(__aarch64__)1973// FreeBSD doesn't provide ESR in the ucontext.1974static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { return false; }1975# endif1976 1977using Context = ucontext_t;1978 1979SignalContext::WriteFlag SignalContext::GetWriteFlag() const {1980 Context *ucontext = (Context *)context;1981# if defined(__x86_64__) || defined(__i386__)1982# if !SANITIZER_HAIKU1983 static const uptr PF_WRITE = 1U << 1;1984# endif1985# if SANITIZER_FREEBSD1986 uptr err = ucontext->uc_mcontext.mc_err;1987# elif SANITIZER_NETBSD1988 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];1989# elif SANITIZER_HAIKU1990 uptr err = ucontext->uc_mcontext.r13;1991# elif SANITIZER_SOLARIS && defined(__i386__)1992 const int Err = 13;1993 uptr err = ucontext->uc_mcontext.gregs[Err];1994# else1995 uptr err = ucontext->uc_mcontext.gregs[REG_ERR];1996# endif // SANITIZER_FREEBSD1997 return err & PF_WRITE ? Write : Read;1998# elif defined(__mips__)1999 uint32_t *exception_source;2000 uint32_t faulty_instruction;2001 uint32_t op_code;2002 2003 exception_source = (uint32_t *)ucontext->uc_mcontext.pc;2004 faulty_instruction = (uint32_t)(*exception_source);2005 2006 op_code = (faulty_instruction >> 26) & 0x3f;2007 2008 // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions.2009 switch (op_code) {2010 case 0x28: // sb2011 case 0x29: // sh2012 case 0x2b: // sw2013 case 0x3f: // sd2014# if __mips_isa_rev < 62015 case 0x2c: // sdl2016 case 0x2d: // sdr2017 case 0x2a: // swl2018 case 0x2e: // swr2019# endif2020 return SignalContext::Write;2021 2022 case 0x20: // lb2023 case 0x24: // lbu2024 case 0x21: // lh2025 case 0x25: // lhu2026 case 0x23: // lw2027 case 0x27: // lwu2028 case 0x37: // ld2029# if __mips_isa_rev < 62030 case 0x1a: // ldl2031 case 0x1b: // ldr2032 case 0x22: // lwl2033 case 0x26: // lwr2034# endif2035 return SignalContext::Read;2036# if __mips_isa_rev == 62037 case 0x3b: // pcrel2038 op_code = (faulty_instruction >> 19) & 0x3;2039 switch (op_code) {2040 case 0x1: // lwpc2041 case 0x2: // lwupc2042 return SignalContext::Read;2043 }2044# endif2045 }2046 return SignalContext::Unknown;2047# elif defined(__arm__)2048 static const uptr FSR_WRITE = 1U << 11;2049 uptr fsr = ucontext->uc_mcontext.error_code;2050 return fsr & FSR_WRITE ? Write : Read;2051# elif defined(__aarch64__)2052 static const u64 ESR_ELx_WNR = 1U << 6;2053 u64 esr;2054 if (!Aarch64GetESR(ucontext, &esr))2055 return Unknown;2056 return esr & ESR_ELx_WNR ? Write : Read;2057# elif defined(__loongarch__)2058 // In the musl environment, the Linux kernel uapi sigcontext.h is not2059 // included in signal.h. To avoid missing the SC_ADDRERR_{RD,WR} macros,2060 // copy them here. The LoongArch Linux kernel uapi is already stable,2061 // so there's no need to worry about the value changing.2062# ifndef SC_ADDRERR_RD2063 // Address error was due to memory load2064# define SC_ADDRERR_RD (1 << 30)2065# endif2066# ifndef SC_ADDRERR_WR2067 // Address error was due to memory store2068# define SC_ADDRERR_WR (1 << 31)2069# endif2070 u32 flags = ucontext->uc_mcontext.__flags;2071 if (flags & SC_ADDRERR_RD)2072 return SignalContext::Read;2073 if (flags & SC_ADDRERR_WR)2074 return SignalContext::Write;2075 return SignalContext::Unknown;2076# elif defined(__sparc__)2077 // Decode the instruction to determine the access type.2078 // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).2079# if SANITIZER_SOLARIS2080 uptr pc = ucontext->uc_mcontext.gregs[REG_PC];2081# else2082 // Historical BSDism here.2083 struct sigcontext *scontext = (struct sigcontext *)context;2084# if defined(__arch64__)2085 uptr pc = scontext->sigc_regs.tpc;2086# else2087 uptr pc = scontext->si_regs.pc;2088# endif2089# endif2090 u32 instr = *(u32 *)pc;2091 return (instr >> 21) & 1 ? Write : Read;2092# elif defined(__riscv)2093# if SANITIZER_FREEBSD2094 unsigned long pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;2095# else2096 unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];2097# endif2098 unsigned faulty_instruction = *(uint16_t *)pc;2099 2100# if defined(__riscv_compressed)2101 if ((faulty_instruction & 0x3) != 0x3) { // it's a compressed instruction2102 // set op_bits to the instruction bits [1, 0, 15, 14, 13]2103 unsigned op_bits =2104 ((faulty_instruction & 0x3) << 3) | (faulty_instruction >> 13);2105 unsigned rd = faulty_instruction & 0xF80; // bits 7-11, inclusive2106 switch (op_bits) {2107 case 0b10'010: // c.lwsp (rd != x0)2108# if __riscv_xlen == 642109 case 0b10'011: // c.ldsp (rd != x0)2110# endif2111 return rd ? SignalContext::Read : SignalContext::Unknown;2112 case 0b00'010: // c.lw2113# if __riscv_flen >= 32 && __riscv_xlen == 322114 case 0b10'011: // c.flwsp2115# endif2116# if __riscv_flen >= 32 || __riscv_xlen == 642117 case 0b00'011: // c.flw / c.ld2118# endif2119# if __riscv_flen == 642120 case 0b00'001: // c.fld2121 case 0b10'001: // c.fldsp2122# endif2123 return SignalContext::Read;2124 case 0b00'110: // c.sw2125 case 0b10'110: // c.swsp2126# if __riscv_flen >= 32 || __riscv_xlen == 642127 case 0b00'111: // c.fsw / c.sd2128 case 0b10'111: // c.fswsp / c.sdsp2129# endif2130# if __riscv_flen == 642131 case 0b00'101: // c.fsd2132 case 0b10'101: // c.fsdsp2133# endif2134 return SignalContext::Write;2135 default:2136 return SignalContext::Unknown;2137 }2138 }2139# endif2140 2141 unsigned opcode = faulty_instruction & 0x7f; // lower 7 bits2142 unsigned funct3 = (faulty_instruction >> 12) & 0x7; // bits 12-14, inclusive2143 switch (opcode) {2144 case 0b0000011: // loads2145 switch (funct3) {2146 case 0b000: // lb2147 case 0b001: // lh2148 case 0b010: // lw2149# if __riscv_xlen == 642150 case 0b011: // ld2151# endif2152 case 0b100: // lbu2153 case 0b101: // lhu2154 return SignalContext::Read;2155 default:2156 return SignalContext::Unknown;2157 }2158 case 0b0100011: // stores2159 switch (funct3) {2160 case 0b000: // sb2161 case 0b001: // sh2162 case 0b010: // sw2163# if __riscv_xlen == 642164 case 0b011: // sd2165# endif2166 return SignalContext::Write;2167 default:2168 return SignalContext::Unknown;2169 }2170# if __riscv_flen >= 322171 case 0b0000111: // floating-point loads2172 switch (funct3) {2173 case 0b010: // flw2174# if __riscv_flen == 642175 case 0b011: // fld2176# endif2177 return SignalContext::Read;2178 default:2179 return SignalContext::Unknown;2180 }2181 case 0b0100111: // floating-point stores2182 switch (funct3) {2183 case 0b010: // fsw2184# if __riscv_flen == 642185 case 0b011: // fsd2186# endif2187 return SignalContext::Write;2188 default:2189 return SignalContext::Unknown;2190 }2191# endif2192 default:2193 return SignalContext::Unknown;2194 }2195# else2196 (void)ucontext;2197 return Unknown; // FIXME: Implement.2198# endif2199}2200 2201bool SignalContext::IsTrueFaultingAddress() const {2202 auto si = static_cast<const siginfo_t *>(siginfo);2203 // SIGSEGV signals without a true fault address have si_code set to 128.2204 return si->si_signo == SIGSEGV && si->si_code != 128;2205}2206 2207UNUSED2208static const char *RegNumToRegName(int reg) {2209 switch (reg) {2210# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD2211# if defined(__x86_64__)2212# if SANITIZER_NETBSD2213# define REG_RAX _REG_RAX2214# define REG_RBX _REG_RBX2215# define REG_RCX _REG_RCX2216# define REG_RDX _REG_RDX2217# define REG_RDI _REG_RDI2218# define REG_RSI _REG_RSI2219# define REG_RBP _REG_RBP2220# define REG_RSP _REG_RSP2221# define REG_R8 _REG_R82222# define REG_R9 _REG_R92223# define REG_R10 _REG_R102224# define REG_R11 _REG_R112225# define REG_R12 _REG_R122226# define REG_R13 _REG_R132227# define REG_R14 _REG_R142228# define REG_R15 _REG_R152229# endif2230 case REG_RAX:2231 return "rax";2232 case REG_RBX:2233 return "rbx";2234 case REG_RCX:2235 return "rcx";2236 case REG_RDX:2237 return "rdx";2238 case REG_RDI:2239 return "rdi";2240 case REG_RSI:2241 return "rsi";2242 case REG_RBP:2243 return "rbp";2244 case REG_RSP:2245 return "rsp";2246 case REG_R8:2247 return "r8";2248 case REG_R9:2249 return "r9";2250 case REG_R10:2251 return "r10";2252 case REG_R11:2253 return "r11";2254 case REG_R12:2255 return "r12";2256 case REG_R13:2257 return "r13";2258 case REG_R14:2259 return "r14";2260 case REG_R15:2261 return "r15";2262# elif defined(__i386__)2263# if SANITIZER_NETBSD2264# define REG_EAX _REG_EAX2265# define REG_EBX _REG_EBX2266# define REG_ECX _REG_ECX2267# define REG_EDX _REG_EDX2268# define REG_EDI _REG_EDI2269# define REG_ESI _REG_ESI2270# define REG_EBP _REG_EBP2271# define REG_ESP _REG_ESP2272# endif2273 case REG_EAX:2274 return "eax";2275 case REG_EBX:2276 return "ebx";2277 case REG_ECX:2278 return "ecx";2279 case REG_EDX:2280 return "edx";2281 case REG_EDI:2282 return "edi";2283 case REG_ESI:2284 return "esi";2285 case REG_EBP:2286 return "ebp";2287 case REG_ESP:2288 return "esp";2289# elif defined(__arm__)2290# ifdef MAKE_CASE2291# undef MAKE_CASE2292# endif2293# define REG_STR(reg) #reg2294# define MAKE_CASE(N) \2295 case REG_R##N: \2296 return REG_STR(r##N)2297 MAKE_CASE(0);2298 MAKE_CASE(1);2299 MAKE_CASE(2);2300 MAKE_CASE(3);2301 MAKE_CASE(4);2302 MAKE_CASE(5);2303 MAKE_CASE(6);2304 MAKE_CASE(7);2305 MAKE_CASE(8);2306 MAKE_CASE(9);2307 MAKE_CASE(10);2308 MAKE_CASE(11);2309 MAKE_CASE(12);2310 case REG_R13:2311 return "sp";2312 case REG_R14:2313 return "lr";2314 case REG_R15:2315 return "pc";2316# elif defined(__aarch64__)2317# define REG_STR(reg) #reg2318# define MAKE_CASE(N) \2319 case N: \2320 return REG_STR(x##N)2321 MAKE_CASE(0);2322 MAKE_CASE(1);2323 MAKE_CASE(2);2324 MAKE_CASE(3);2325 MAKE_CASE(4);2326 MAKE_CASE(5);2327 MAKE_CASE(6);2328 MAKE_CASE(7);2329 MAKE_CASE(8);2330 MAKE_CASE(9);2331 MAKE_CASE(10);2332 MAKE_CASE(11);2333 MAKE_CASE(12);2334 MAKE_CASE(13);2335 MAKE_CASE(14);2336 MAKE_CASE(15);2337 MAKE_CASE(16);2338 MAKE_CASE(17);2339 MAKE_CASE(18);2340 MAKE_CASE(19);2341 MAKE_CASE(20);2342 MAKE_CASE(21);2343 MAKE_CASE(22);2344 MAKE_CASE(23);2345 MAKE_CASE(24);2346 MAKE_CASE(25);2347 MAKE_CASE(26);2348 MAKE_CASE(27);2349 MAKE_CASE(28);2350 case 29:2351 return "fp";2352 case 30:2353 return "lr";2354 case 31:2355 return "sp";2356# endif2357# endif // SANITIZER_LINUX && SANITIZER_GLIBC2358 default:2359 return NULL;2360 }2361 return NULL;2362}2363 2364# if ((SANITIZER_LINUX && SANITIZER_GLIBC) || SANITIZER_NETBSD) && \2365 (defined(__arm__) || defined(__aarch64__))2366static uptr GetArmRegister(ucontext_t *ctx, int RegNum) {2367 switch (RegNum) {2368# if defined(__arm__) && !SANITIZER_NETBSD2369# ifdef MAKE_CASE2370# undef MAKE_CASE2371# endif2372# define MAKE_CASE(N) \2373 case REG_R##N: \2374 return ctx->uc_mcontext.arm_r##N2375 MAKE_CASE(0);2376 MAKE_CASE(1);2377 MAKE_CASE(2);2378 MAKE_CASE(3);2379 MAKE_CASE(4);2380 MAKE_CASE(5);2381 MAKE_CASE(6);2382 MAKE_CASE(7);2383 MAKE_CASE(8);2384 MAKE_CASE(9);2385 MAKE_CASE(10);2386 case REG_R11:2387 return ctx->uc_mcontext.arm_fp;2388 case REG_R12:2389 return ctx->uc_mcontext.arm_ip;2390 case REG_R13:2391 return ctx->uc_mcontext.arm_sp;2392 case REG_R14:2393 return ctx->uc_mcontext.arm_lr;2394 case REG_R15:2395 return ctx->uc_mcontext.arm_pc;2396# elif defined(__aarch64__)2397# if SANITIZER_LINUX2398 case 0 ... 30:2399 return ctx->uc_mcontext.regs[RegNum];2400 case 31:2401 return ctx->uc_mcontext.sp;2402# elif SANITIZER_NETBSD2403 case 0 ... 31:2404 return ctx->uc_mcontext.__gregs[RegNum];2405# endif2406# endif2407 default:2408 return 0;2409 }2410 return 0;2411}2412# endif // SANITIZER_LINUX && SANITIZER_GLIBC && (defined(__arm__) ||2413 // defined(__aarch64__))2414 2415UNUSED2416static void DumpSingleReg(ucontext_t *ctx, int RegNum) {2417 const char *RegName = RegNumToRegName(RegNum);2418# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD2419# if defined(__x86_64__)2420 Printf("%s%s = 0x%016llx ", internal_strlen(RegName) == 2 ? " " : "",2421 RegName,2422# if SANITIZER_LINUX2423 ctx->uc_mcontext.gregs[RegNum]2424# elif SANITIZER_NETBSD2425 ctx->uc_mcontext.__gregs[RegNum]2426# endif2427 );2428# elif defined(__i386__)2429 Printf("%s = 0x%08x ", RegName,2430# if SANITIZER_LINUX2431 ctx->uc_mcontext.gregs[RegNum]2432# elif SANITIZER_NETBSD2433 ctx->uc_mcontext.__gregs[RegNum]2434# endif2435 );2436# elif defined(__arm__)2437 Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,2438 GetArmRegister(ctx, RegNum));2439# elif defined(__aarch64__)2440 Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,2441 GetArmRegister(ctx, RegNum));2442# else2443 (void)RegName;2444# endif2445# else2446 (void)RegName;2447# endif2448}2449 2450void SignalContext::DumpAllRegisters(void *context) {2451 ucontext_t *ucontext = (ucontext_t *)context;2452# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD2453# if defined(__x86_64__)2454 Report("Register values:\n");2455 DumpSingleReg(ucontext, REG_RAX);2456 DumpSingleReg(ucontext, REG_RBX);2457 DumpSingleReg(ucontext, REG_RCX);2458 DumpSingleReg(ucontext, REG_RDX);2459 Printf("\n");2460 DumpSingleReg(ucontext, REG_RDI);2461 DumpSingleReg(ucontext, REG_RSI);2462 DumpSingleReg(ucontext, REG_RBP);2463 DumpSingleReg(ucontext, REG_RSP);2464 Printf("\n");2465 DumpSingleReg(ucontext, REG_R8);2466 DumpSingleReg(ucontext, REG_R9);2467 DumpSingleReg(ucontext, REG_R10);2468 DumpSingleReg(ucontext, REG_R11);2469 Printf("\n");2470 DumpSingleReg(ucontext, REG_R12);2471 DumpSingleReg(ucontext, REG_R13);2472 DumpSingleReg(ucontext, REG_R14);2473 DumpSingleReg(ucontext, REG_R15);2474 Printf("\n");2475# elif defined(__i386__)2476 // Duplication of this report print is caused by partial support2477 // of register values dumping. In case of unsupported yet architecture let's2478 // avoid printing 'Register values:' without actual values in the following2479 // output.2480 Report("Register values:\n");2481 DumpSingleReg(ucontext, REG_EAX);2482 DumpSingleReg(ucontext, REG_EBX);2483 DumpSingleReg(ucontext, REG_ECX);2484 DumpSingleReg(ucontext, REG_EDX);2485 Printf("\n");2486 DumpSingleReg(ucontext, REG_EDI);2487 DumpSingleReg(ucontext, REG_ESI);2488 DumpSingleReg(ucontext, REG_EBP);2489 DumpSingleReg(ucontext, REG_ESP);2490 Printf("\n");2491# elif defined(__arm__) && !SANITIZER_NETBSD2492 Report("Register values:\n");2493 DumpSingleReg(ucontext, REG_R0);2494 DumpSingleReg(ucontext, REG_R1);2495 DumpSingleReg(ucontext, REG_R2);2496 DumpSingleReg(ucontext, REG_R3);2497 Printf("\n");2498 DumpSingleReg(ucontext, REG_R4);2499 DumpSingleReg(ucontext, REG_R5);2500 DumpSingleReg(ucontext, REG_R6);2501 DumpSingleReg(ucontext, REG_R7);2502 Printf("\n");2503 DumpSingleReg(ucontext, REG_R8);2504 DumpSingleReg(ucontext, REG_R9);2505 DumpSingleReg(ucontext, REG_R10);2506 DumpSingleReg(ucontext, REG_R11);2507 Printf("\n");2508 DumpSingleReg(ucontext, REG_R12);2509 DumpSingleReg(ucontext, REG_R13);2510 DumpSingleReg(ucontext, REG_R14);2511 DumpSingleReg(ucontext, REG_R15);2512 Printf("\n");2513# elif defined(__aarch64__)2514 Report("Register values:\n");2515 for (int i = 0; i <= 31; ++i) {2516 DumpSingleReg(ucontext, i);2517 if (i % 4 == 3)2518 Printf("\n");2519 }2520# else2521 (void)ucontext;2522# endif2523# elif SANITIZER_FREEBSD2524# if defined(__x86_64__)2525 Report("Register values:\n");2526 Printf("rax = 0x%016lx ", ucontext->uc_mcontext.mc_rax);2527 Printf("rbx = 0x%016lx ", ucontext->uc_mcontext.mc_rbx);2528 Printf("rcx = 0x%016lx ", ucontext->uc_mcontext.mc_rcx);2529 Printf("rdx = 0x%016lx ", ucontext->uc_mcontext.mc_rdx);2530 Printf("\n");2531 Printf("rdi = 0x%016lx ", ucontext->uc_mcontext.mc_rdi);2532 Printf("rsi = 0x%016lx ", ucontext->uc_mcontext.mc_rsi);2533 Printf("rbp = 0x%016lx ", ucontext->uc_mcontext.mc_rbp);2534 Printf("rsp = 0x%016lx ", ucontext->uc_mcontext.mc_rsp);2535 Printf("\n");2536 Printf(" r8 = 0x%016lx ", ucontext->uc_mcontext.mc_r8);2537 Printf(" r9 = 0x%016lx ", ucontext->uc_mcontext.mc_r9);2538 Printf("r10 = 0x%016lx ", ucontext->uc_mcontext.mc_r10);2539 Printf("r11 = 0x%016lx ", ucontext->uc_mcontext.mc_r11);2540 Printf("\n");2541 Printf("r12 = 0x%016lx ", ucontext->uc_mcontext.mc_r12);2542 Printf("r13 = 0x%016lx ", ucontext->uc_mcontext.mc_r13);2543 Printf("r14 = 0x%016lx ", ucontext->uc_mcontext.mc_r14);2544 Printf("r15 = 0x%016lx ", ucontext->uc_mcontext.mc_r15);2545 Printf("\n");2546# elif defined(__i386__)2547 Report("Register values:\n");2548 Printf("eax = 0x%08x ", ucontext->uc_mcontext.mc_eax);2549 Printf("ebx = 0x%08x ", ucontext->uc_mcontext.mc_ebx);2550 Printf("ecx = 0x%08x ", ucontext->uc_mcontext.mc_ecx);2551 Printf("edx = 0x%08x ", ucontext->uc_mcontext.mc_edx);2552 Printf("\n");2553 Printf("edi = 0x%08x ", ucontext->uc_mcontext.mc_edi);2554 Printf("esi = 0x%08x ", ucontext->uc_mcontext.mc_esi);2555 Printf("ebp = 0x%08x ", ucontext->uc_mcontext.mc_ebp);2556 Printf("esp = 0x%08x ", ucontext->uc_mcontext.mc_esp);2557 Printf("\n");2558# else2559 (void)ucontext;2560# endif2561# else2562 (void)ucontext;2563# endif2564 // FIXME: Implement this for other OSes and architectures.2565}2566 2567static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {2568# if SANITIZER_NETBSD2569 // This covers all NetBSD architectures2570 ucontext_t *ucontext = (ucontext_t *)context;2571 *pc = _UC_MACHINE_PC(ucontext);2572 *bp = _UC_MACHINE_FP(ucontext);2573 *sp = _UC_MACHINE_SP(ucontext);2574# elif defined(__arm__)2575 ucontext_t *ucontext = (ucontext_t *)context;2576 *pc = ucontext->uc_mcontext.arm_pc;2577 *bp = ucontext->uc_mcontext.arm_fp;2578 *sp = ucontext->uc_mcontext.arm_sp;2579# elif defined(__aarch64__)2580# if SANITIZER_FREEBSD2581 ucontext_t *ucontext = (ucontext_t *)context;2582 *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr;2583 *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29];2584 *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;2585# else2586 ucontext_t *ucontext = (ucontext_t *)context;2587 *pc = ucontext->uc_mcontext.pc;2588 *bp = ucontext->uc_mcontext.regs[29];2589 *sp = ucontext->uc_mcontext.sp;2590# endif2591# elif defined(__hppa__)2592 ucontext_t *ucontext = (ucontext_t *)context;2593 *pc = ucontext->uc_mcontext.sc_iaoq[0];2594 /* GCC uses %r3 whenever a frame pointer is needed. */2595 *bp = ucontext->uc_mcontext.sc_gr[3];2596 *sp = ucontext->uc_mcontext.sc_gr[30];2597# elif defined(__x86_64__)2598# if SANITIZER_FREEBSD2599 ucontext_t *ucontext = (ucontext_t *)context;2600 *pc = ucontext->uc_mcontext.mc_rip;2601 *bp = ucontext->uc_mcontext.mc_rbp;2602 *sp = ucontext->uc_mcontext.mc_rsp;2603# elif SANITIZER_HAIKU2604 ucontext_t *ucontext = (ucontext_t *)context;2605 *pc = ucontext->uc_mcontext.rip;2606 *bp = ucontext->uc_mcontext.rbp;2607 *sp = ucontext->uc_mcontext.rsp;2608# else2609 ucontext_t *ucontext = (ucontext_t *)context;2610 *pc = ucontext->uc_mcontext.gregs[REG_RIP];2611 *bp = ucontext->uc_mcontext.gregs[REG_RBP];2612 *sp = ucontext->uc_mcontext.gregs[REG_RSP];2613# endif2614# elif defined(__i386__)2615# if SANITIZER_FREEBSD2616 ucontext_t *ucontext = (ucontext_t *)context;2617 *pc = ucontext->uc_mcontext.mc_eip;2618 *bp = ucontext->uc_mcontext.mc_ebp;2619 *sp = ucontext->uc_mcontext.mc_esp;2620# else2621 ucontext_t *ucontext = (ucontext_t *)context;2622# if SANITIZER_SOLARIS2623 /* Use the numeric values: the symbolic ones are undefined by llvm2624 include/llvm/Support/Solaris.h. */2625# ifndef REG_EIP2626# define REG_EIP 14 // REG_PC2627# endif2628# ifndef REG_EBP2629# define REG_EBP 6 // REG_FP2630# endif2631# ifndef REG_UESP2632# define REG_UESP 17 // REG_SP2633# endif2634# endif2635 *pc = ucontext->uc_mcontext.gregs[REG_EIP];2636 *bp = ucontext->uc_mcontext.gregs[REG_EBP];2637 *sp = ucontext->uc_mcontext.gregs[REG_UESP];2638# endif2639# elif defined(__powerpc__) || defined(__powerpc64__)2640# if SANITIZER_FREEBSD2641 ucontext_t *ucontext = (ucontext_t *)context;2642 *pc = ucontext->uc_mcontext.mc_srr0;2643 *sp = ucontext->uc_mcontext.mc_frame[1];2644 *bp = ucontext->uc_mcontext.mc_frame[31];2645# else2646 ucontext_t *ucontext = (ucontext_t *)context;2647 *pc = ucontext->uc_mcontext.regs->nip;2648 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];2649 // The powerpc{,64}-linux ABIs do not specify r31 as the frame2650 // pointer, but GCC always uses r31 when we need a frame pointer.2651 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];2652# endif2653# elif defined(__sparc__)2654# if defined(__arch64__) || defined(__sparcv9)2655# define STACK_BIAS 20472656# else2657# define STACK_BIAS 02658# endif2659# if SANITIZER_SOLARIS2660 ucontext_t *ucontext = (ucontext_t *)context;2661 *pc = ucontext->uc_mcontext.gregs[REG_PC];2662 *sp = ucontext->uc_mcontext.gregs[REG_SP] + STACK_BIAS;2663 // Avoid SEGV when dereferencing sp on stack overflow with non-faulting load.2664 // This requires a SPARC V9 CPU. Cannot use #ASI_PNF here: only supported2665 // since clang-19.2666# if defined(__sparcv9)2667 asm("ldxa [%[fp]] 0x82, %[bp]"2668# else2669 asm("lduwa [%[fp]] 0x82, %[bp]"2670# endif2671 : [bp] "=r"(*bp)2672 : [fp] "r"(&((struct frame *)*sp)->fr_savfp));2673 if (*bp)2674 *bp += STACK_BIAS;2675# else2676 // Historical BSDism here.2677 struct sigcontext *scontext = (struct sigcontext *)context;2678# if defined(__arch64__)2679 *pc = scontext->sigc_regs.tpc;2680 *sp = scontext->sigc_regs.u_regs[14] + STACK_BIAS;2681# else2682 *pc = scontext->si_regs.pc;2683 *sp = scontext->si_regs.u_regs[14];2684# endif2685 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;2686# endif2687# elif defined(__mips__)2688 ucontext_t *ucontext = (ucontext_t *)context;2689 *pc = ucontext->uc_mcontext.pc;2690 *bp = ucontext->uc_mcontext.gregs[30];2691 *sp = ucontext->uc_mcontext.gregs[29];2692# elif defined(__s390__)2693 ucontext_t *ucontext = (ucontext_t *)context;2694# if defined(__s390x__)2695 *pc = ucontext->uc_mcontext.psw.addr;2696# else2697 *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;2698# endif2699 *bp = ucontext->uc_mcontext.gregs[11];2700 *sp = ucontext->uc_mcontext.gregs[15];2701# elif defined(__riscv)2702 ucontext_t *ucontext = (ucontext_t *)context;2703# if SANITIZER_FREEBSD2704 *pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;2705 *bp = ucontext->uc_mcontext.mc_gpregs.gp_s[0];2706 *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;2707# else2708 *pc = ucontext->uc_mcontext.__gregs[REG_PC];2709 *bp = ucontext->uc_mcontext.__gregs[REG_S0];2710 *sp = ucontext->uc_mcontext.__gregs[REG_SP];2711# endif2712# elif defined(__hexagon__)2713 ucontext_t *ucontext = (ucontext_t *)context;2714 *pc = ucontext->uc_mcontext.pc;2715 *bp = ucontext->uc_mcontext.r30;2716 *sp = ucontext->uc_mcontext.r29;2717# elif defined(__loongarch__)2718 ucontext_t *ucontext = (ucontext_t *)context;2719 *pc = ucontext->uc_mcontext.__pc;2720 *bp = ucontext->uc_mcontext.__gregs[22];2721 *sp = ucontext->uc_mcontext.__gregs[3];2722# else2723# error "Unsupported arch"2724# endif2725}2726 2727void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }2728 2729void InitializePlatformEarly() { InitTlsSize(); }2730 2731void CheckASLR() {2732# if SANITIZER_NETBSD2733 int mib[3];2734 int paxflags;2735 uptr len = sizeof(paxflags);2736 2737 mib[0] = CTL_PROC;2738 mib[1] = internal_getpid();2739 mib[2] = PROC_PID_PAXFLAGS;2740 2741 if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {2742 Printf("sysctl failed\n");2743 Die();2744 }2745 2746 if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)) {2747 Printf(2748 "This sanitizer is not compatible with enabled ASLR.\n"2749 "To disable ASLR, please run \"paxctl +a %s\" and try again.\n",2750 GetArgv()[0]);2751 Die();2752 }2753# elif SANITIZER_FREEBSD2754 int aslr_status;2755 int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status);2756 if (UNLIKELY(r == -1)) {2757 // We're making things less 'dramatic' here since2758 // the cmd is not necessarily guaranteed to be here2759 // just yet regarding FreeBSD release2760 return;2761 }2762 if ((aslr_status & PROC_ASLR_ACTIVE) != 0) {2763 VReport(1,2764 "This sanitizer is not compatible with enabled ASLR "2765 "and binaries compiled with PIE\n"2766 "ASLR will be disabled and the program re-executed.\n");2767 int aslr_ctl = PROC_ASLR_FORCE_DISABLE;2768 CHECK_NE(internal_procctl(P_PID, 0, PROC_ASLR_CTL, &aslr_ctl), -1);2769 ReExec();2770 }2771# elif SANITIZER_PPC64V22772 // Disable ASLR for Linux PPC64LE.2773 int old_personality = personality(0xffffffff);2774 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {2775 VReport(1,2776 "WARNING: Program is being run with address space layout "2777 "randomization (ASLR) enabled which prevents the thread and "2778 "memory sanitizers from working on powerpc64le.\n"2779 "ASLR will be disabled and the program re-executed.\n");2780 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);2781 ReExec();2782 }2783# else2784 // Do nothing2785# endif2786}2787 2788void CheckMPROTECT() {2789# if SANITIZER_NETBSD2790 int mib[3];2791 int paxflags;2792 uptr len = sizeof(paxflags);2793 2794 mib[0] = CTL_PROC;2795 mib[1] = internal_getpid();2796 mib[2] = PROC_PID_PAXFLAGS;2797 2798 if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {2799 Printf("sysctl failed\n");2800 Die();2801 }2802 2803 if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_MPROTECT)) {2804 Printf("This sanitizer is not compatible with enabled MPROTECT\n");2805 Die();2806 }2807# else2808 // Do nothing2809# endif2810}2811 2812void CheckNoDeepBind(const char *filename, int flag) {2813# ifdef RTLD_DEEPBIND2814 if (flag & RTLD_DEEPBIND) {2815 Report(2816 "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"2817 " which is incompatible with sanitizer runtime "2818 "(see https://github.com/google/sanitizers/issues/611 for details"2819 "). If you want to run %s library under sanitizers please remove "2820 "RTLD_DEEPBIND from dlopen flags.\n",2821 filename, filename);2822 Die();2823 }2824# endif2825}2826 2827uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,2828 uptr *largest_gap_found,2829 uptr *max_occupied_addr) {2830 UNREACHABLE("FindAvailableMemoryRange is not available");2831 return 0;2832}2833 2834bool GetRandom(void *buffer, uptr length, bool blocking) {2835 if (!buffer || !length || length > 256)2836 return false;2837# if SANITIZER_USE_GETENTROPY2838 uptr rnd = getentropy(buffer, length);2839 int rverrno = 0;2840 if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT)2841 return false;2842 else if (rnd == 0)2843 return true;2844# endif // SANITIZER_USE_GETENTROPY2845 2846# if SANITIZER_USE_GETRANDOM2847 static atomic_uint8_t skip_getrandom_syscall;2848 if (!atomic_load_relaxed(&skip_getrandom_syscall)) {2849 // Up to 256 bytes, getrandom will not be interrupted.2850 uptr res = internal_syscall(SYSCALL(getrandom), buffer, length,2851 blocking ? 0 : GRND_NONBLOCK);2852 int rverrno = 0;2853 if (internal_iserror(res, &rverrno) && rverrno == ENOSYS)2854 atomic_store_relaxed(&skip_getrandom_syscall, 1);2855 else if (res == length)2856 return true;2857 }2858# endif // SANITIZER_USE_GETRANDOM2859 // Up to 256 bytes, a read off /dev/urandom will not be interrupted.2860 // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.2861 uptr fd = internal_open("/dev/urandom", O_RDONLY);2862 if (internal_iserror(fd))2863 return false;2864 uptr res = internal_read(fd, buffer, length);2865 if (internal_iserror(res))2866 return false;2867 internal_close(fd);2868 return true;2869}2870 2871} // namespace __sanitizer2872 2873#endif2874