brintos

brintos / llvm-project-archived public Read only

0
0
Text · 89.9 KiB · 87a18b1 Raw
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, &currentset);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