asan_linux.cc revision 6895adc39c4e09371154c8037366ad4464163ed0
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific details. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 14d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __linux__ 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 16df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_interceptors.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 18d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include "asan_lock.h" 19df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 20c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include "asan_thread.h" 21ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common/sanitizer_procmaps.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 24c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/time.h> 25c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/resource.h> 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/syscall.h> 28de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <sys/types.h> 29de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <fcntl.h> 30c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 31df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include <stdio.h> 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 339cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#include <unwind.h> 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 359107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifndef ANDROID 369107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany// FIXME: where to get ucontext on Android? 379107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 389107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 399107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 40aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanovextern "C" void* _DYNAMIC; 41aa33a50c9d0f3e3f22c8b21fa7309ec91f9d939aEvgeniy Stepanov 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 443f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyconst uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M 456f350e0d1c385189cb94ddde7b288a2533b45b32Kostya Serebryany 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // This will fail to link with -static. 48efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return &_DYNAMIC; // defined in link.h 491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 513f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#ifdef ANDROID 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = *sp = *bp = 0; 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#elif defined(__arm__) 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.arm_pc; 579107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.arm_fp; 589107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.arm_sp; 599107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__x86_64__) 609107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 619107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 629107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 639107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 649107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# elif defined(__i386__) 659107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 669107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 679107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 689107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 699107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#else 709107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# error "Unsupported arch" 719107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#endif 729107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 739107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return signum == SIGSEGV && FLAG_handle_segv; 764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 783f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid *AsanMmapFixedNoReserve(uptr fixed_addr, uptr size) { 79ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return internal_mmap((void*)fixed_addr, size, 80ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov PROT_READ | PROT_WRITE, 81ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 82ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 0, 0); 83a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 84a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 853f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid *AsanMprotect(uptr fixed_addr, uptr size) { 86ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return internal_mmap((void*)fixed_addr, size, 87ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov PROT_NONE, 88ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 89ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 0, 0); 90a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 91a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 921e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko// Like getenv, but reads env directly from /proc and does not use libc. 931e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko// This function should be called first inside __asan_init. 941e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenkoconst char* AsanGetEnv(const char* name) { 951e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko static char *environ; 963f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr len; 971e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko static bool inited; 981e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (!inited) { 991e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko inited = true; 1003f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr environ_size; 1011e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko len = ReadFileToBuffer("/proc/self/environ", 102160cc4aa34e2418ba91035bb49648e751476f0d9Kostya Serebryany &environ, &environ_size, 1 << 26); 1031e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1043f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (!environ || len == 0) return 0; 1053f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr namelen = internal_strlen(name); 1061e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char *p = environ; 1071e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko while (*p != '\0') { // will happen at the \0\0 that terminates the buffer 1081e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko // proc file has the format NAME=value\0NAME=value\0NAME=value\0... 1091e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char* endp = 1101e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko (char*)internal_memchr(p, '\0', len - (p - environ)); 1113f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (endp == 0) // this entry isn't NUL terminated 1123f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 1131e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. 1141e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return p + namelen + 1; // point after = 1151e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko p = endp + 1; 1161e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1173f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; // Not found. 1181e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko} 1191e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko 120c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 121c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (tid() == 0) { 122c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 123c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany struct rlimit rl; 124c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 125c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 126c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Find the mapping that contains a stack variable. 1276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov ProcessMaps proc_maps; 1283f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr start, end, offset; 1293f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr prev_end = 0; 1303f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, 0, 0)) { 1313f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if ((uptr)&rl < end) 132c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany break; 133c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany prev_end = end; 134c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 1353f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK((uptr)&rl >= start && (uptr)&rl < end); 136c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 137c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 138c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // with other mappings. 1393f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr stacksize = rl.rlim_cur; 140c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > end - prev_end) 141c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = end - prev_end; 1426f350e0d1c385189cb94ddde7b288a2533b45b32Kostya Serebryany // When running with unlimited stack size, we still want to set some limit. 1436f350e0d1c385189cb94ddde7b288a2533b45b32Kostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 144ed2341803878f04093f58848468926337d9ca88fDmitry Vyukov // Also, for some reason, GNU make spawns subprocesses with unlimited stack. 145c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) 146c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = kMaxThreadStackSize; 147c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = end; 148c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = end - stacksize; 1493f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(AddrIsInStack((uptr)&rl)); 150c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany return; 151c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 152c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_t attr; 153c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 1543f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr stacksize = 0; 1553f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany void *stackaddr = 0; 1563f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); 157c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_destroy(&attr); 158c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 1593f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany stack_top_ = (uptr)stackaddr + stacksize; 1603f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany stack_bottom_ = (uptr)stackaddr; 1616f350e0d1c385189cb94ddde7b288a2533b45b32Kostya Serebryany CHECK(stacksize < kMaxThreadStackSize); // Sanity check. 1623f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(AddrIsInStack((uptr)&attr)); 163c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 164c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 165d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya SerebryanyAsanLock::AsanLock(LinkerInitialized) { 166d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // We assume that pthread_mutex_t initialized to all zeroes is a valid 167d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers 168d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // a gcc warning: 169d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // extended initializer lists only available with -std=c++0x or -std=gnu++0x 170d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 171d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 172d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Lock() { 173d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_)); 174d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_); 175d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(!owner_); 1763f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany owner_ = (uptr)pthread_self(); 177d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 178d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 179d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Unlock() { 1803f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(owner_ == (uptr)pthread_self()); 181d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = 0; 182d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_); 183d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 184d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 1859cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 1869cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_STOP _URC_END_OF_STACK 1879cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_CONTINUE _URC_NO_REASON 1889cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 1899cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_STOP _URC_NORMAL_STOP 1909cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#define UNWIND_CONTINUE _URC_NO_REASON 1919cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 1929cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 1933f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyuptr Unwind_GetIP(struct _Unwind_Context *ctx) { 1949cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 1953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr val; 1969cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 1979cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 15 /* r15 = PC */, _UVRSD_UINT32, &val); 1989cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 1999cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov // Clear the Thumb bit. 2003f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return val & ~(uptr)1; 2019cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 2029cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov return _Unwind_GetIP(ctx); 2039cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 2049cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 2059cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 2069cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, 2079cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov void *param) { 2089cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov AsanStackTrace *b = (AsanStackTrace*)param; 2099cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov CHECK(b->size < b->max_size); 2103f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr pc = Unwind_GetIP(ctx); 2119cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov b->trace[b->size++] = pc; 2129cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov if (b->size == b->max_size) return UNWIND_STOP; 2139cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov return UNWIND_CONTINUE; 2149cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 2159cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 2163f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid AsanStackTrace::GetStackTrace(uptr max_s, uptr pc, uptr bp) { 2179cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov size = 0; 2189cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov trace[0] = pc; 2199cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov if ((max_s) > 1) { 2209cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov max_size = max_s; 2219cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#ifdef __arm__ 2229cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov _Unwind_Backtrace(Unwind_Trace, this); 2239cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#else 2249cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov FastUnwindStack(pc, bp); 2259cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov#endif 2269cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov } 2279cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 2289cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 230d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 231d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __linux__ 232