sanitizer_linux.cc revision 7c9150579ed0278492f51cc8434b1d63a44b9bd1
1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_linux.cc ------------------------------------------------===//
2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//                     The LLVM Compiler Infrastructure
4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details.
7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
10ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// run-time libraries and implements linux-specific functions from
12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// sanitizer_libc.h.
13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h"
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX
17ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_allocator_internal.h"
196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h"
2194b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
22ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
236fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include "sanitizer_linux.h"
2493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
25a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
27a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany#include "sanitizer_stacktrace.h"
285ce93fc96ab5e2defd85890da63b51cc4c57a2afAlexander Potapenko#include "sanitizer_symbolizer.h"
29ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
31088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <asm/param.h>
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// access stat from asm/stat.h, without conflicting with definition in
3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// sys/stat.h, we use this trick.
3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64)
3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <sys/types.h>
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define stat kernel_stat
4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <asm/stat.h>
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef stat
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
45b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov#include <dlfcn.h>
4635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <errno.h>
47c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
486d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#if !SANITIZER_ANDROID
492e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne#include <link.h>
506d40a0a2ffa6735e45bd1d62c94ff725fd3e8b71Peter Collingbourne#endif
51e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
520969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
53ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany#include <sys/ptrace.h>
55e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
56c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
57ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
58e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
59ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <ucontext.h>
61ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
6235a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <sys/sysctl.h>
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <machine/atomic.h>
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FreeBSD 9.2 and 10.0.
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/umtx.h>
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesextern char **environ;  // provided by crt1
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if !SANITIZER_ANDROID
7535a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#include <sys/signal.h>
7635a7faf1fbfac678136e79d53824672dafb7d13eAlexey Samsonov#endif
77fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <android/log.h>
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/system_properties.h>
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
844bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov// <linux/time.h>
854bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstruct kernel_timeval {
864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_sec;
874bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  long tv_usec;
884bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov};
894bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
90fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukov// <linux/futex.h> is broken on some linux distributions.
91fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAIT = 0;
92fa5c41eddf77a3614da0f62044ebf741d86aeab7Dmitry Vyukovconst int FUTEX_WAKE = 1;
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
94ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Are we using 32-bit or 64-bit Linux syscalls?
965af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
9708bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64)
999d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
1009d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
1019d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
1029d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
1039d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
104ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
105ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && defined(__x86_64__)
1079578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_linux_x86_64.inc"
1089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#else
1099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
1109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#endif
1119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
112e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                   u64 offset) {
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
117e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          offset);
118ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // mmap2 specifies file offset in 4096-byte units.
12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(IsAligned(offset, 4096));
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                          offset / 4096);
123ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
124ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
125ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1269578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_munmap(void *addr, uptr length) {
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
1281f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
1291f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
1309578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(close), fd);
132a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
133a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags);
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
140ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
141ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
1429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          mode);
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
149ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
150ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
151a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
1523334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1553334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
156a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
157a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
158a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
1593334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines               count));
1623334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
163a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
164a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) {
1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  sptr res;
1677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
1687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar               (OFF_T)size));
1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;
1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
1732be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstatic void stat64_to_stat(struct stat64 *in, struct stat *out) {
1742be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  internal_memset(out, 0, sizeof(*out));
1752be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_dev = in->st_dev;
1762be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1772be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mode = in->st_mode;
1782be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_nlink = in->st_nlink;
1792be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_uid = in->st_uid;
1802be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_gid = in->st_gid;
1812be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_rdev = in->st_rdev;
1822be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_size = in->st_size;
1832be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blksize = in->st_blksize;
1842be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_blocks = in->st_blocks;
1852be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_atime = in->st_atime;
1862be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_mtime = in->st_mtime;
1872be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ctime = in->st_ctime;
1882be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  out->st_ino = in->st_ino;
1892be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov}
1902be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov#endif
1912be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__mips64)
19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
19486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_memset(out, 0, sizeof(*out));
19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_dev = in->st_dev;
19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
19786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mode = in->st_mode;
19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_nlink = in->st_nlink;
19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_uid = in->st_uid;
20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_gid = in->st_gid;
20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_rdev = in->st_rdev;
20286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_size = in->st_size;
20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blksize = in->st_blksize;
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_blocks = in->st_blocks;
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_atime = in->st_atime_nsec;
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_mtime = in->st_mtime_nsec;
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ctime = in->st_ctime_nsec;
20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  out->st_ino = in->st_ino;
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2129578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), path, buf);
2152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)buf, 0);
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
21986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# if defined(__mips64)
22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // For mips64, stat syscall fills buffer in the format of kernel_stat
22186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  struct kernel_stat kbuf;
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int res = internal_syscall(SYSCALL(stat), path, &kbuf);
22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  kernel_stat_to_stat(&kbuf, (struct stat *)buf);
22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# else
2262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines# endif
2284c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(stat64), path, &buf64);
2312be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2322be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2334c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2344c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2354c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2369578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
2372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), path, buf);
2392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         (uptr)buf, AT_SYMLINK_NOFOLLOW);
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
2444c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2452be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
2472be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2482be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2494c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2504c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2514c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2529578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
2554c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
2562be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat64 buf64;
2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
2582be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  stat64_to_stat(&buf64, (struct stat *)buf);
2592be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  return res;
2604c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
2614c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
2624c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
2638e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
264a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
2654c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
2664c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov    return -1;
2678e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
2688e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2698e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
2709578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
2712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(dup2), oldfd, newfd);
2752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2768e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
2778e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
278d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
2792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
2812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)path, (uptr)buf, bufsize);
2822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
2842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
285d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
286d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
2879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_unlink(const char *path) {
2882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
2902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(unlink), (uptr)path);
2922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) {
2962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
2972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
2982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)newpath);
2992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3026d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov}
3036d6ab9eeea4a99370d7ab18ce80eb96091e2cf3fDmitry Vyukov
3049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
3052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sched_yield));
3060969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
3070969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
308f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit), exitcode);
3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(exit_group), exitcode);
3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
314f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  Die();  // Unreachable.
315f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
316f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
3179578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_execve(const char *filename, char *const argv[],
3189578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                     char *const envp[]) {
3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)envp);
3219578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
3229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
323e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
32493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct stat st;
32686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3292be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  if (internal_stat(filename, &st))
33086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
33193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
33293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
33393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
33493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
33593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
336e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
3372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (uptr)pthread_self();
3392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(gettid));
3412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
342e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
343e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
3444bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovu64 NanoTime() {
3452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
3462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  timeval tv;
3472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
3485e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  kernel_timeval tv;
3492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
3505e7ba22755b994e4f6aaf8cc00773c4d1b8dbf07Peter Collingbourne  internal_memset(&tv, 0, sizeof(tv));
3512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
3524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
3534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
3544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
3556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// Like getenv, but reads env directly from /proc (on Linux) or parses the
3566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// 'environ' array (on FreeBSD) and does not use libc. This function should be
3576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// called first inside __asan_init.
3583dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
3596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
3606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (::environ != 0) {
3616a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    uptr NameLen = internal_strlen(name);
3626a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    for (char **Env = ::environ; *Env != 0; Env++) {
3636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
3646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        return (*Env) + NameLen + 1;
3656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    }
3666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
3676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return 0;  // Not found.
3686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#elif SANITIZER_LINUX
3693dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
3703dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
3713dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
3723dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
3733dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
3743dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
3753dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
3763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
3773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
3793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
3803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
3813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
3823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
3833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
3843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
3853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
3863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
3873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
3883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
3893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
3903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
3913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
3926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
3936a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#error "Unsupported platform"
3946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
3953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
3963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
397eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovextern "C" {
3983c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov  SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
399eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
400eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
40126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
40223709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbournestatic void ReadNullSepFileToArray(const char *path, char ***arr,
40323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne                                   int arr_size) {
40423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char *buff;
405d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
40623709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
40723709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
40823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[0] = buff;
40923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  int count, i;
41023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  for (count = 1, i = 1; ; i++) {
411d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
412d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
41323709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      (*arr)[count] = &buff[i+1];
41423709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
41523709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne      count++;
416d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
417d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
41823709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  (*arr)[count] = 0;
41923709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne}
42026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
42123709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne
42226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbournestatic void GetArgsAndEnv(char*** argv, char*** envp) {
42326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
42426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  if (&__libc_stack_end) {
42526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
42626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    uptr* stack_end = (uptr*)__libc_stack_end;
42726337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    int argc = *stack_end;
42826337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *argv = (char**)(stack_end + 1);
42926337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    *envp = (char**)(stack_end + argc + 2);
43026337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#if !SANITIZER_GO
43126337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  } else {
43226337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    static const int kMaxArgv = 2000, kMaxEnvp = 2000;
43326337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
43426337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne    ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
43526337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne  }
43626337b60b1d551c4744454edd8e5ef3c479e3467Peter Collingbourne#endif
437eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov}
438eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov
439eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanovvoid ReExec() {
44023709c9ad9ac7c45de288f5260403426bf932db7Peter Collingbourne  char **argv, **envp;
441eab061185ec0046d447b298a1dff84f028202a3cEvgeniy Stepanov  GetArgsAndEnv(&argv, &envp);
4429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr rv = internal_execve("/proc/self/exe", argv, envp);
4439578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int rverrno;
4449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  CHECK_EQ(internal_iserror(rv, &rverrno), true);
4459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  Printf("execve failed, errno %d\n", rverrno);
446f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  Die();
447d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
448d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
449f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovenum MutexState {
450f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxUnlocked = 0,
451f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxLocked = 1,
452f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  MtxSleeping = 2
453f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov};
454f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
45593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
45693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
45793af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
45893af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
459f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
46086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_EQ(owner_, 0);
461f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
462f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
463f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov    return;
4642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
4652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
4672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
4692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
471f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
472f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
473f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
474f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
475f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
47648526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov  CHECK_NE(v, MtxUnlocked);
4772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (v == MtxSleeping) {
4782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
4792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
4802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
4812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
4822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
484f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
485f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
486ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
487ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
488ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
489ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
490ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
4916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ----------------- sanitizer_linux.h
4926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// The actual size of this structure is specified by d_reclen.
4936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Note that getdents64 uses a different structure format. We only provide the
4946fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// 32-bit syscall here.
4956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanystruct linux_dirent {
4962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_X32
4972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_ino;
4982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 d_off;
4992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5006fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_ino;
5016fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned long      d_off;
5022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5036fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  unsigned short     d_reclen;
5046fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char               d_name[256];
5056fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany};
5066fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5076fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// Syscall wrappers.
5089578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_ptrace(int request, int pid, void *addr, void *data) {
5092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
5102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)data);
5119578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne}
5129578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
5139578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_waitpid(int pid, int *status, int options) {
5142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
515e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                          0 /* rusage */);
5166fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5176fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5189578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getpid() {
5192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getpid));
5206fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5216fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5229578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getppid() {
5232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getppid));
5246fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5256fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5269578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
5272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
5292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5349578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
5352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(lseek), fd, offset, whence);
5366fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5399578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
5402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
5416fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sigaltstack(const struct sigaltstack *ss,
5456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                         struct sigaltstack *oss) {
5462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
5472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
5482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() {
5502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
5512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
5522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
5532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(fork));
5542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
5556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
5566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
5572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
5587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#define SA_RESTORER 0x04000000
5592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Doesn't set sa_restorer, use with caution (see below).
5602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
5612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigaction_t k_act, k_oldact;
5622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
5632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
5646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
5652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
5662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (u_act) {
5672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.handler = u_act->handler;
5682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sigaction = u_act->sigaction;
5692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
5702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
5727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
5732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // FIXME: most often sa_restorer is unset, however the kernel requires it
5742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // to point to a valid signal restorer that calls the rt_sigreturn syscall.
5752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // If sa_restorer passed to the kernel is NULL, the program may crash upon
5762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // signal delivery or fail to unwind the stack in the signal handler.
5772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // libc implementation of sigaction() passes its own restorer to
5782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // rt_sigaction, so we need to do the same (we'll need to reimplement the
5792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // restorers; for x86_64 the restorer address can be obtained from
5802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
5812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    k_act.sa_restorer = u_act->sa_restorer;
5822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
5832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
5852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_act ? &k_act : NULL),
5862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)(u_oldact ? &k_oldact : NULL),
5872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (uptr)sizeof(__sanitizer_kernel_sigset_t));
5882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
5892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if ((result == 0) && u_oldact) {
5902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->handler = k_oldact.handler;
5912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sigaction = k_oldact.sigaction;
5922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
5932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    sizeof(__sanitizer_kernel_sigset_t));
5942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_flags = k_oldact.sa_flags;
5952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    u_oldact->sa_restorer = k_oldact.sa_restorer;
5962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
5972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return result;
5980f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
5992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6000f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
6022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __sanitizer_sigset_t *oldset) {
6032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD
6042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
6052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
6062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
6072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
6082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
6092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
6102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                          sizeof(__sanitizer_kernel_sigset_t));
6112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
6120f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6130f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigfillset(__sanitizer_sigset_t *set) {
6150f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  internal_memset(set, 0xff, sizeof(*set));
6160f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6170f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX
6192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
6200f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  signum -= 1;
6210f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_GE(signum, 0);
6220f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov  CHECK_LT(signum, sizeof(*set) * 8);
6232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
6242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
6252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
6262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  k_set->sig[idx] &= ~(1 << bit);
6270f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov}
6282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LINUX
6290f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov
6306fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany// ThreadLister implementation.
6316fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::ThreadLister(int pid)
6326fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  : pid_(pid),
6336fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    descriptor_(-1),
63410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    buffer_(4096),
6356fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_(true),
63610f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    entry_((struct linux_dirent *)buffer_.data()),
6376fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    bytes_read_(0) {
6386fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  char task_directory_path[80];
6396fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_snprintf(task_directory_path, sizeof(task_directory_path),
6406fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany                    "/proc/%d/task/", pid);
6419578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
6429578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(openrv)) {
6436fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6446fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't open /proc/%d/task for reading.\n", pid);
6456fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else {
6466fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = false;
6479578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    descriptor_ = openrv;
6486fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
6496fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6506fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6516fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyint ThreadLister::GetNextTID() {
6526fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  int tid = -1;
6536fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  do {
6546fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (error_)
6556fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6566fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
6576fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      return -1;
6586fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
6596fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany        entry_->d_name[0] <= '9') {
6606fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      // Found a valid tid.
6616fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany      tid = (int)internal_atoll(entry_->d_name);
6626fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    }
6636fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
6646fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } while (tid < 0);
6656fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return tid;
6666fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6676fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6686fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanyvoid ThreadLister::Reset() {
6696fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (error_ || descriptor_ < 0)
6706fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return;
6716fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  internal_lseek(descriptor_, 0, SEEK_SET);
6726fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6736fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6746fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya SerebryanyThreadLister::~ThreadLister() {
6756fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  if (descriptor_ >= 0)
6766fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    internal_close(descriptor_);
6776fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6786fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6796fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::error() { return error_; }
6806fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6816fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryanybool ThreadLister::GetDirectoryEntries() {
6826fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_GE(descriptor_, 0);
6836fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  CHECK_NE(error_, true);
6846fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  bytes_read_ = internal_getdents(descriptor_,
68510f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  (struct linux_dirent *)buffer_.data(),
68610f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov                                  buffer_.size());
6879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(bytes_read_)) {
6886fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    Report("Can't read directory entries from /proc/%d/task.\n", pid_);
6896fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    error_ = true;
6906fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6916fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  } else if (bytes_read_ == 0) {
6926fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany    return false;
6936fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  }
69410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  entry_ = (struct linux_dirent *)buffer_.data();
6956fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany  return true;
6966fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany}
6976fb47af2d2d305adbfc3d41bea589d1527a364a9Kostya Serebryany
6984df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() {
6992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
7004df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne  return EXEC_PAGESIZE;
701a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#else
702a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany  return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
703a8bc34e420d27c47560b0742cec295e40b0f430eKostya Serebryany#endif
7044df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne}
7054df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne
7067847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic char proc_self_exe_cache_str[kMaxPathLength];
7077847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic uptr proc_self_exe_cache_len = 0;
7087847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7097847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
7106a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (proc_self_exe_cache_len > 0) {
7116a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // If available, use the cached module name.
7126a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    uptr module_name_len =
7136a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        internal_snprintf(buf, buf_len, "%s", proc_self_exe_cache_str);
7146a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    CHECK_LT(module_name_len, buf_len);
7156a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    return module_name_len;
7166a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
7176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#if SANITIZER_FREEBSD
7186a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
7196a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  size_t Size = buf_len;
7206a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  bool IsErr = (sysctl(Mib, 4, buf, &Size, NULL, 0) != 0);
7216a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  int readlink_error = IsErr ? errno : 0;
7226a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr module_name_len = Size;
7236a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
7247847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  uptr module_name_len = internal_readlink(
7257847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov      "/proc/self/exe", buf, buf_len);
7267847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  int readlink_error;
7276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  bool IsErr = internal_iserror(module_name_len, &readlink_error);
7286a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
7296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (IsErr) {
7306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // We can't read /proc/self/exe for some reason, assume the name of the
7316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // binary is unknown.
7326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
7336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines           "some stack frames may not be symbolized\n", readlink_error);
7346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
7357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    CHECK_LT(module_name_len, buf_len);
7367847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
7377847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  return module_name_len;
7387847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
7397847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7407847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovvoid CacheBinaryName() {
7417847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  if (!proc_self_exe_cache_len) {
7427847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov    proc_self_exe_cache_len =
7437847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov        ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
7447847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov  }
7457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}
7467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov
7473de0086409d143a612a54a7a0ed809e286656188Sergey Matveev// Match full names of the form /path/to/base_name{-,.}*
7483de0086409d143a612a54a7a0ed809e286656188Sergey Matveevbool LibraryNameIs(const char *full_name, const char *base_name) {
7493de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  const char *name = full_name;
7503de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  // Strip path.
7513de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (*name != '\0') name++;
7523de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  while (name > full_name && *name != '/') name--;
7533de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (*name == '/') name++;
7543de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  uptr base_name_length = internal_strlen(base_name);
7553de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  if (internal_strncmp(name, base_name, base_name_length)) return false;
7563de0086409d143a612a54a7a0ed809e286656188Sergey Matveev  return (name[base_name_length] == '-' || name[base_name_length] == '.');
7573de0086409d143a612a54a7a0ed809e286656188Sergey Matveev}
7583de0086409d143a612a54a7a0ed809e286656188Sergey Matveev
759d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#if !SANITIZER_ANDROID
7602e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne// Call cb for each region mapped by map.
7612e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbournevoid ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(map, nullptr);
7632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD
7642e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Phdr) Elf_Phdr;
7652e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  typedef ElfW(Ehdr) Elf_Ehdr;
7662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // !SANITIZER_FREEBSD
7672e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *base = (char *)map->l_addr;
7682e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
7692e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs = base + ehdr->e_phoff;
7702e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
7712e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7722e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Find the segment with the minimum base so we can "relocate" the p_vaddr
7732e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // fields.  Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
7742e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // objects have a non-zero base.
775f50b0fc601aea71d9fb22f01a11c7e206c666edcPeter Collingbourne  uptr preferred_base = (uptr)-1;
7762e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7772e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7782e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
7792e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      preferred_base = (uptr)phdr->p_vaddr;
7802e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7812e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
7822e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Compute the delta from the real base to get a relocation delta.
7832e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  sptr delta = (uptr)base - preferred_base;
7842e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  // Now we can figure out what the loader really mapped.
7852e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
7862e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    Elf_Phdr *phdr = (Elf_Phdr *)iter;
7872e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    if (phdr->p_type == PT_LOAD) {
7882e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_start = phdr->p_vaddr + delta;
7892e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      uptr seg_end = seg_start + phdr->p_memsz;
7902e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // None of these values are aligned.  We consider the ragged edges of the
7912e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      // load command as defined, since they are mapped from the file.
7922e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_start = RoundDownTo(seg_start, GetPageSizeCached());
7932e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      seg_end = RoundUpTo(seg_end, GetPageSizeCached());
7942e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne      cb((void *)seg_start, seg_end - seg_start);
7952e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne    }
7962e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne  }
7972e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne}
798d054abef27369471e154ec5693949538c2fdffd9Evgeniy Stepanov#endif
7992e75ac983cb233daa1abfa35fb33d2bafffe2ab1Peter Collingbourne
8002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) && SANITIZER_LINUX
801cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// We cannot use glibc's clone wrapper, because it messes with the child
802cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// task's TLS. It writes the PID and TID of the child task to its thread
803cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor, but in our case the child task shares the thread descriptor with
804cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// the parent (because we don't know how to allocate a new thread
805cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// descriptor to keep glibc happy). So the stock version of clone(), when
806cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
807cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveevuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
808cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                    int *parent_tidptr, void *newtls, int *child_tidptr) {
809cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  long long res;
810cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  if (!fn || !child_stack)
811cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev    return -EINVAL;
812cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  CHECK_EQ(0, (uptr)child_stack % 16);
813e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
814e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[0] = (uptr)fn;
815e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  ((unsigned long long *)child_stack)[1] = (uptr)arg;
816e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register void *r8 __asm__("r8") = newtls;
817e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany  register int *r10 __asm__("r10") = child_tidptr;
818cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  __asm__ __volatile__(
8192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       /* %rax = syscall(%rax = SYSCALL(clone),
820cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdi = flags,
821cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rsi = child_stack,
822cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %rdx = parent_tidptr,
823cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r8  = new_tls,
824cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *                %r10 = child_tidptr)
825cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
826cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
827cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
828cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* if (%rax != 0)
829cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        *   return;
830cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                        */
831cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "testq  %%rax,%%rax\n"
832cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "jnz    1f\n"
833cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
834cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* In the child. Terminate unwind chain. */
835497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // XXX: We should also terminate the CFI unwind chain
836497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // here. Unfortunately clang 3.2 doesn't support the
837497ae56316cd05a0d539e0d6e065bbaee254aca3Sergey Matveev                       // necessary CFI directives, so we skip that part.
838cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "xorq   %%rbp,%%rbp\n"
839cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
840cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call "fn(arg)". */
841cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rax\n"
842cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "popq   %%rdi\n"
843cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "call   *%%rax\n"
844cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
845cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Call _exit(%rax). */
846cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %%rax,%%rdi\n"
847cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "movq   %2,%%rax\n"
848cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       "syscall\n"
849cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev
850cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       /* Return to parent. */
851cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                     "1:\n"
852cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                       : "=a" (res)
8532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                       : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
854cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "S"(child_stack),
855cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "D"(flags),
856cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev                         "d"(parent_tidptr),
857e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r8),
858e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                         "r"(r10)
859e041c6024b3ebf1365c0f99732fc69c607577571Kostya Serebryany                       : "rsp", "memory", "r11", "rcx");
860cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  return res;
861cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev}
86286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#elif defined(__mips__)
86386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// TODO(sagarthakur): clone function is to be rewritten in assembly.
86486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
86586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    int *parent_tidptr, void *newtls, int *child_tidptr) {
86686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return clone(fn, child_stack, flags, arg, parent_tidptr,
86786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines               newtls, child_tidptr);
86886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
8692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // defined(__x86_64__) && SANITIZER_LINUX
8702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID
872aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovstatic atomic_uint8_t android_log_initialized;
873aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
874aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanovvoid AndroidLogInit() {
875aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov  atomic_store(&android_log_initialized, 1, memory_order_release);
876aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov}
8772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This thing is not, strictly speaking, async signal safe, but it does not seem
8782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to cause any issues. Alternative is writing to log devices directly, but
8792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// their location and message format might change in the future, so we'd really
8802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// like to avoid that.
8812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AndroidLogWrite(const char *buffer) {
882aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov  if (!atomic_load(&android_log_initialized, memory_order_acquire))
883aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov    return;
884aafc5c8d620e24104f1ca340d97286b15a5cec90Evgeniy Stepanov
8852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *copy = internal_strdup(buffer);
8862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *p = copy;
8872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *q;
8882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // __android_log_write has an implicit message length limit.
8892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Print one line at a time.
8902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  do {
8912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    q = internal_strchr(p, '\n');
8922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) *q = '\0';
8932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __android_log_write(ANDROID_LOG_INFO, NULL, p);
8942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (q) p = q + 1;
8952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } while (q);
8962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InternalFree(copy);
8972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetExtraActivationFlags(char *buf, uptr size) {
9002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(size > PROP_VALUE_MAX);
9012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __system_property_get("asan.options", buf);
9022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
9032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
9042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
9052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool IsDeadlySignal(int signum) {
90686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
90786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
90886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
90986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
91086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void(*func)(void *arg), void *arg) {
91186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Start the thread with signals blocked, otherwise it can steal user signals.
91286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __sanitizer_sigset_t set, old;
91386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigfillset(&set);
91486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigprocmask(SIG_SETMASK, &set, &old);
91586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *th;
91686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  real_pthread_create(&th, 0, (void*(*)(void *arg))func, arg);
91786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_sigprocmask(SIG_SETMASK, &old, 0);
91886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return th;
9192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
9202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
92186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {
92286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  real_pthread_join(th, 0);
92386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
92486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else
92586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
92686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
92786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid internal_join_thread(void *th) {}
92886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
92986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
9317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if defined(__arm__)
9327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.arm_pc;
9347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.arm_fp;
9357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.arm_sp;
9367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__aarch64__)
9377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.pc;
9397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs[29];
9407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sp;
9417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__hppa__)
9427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.sc_iaoq[0];
9447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  /* GCC uses %r3 whenever a frame pointer is needed.  */
9457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.sc_gr[3];
9467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.sc_gr[30];
9477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__x86_64__)
9487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
9497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_rip;
9517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_rbp;
9527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_rsp;
9537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
9547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_RIP];
9567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_RBP];
9577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_RSP];
9587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
9597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__i386__)
9607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if SANITIZER_FREEBSD
9617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_eip;
9637c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.mc_ebp;
9647c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_esp;
9657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
9667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9677c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_EIP];
9687c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[REG_EBP];
9697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_ESP];
9707c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
9717c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__powerpc__) || defined(__powerpc64__)
9727c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.regs->nip;
9747c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
9757c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // The powerpc{,64}-linux ABIs do not specify r31 as the frame
9767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  // pointer, but GCC always uses r31 when we need a frame pointer.
9777c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
9787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__sparc__)
9797c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9807c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr *stk_ptr;
9817c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# if defined (__arch64__)
9827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
9837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
9847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) (*sp + 2047);
9857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
9867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# else
9877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[REG_PC];
9887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[REG_O6];
9897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  stk_ptr = (uptr *) *sp;
9907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = stk_ptr[15];
9917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# endif
9927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__mips__)
9937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  ucontext_t *ucontext = (ucontext_t*)context;
9947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *pc = ucontext->uc_mcontext.gregs[31];
9957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *bp = ucontext->uc_mcontext.gregs[30];
9967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  *sp = ucontext->uc_mcontext.gregs[29];
9977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#else
9987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar# error "Unsupported arch"
9997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#endif
10007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
10017c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
1002ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
1003ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
10042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
1005