forked from OSchip/llvm-project
[asan] refactoring: move all interceptors to a single file
llvm-svn: 147784
This commit is contained in:
parent
12ea3c56c3
commit
9fd01e5ea5
|
@ -19,7 +19,9 @@
|
|||
#include "asan_mapping.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_stats.h"
|
||||
#include "asan_thread_registry.h"
|
||||
|
||||
#include <new>
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
@ -27,6 +29,29 @@
|
|||
|
||||
namespace __asan {
|
||||
|
||||
typedef void (*longjmp_f)(void *env, int val);
|
||||
typedef longjmp_f _longjmp_f;
|
||||
typedef longjmp_f siglongjmp_f;
|
||||
typedef void (*__cxa_throw_f)(void *, void *, void *);
|
||||
typedef int (*pthread_create_f)(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
#ifdef __APPLE__
|
||||
dispatch_async_f_f real_dispatch_async_f;
|
||||
dispatch_sync_f_f real_dispatch_sync_f;
|
||||
dispatch_after_f_f real_dispatch_after_f;
|
||||
dispatch_barrier_async_f_f real_dispatch_barrier_async_f;
|
||||
dispatch_group_async_f_f real_dispatch_group_async_f;
|
||||
pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np;
|
||||
#endif
|
||||
|
||||
sigaction_f real_sigaction;
|
||||
signal_f real_signal;
|
||||
longjmp_f real_longjmp;
|
||||
_longjmp_f real__longjmp;
|
||||
siglongjmp_f real_siglongjmp;
|
||||
__cxa_throw_f real___cxa_throw;
|
||||
pthread_create_f real_pthread_create;
|
||||
|
||||
index_f real_index;
|
||||
memcmp_f real_memcmp;
|
||||
memcpy_f real_memcpy;
|
||||
|
@ -156,6 +181,32 @@ void InitializeAsanInterceptors() {
|
|||
INTERCEPT_FUNCTION(strncasecmp);
|
||||
INTERCEPT_FUNCTION(strncmp);
|
||||
INTERCEPT_FUNCTION(strncpy);
|
||||
|
||||
INTERCEPT_FUNCTION(sigaction);
|
||||
INTERCEPT_FUNCTION(signal);
|
||||
INTERCEPT_FUNCTION(longjmp);
|
||||
INTERCEPT_FUNCTION(_longjmp);
|
||||
INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw);
|
||||
INTERCEPT_FUNCTION(pthread_create);
|
||||
|
||||
#ifdef __APPLE__
|
||||
INTERCEPT_FUNCTION(dispatch_async_f);
|
||||
INTERCEPT_FUNCTION(dispatch_sync_f);
|
||||
INTERCEPT_FUNCTION(dispatch_after_f);
|
||||
INTERCEPT_FUNCTION(dispatch_barrier_async_f);
|
||||
INTERCEPT_FUNCTION(dispatch_group_async_f);
|
||||
// We don't need to intercept pthread_workqueue_additem_np() to support the
|
||||
// libdispatch API, but it helps us to debug the unsupported functions. Let's
|
||||
// intercept it only during verbose runs.
|
||||
if (FLAG_v >= 2) {
|
||||
INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
|
||||
}
|
||||
#else
|
||||
// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
|
||||
// there.
|
||||
INTERCEPT_FUNCTION(siglongjmp);
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
INTERCEPT_FUNCTION(strnlen);
|
||||
#endif
|
||||
|
@ -169,6 +220,136 @@ void InitializeAsanInterceptors() {
|
|||
// ---------------------- Wrappers ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
#define OPERATOR_NEW_BODY \
|
||||
GET_STACK_TRACE_HERE_FOR_MALLOC;\
|
||||
return asan_memalign(0, size, &stack);
|
||||
|
||||
#ifdef ANDROID
|
||||
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
|
||||
#else
|
||||
void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
|
||||
void *operator new(size_t size, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_NEW_BODY; }
|
||||
#endif
|
||||
|
||||
#define OPERATOR_DELETE_BODY \
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
|
||||
asan_free(ptr, &stack);
|
||||
|
||||
void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
|
||||
void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
|
||||
void operator delete(void *ptr, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_DELETE_BODY; }
|
||||
void operator delete[](void *ptr, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_DELETE_BODY;}
|
||||
|
||||
static void *asan_thread_start(void *arg) {
|
||||
AsanThread *t = (AsanThread*)arg;
|
||||
asanThreadRegistry().SetCurrent(t);
|
||||
return t->ThreadStart();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
#ifndef __APPLE__
|
||||
__attribute__((visibility("default")))
|
||||
#endif
|
||||
int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg) {
|
||||
GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false);
|
||||
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
|
||||
CHECK(curr_thread || asanThreadRegistry().IsCurrentThreadDying());
|
||||
int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
|
||||
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg);
|
||||
asanThreadRegistry().RegisterThread(t, current_tid, &stack);
|
||||
return real_pthread_create(thread, attr, asan_thread_start, t);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void *WRAP(signal)(int signum, void *handler) {
|
||||
if (!AsanInterceptsSignal(signum)) {
|
||||
return real_signal(signum, handler);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int WRAP(sigaction)(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact) {
|
||||
if (!AsanInterceptsSignal(signum)) {
|
||||
return real_sigaction(signum, act, oldact);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void UnpoisonStackFromHereToTop() {
|
||||
int local_stack;
|
||||
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
|
||||
CHECK(curr_thread);
|
||||
uintptr_t top = curr_thread->stack_top();
|
||||
uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1);
|
||||
PoisonShadow(bottom, top - bottom, 0);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(longjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real_longjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(_longjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real__longjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(siglongjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real_siglongjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_throw(void *a, void *b, void *c);
|
||||
|
||||
#if ASAN_HAS_EXCEPTIONS == 1
|
||||
extern "C" void WRAP(__cxa_throw)(void *a, void *b, void *c) {
|
||||
CHECK(&real___cxa_throw);
|
||||
UnpoisonStackFromHereToTop();
|
||||
real___cxa_throw(a, b, c);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
// intercept mlock and friends.
|
||||
// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
|
||||
// All functions return 0 (success).
|
||||
static void MlockIsUnsupported() {
|
||||
static bool printed = 0;
|
||||
if (printed) return;
|
||||
printed = true;
|
||||
Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
|
||||
}
|
||||
int mlock(const void *addr, size_t len) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int munlock(const void *addr, size_t len) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int mlockall(int flags) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int munlockall(void) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
||||
|
||||
static inline int CharCmp(unsigned char c1, unsigned char c2) {
|
||||
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ typedef int (*strncasecmp_f)(const char *s1, const char *s2, size_t n);
|
|||
typedef int (*strncmp_f)(const char *s1, const char *s2, size_t size);
|
||||
typedef char* (*strncpy_f)(char *to, const char *from, size_t size);
|
||||
typedef size_t (*strnlen_f)(const char *s, size_t maxlen);
|
||||
typedef void *(*signal_f)(int signum, void *handler);
|
||||
typedef int (*sigaction_f)(int signum, const void *act, void *oldact);
|
||||
|
||||
// __asan::real_X() holds pointer to library implementation of X().
|
||||
extern index_f real_index;
|
||||
|
@ -119,6 +121,8 @@ extern strncasecmp_f real_strncasecmp;
|
|||
extern strncmp_f real_strncmp;
|
||||
extern strncpy_f real_strncpy;
|
||||
extern strnlen_f real_strnlen;
|
||||
extern signal_f real_signal;
|
||||
extern sigaction_f real_sigaction;
|
||||
|
||||
// __asan::internal_X() is the implementation of X() for use in RTL.
|
||||
size_t internal_strlen(const char *s);
|
||||
|
|
|
@ -106,6 +106,8 @@ ssize_t AsanRead(int fd, void *buf, size_t count);
|
|||
ssize_t AsanWrite(int fd, const void *buf, size_t count);
|
||||
int AsanClose(int fd);
|
||||
|
||||
bool AsanInterceptsSignal(int signum);
|
||||
|
||||
// Opens the file 'file_name" and reads up to 'max_len' bytes.
|
||||
// The resulting buffer is mmaped and stored in '*buff'.
|
||||
// The size of the mmaped region is stored in '*buff_size',
|
||||
|
@ -151,6 +153,7 @@ extern bool FLAG_use_fake_stack;
|
|||
extern size_t FLAG_max_malloc_fill_size;
|
||||
extern int FLAG_exitcode;
|
||||
extern bool FLAG_allow_user_poisoning;
|
||||
extern bool FLAG_handle_segv;
|
||||
|
||||
extern int asan_inited;
|
||||
// Used to avoid infinite recursion in __asan_init().
|
||||
|
|
|
@ -64,6 +64,10 @@ void GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool AsanInterceptsSignal(int signum) {
|
||||
return signum == SIGSEGV && FLAG_handle_segv;
|
||||
}
|
||||
|
||||
static void *asan_mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, uint64_t offset) {
|
||||
# if __WORDSIZE == 64
|
||||
|
|
|
@ -56,6 +56,10 @@ void *AsanDoesNotSupportStaticLinkage() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool AsanInterceptsSignal(int signum) {
|
||||
return (signum == SIGSEGV || signum == SIGBUS) && FLAG_handle_segv;
|
||||
}
|
||||
|
||||
static void *asan_mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, uint64_t offset) {
|
||||
return mmap(addr, length, prot, flags, fd, offset);
|
||||
|
|
|
@ -24,19 +24,9 @@
|
|||
#include "asan_thread.h"
|
||||
#include "asan_thread_registry.h"
|
||||
|
||||
#include <new>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
// must not include <setjmp.h> on Linux
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -69,33 +59,6 @@ bool FLAG_allow_user_poisoning;
|
|||
int asan_inited;
|
||||
bool asan_init_is_running;
|
||||
|
||||
// -------------------------- Interceptors ---------------- {{{1
|
||||
typedef int (*sigaction_f)(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact);
|
||||
typedef sig_t (*signal_f)(int signum, sig_t handler);
|
||||
typedef void (*longjmp_f)(void *env, int val);
|
||||
typedef longjmp_f _longjmp_f;
|
||||
typedef longjmp_f siglongjmp_f;
|
||||
typedef void (*__cxa_throw_f)(void *, void *, void *);
|
||||
typedef int (*pthread_create_f)(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
#ifdef __APPLE__
|
||||
dispatch_async_f_f real_dispatch_async_f;
|
||||
dispatch_sync_f_f real_dispatch_sync_f;
|
||||
dispatch_after_f_f real_dispatch_after_f;
|
||||
dispatch_barrier_async_f_f real_dispatch_barrier_async_f;
|
||||
dispatch_group_async_f_f real_dispatch_group_async_f;
|
||||
pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np;
|
||||
#endif
|
||||
|
||||
sigaction_f real_sigaction;
|
||||
signal_f real_signal;
|
||||
longjmp_f real_longjmp;
|
||||
_longjmp_f real__longjmp;
|
||||
siglongjmp_f real_siglongjmp;
|
||||
__cxa_throw_f real___cxa_throw;
|
||||
pthread_create_f real_pthread_create;
|
||||
|
||||
// -------------------------- Misc ---------------- {{{1
|
||||
void ShowStatsAndAbort() {
|
||||
__asan_print_accumulated_stats();
|
||||
|
@ -161,11 +124,15 @@ static const char* GetEnvFromProcSelfEnviron(const char* name) {
|
|||
return NULL; // Not found.
|
||||
}
|
||||
|
||||
// ---------------------- Thread ------------------------- {{{1
|
||||
static void *asan_thread_start(void *arg) {
|
||||
AsanThread *t= (AsanThread*)arg;
|
||||
asanThreadRegistry().SetCurrent(t);
|
||||
return t->ThreadStart();
|
||||
static void MaybeInstallSigaction(int signum,
|
||||
void (*handler)(int, siginfo_t *, void *)) {
|
||||
if (!AsanInterceptsSignal(signum))
|
||||
return;
|
||||
struct sigaction sigact;
|
||||
real_memset(&sigact, 0, sizeof(sigact));
|
||||
sigact.sa_sigaction = handler;
|
||||
sigact.sa_flags = SA_SIGINFO;
|
||||
CHECK(0 == real_sigaction(signum, &sigact, 0));
|
||||
}
|
||||
|
||||
// ---------------------- mmap -------------------- {{{1
|
||||
|
@ -359,151 +326,9 @@ void CheckFailed(const char *cond, const char *file, int line) {
|
|||
|
||||
} // namespace __asan
|
||||
|
||||
// -------------------------- Interceptors ------------------- {{{1
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
#define OPERATOR_NEW_BODY \
|
||||
GET_STACK_TRACE_HERE_FOR_MALLOC;\
|
||||
return asan_memalign(0, size, &stack);
|
||||
|
||||
#ifdef ANDROID
|
||||
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
|
||||
#else
|
||||
void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
|
||||
void *operator new(size_t size, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_NEW_BODY; }
|
||||
void *operator new[](size_t size, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_NEW_BODY; }
|
||||
#endif
|
||||
|
||||
#define OPERATOR_DELETE_BODY \
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
|
||||
asan_free(ptr, &stack);
|
||||
|
||||
void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
|
||||
void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
|
||||
void operator delete(void *ptr, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_DELETE_BODY; }
|
||||
void operator delete[](void *ptr, std::nothrow_t const&) throw()
|
||||
{ OPERATOR_DELETE_BODY;}
|
||||
|
||||
extern "C"
|
||||
#ifndef __APPLE__
|
||||
__attribute__((visibility("default")))
|
||||
#endif
|
||||
int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg) {
|
||||
GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false);
|
||||
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
|
||||
CHECK(curr_thread || asanThreadRegistry().IsCurrentThreadDying());
|
||||
int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
|
||||
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg);
|
||||
asanThreadRegistry().RegisterThread(t, current_tid, &stack);
|
||||
return real_pthread_create(thread, attr, asan_thread_start, t);
|
||||
}
|
||||
|
||||
static bool MySignal(int signum) {
|
||||
if (FLAG_handle_segv && signum == SIGSEGV) return true;
|
||||
#ifdef __APPLE__
|
||||
if (FLAG_handle_segv && signum == SIGBUS) return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static void MaybeInstallSigaction(int signum,
|
||||
void (*handler)(int, siginfo_t *, void *)) {
|
||||
if (!MySignal(signum))
|
||||
return;
|
||||
struct sigaction sigact;
|
||||
real_memset(&sigact, 0, sizeof(sigact));
|
||||
sigact.sa_sigaction = handler;
|
||||
sigact.sa_flags = SA_SIGINFO;
|
||||
CHECK(0 == real_sigaction(signum, &sigact, 0));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
sig_t WRAP(signal)(int signum, sig_t handler) {
|
||||
if (!MySignal(signum)) {
|
||||
return real_signal(signum, handler);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int WRAP(sigaction)(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact) {
|
||||
if (!MySignal(signum)) {
|
||||
return real_sigaction(signum, act, oldact);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void UnpoisonStackFromHereToTop() {
|
||||
int local_stack;
|
||||
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
|
||||
CHECK(curr_thread);
|
||||
uintptr_t top = curr_thread->stack_top();
|
||||
uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1);
|
||||
PoisonShadow(bottom, top - bottom, 0);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(longjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real_longjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(_longjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real__longjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void WRAP(siglongjmp)(void *env, int val) {
|
||||
UnpoisonStackFromHereToTop();
|
||||
real_siglongjmp(env, val);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_throw(void *a, void *b, void *c);
|
||||
|
||||
#if ASAN_HAS_EXCEPTIONS == 1
|
||||
extern "C" void WRAP(__cxa_throw)(void *a, void *b, void *c) {
|
||||
CHECK(&real___cxa_throw);
|
||||
UnpoisonStackFromHereToTop();
|
||||
real___cxa_throw(a, b, c);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
// intercept mlock and friends.
|
||||
// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
|
||||
// All functions return 0 (success).
|
||||
static void MlockIsUnsupported() {
|
||||
static bool printed = 0;
|
||||
if (printed) return;
|
||||
printed = true;
|
||||
Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
|
||||
}
|
||||
int mlock(const void *addr, size_t len) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int munlock(const void *addr, size_t len) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int mlockall(int flags) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
int munlockall(void) {
|
||||
MlockIsUnsupported();
|
||||
return 0;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
int __asan_set_error_exit_code(int exit_code) {
|
||||
int old = FLAG_exitcode;
|
||||
FLAG_exitcode = exit_code;
|
||||
|
@ -655,30 +480,6 @@ void __asan_init() {
|
|||
|
||||
ReplaceSystemMalloc();
|
||||
|
||||
INTERCEPT_FUNCTION(sigaction);
|
||||
INTERCEPT_FUNCTION(signal);
|
||||
INTERCEPT_FUNCTION(longjmp);
|
||||
INTERCEPT_FUNCTION(_longjmp);
|
||||
INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw);
|
||||
INTERCEPT_FUNCTION(pthread_create);
|
||||
#ifdef __APPLE__
|
||||
INTERCEPT_FUNCTION(dispatch_async_f);
|
||||
INTERCEPT_FUNCTION(dispatch_sync_f);
|
||||
INTERCEPT_FUNCTION(dispatch_after_f);
|
||||
INTERCEPT_FUNCTION(dispatch_barrier_async_f);
|
||||
INTERCEPT_FUNCTION(dispatch_group_async_f);
|
||||
// We don't need to intercept pthread_workqueue_additem_np() to support the
|
||||
// libdispatch API, but it helps us to debug the unsupported functions. Let's
|
||||
// intercept it only during verbose runs.
|
||||
if (FLAG_v >= 2) {
|
||||
INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
|
||||
}
|
||||
#else
|
||||
// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
|
||||
// there.
|
||||
INTERCEPT_FUNCTION(siglongjmp);
|
||||
#endif
|
||||
|
||||
MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);
|
||||
MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
|
||||
|
||||
|
|
Loading…
Reference in New Issue