[Sanitizer] Get rid of dependency between sanitizer_common and asan/tsan runtimes: implement tool-specific Die and CheckFailed functions via callbacks

llvm-svn: 163603
This commit is contained in:
Alexey Samsonov 2012-09-11 09:44:48 +00:00
parent 1a471772b0
commit 5c6b93bc33
8 changed files with 56 additions and 34 deletions

View File

@ -27,10 +27,9 @@
#include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_symbolizer.h" #include "sanitizer_common/sanitizer_symbolizer.h"
namespace __sanitizer { namespace __asan {
using namespace __asan;
void Die() { static void AsanDie() {
static atomic_uint32_t num_calls; static atomic_uint32_t num_calls;
if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
// Don't die twice - run a busy loop. // Don't die twice - run a busy loop.
@ -49,8 +48,8 @@ void Die() {
Exit(flags()->exitcode); Exit(flags()->exitcode);
} }
SANITIZER_INTERFACE_ATTRIBUTE static void AsanCheckFailed(const char *file, int line, const char *cond,
void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { u64 v1, u64 v2) {
Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
file, line, cond, (uptr)v1, (uptr)v2); file, line, cond, (uptr)v1, (uptr)v2);
// FIXME: check for infinite recursion without a thread-local counter here. // FIXME: check for infinite recursion without a thread-local counter here.
@ -58,10 +57,6 @@ void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) {
ShowStatsAndAbort(); ShowStatsAndAbort();
} }
} // namespace __sanitizer
namespace __asan {
// -------------------------- Flags ------------------------- {{{1 // -------------------------- Flags ------------------------- {{{1
static const int kDeafultMallocContextSize = 30; static const int kDeafultMallocContextSize = 30;
@ -291,6 +286,9 @@ void __asan_init() {
// Make sure we are not statically linked. // Make sure we are not statically linked.
AsanDoesNotSupportStaticLinkage(); AsanDoesNotSupportStaticLinkage();
// Install tool-specific callbacks in sanitizer_common.
SetDieCallback(AsanDie);
SetCheckFailedCallback(AsanCheckFailed);
SetPrintfAndReportCallback(AppendToErrorMessageBuffer); SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
// Initialize flags. This must be done early, because most of the // Initialize flags. This must be done early, because most of the

View File

@ -16,6 +16,33 @@
namespace __sanitizer { namespace __sanitizer {
static void (*DieCallback)(void);
void SetDieCallback(void (*callback)(void)) {
DieCallback = callback;
}
void NORETURN Die() {
if (DieCallback) {
DieCallback();
}
Exit(1);
}
static CheckFailedCallbackType CheckFailedCallback;
void SetCheckFailedCallback(CheckFailedCallbackType callback) {
CheckFailedCallback = callback;
}
void NORETURN CheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
if (CheckFailedCallback) {
CheckFailedCallback(file, line, cond, v1, v2);
}
Report("Sanitizer CHECK failed: %s:%d %s (%zd, %zd)\n", file, line, cond,
v1, v2);
Die();
}
void RawWrite(const char *buffer) { void RawWrite(const char *buffer) {
static const char *kRawWriteError = "RawWrite can't output requested buffer!"; static const char *kRawWriteError = "RawWrite can't output requested buffer!";
uptr length = (uptr)internal_strlen(buffer); uptr length = (uptr)internal_strlen(buffer);

View File

@ -120,11 +120,23 @@ void DisableCoreDumper();
void DumpProcessMap(); void DumpProcessMap();
void SleepForSeconds(int seconds); void SleepForSeconds(int seconds);
void SleepForMillis(int millis); void SleepForMillis(int millis);
void NORETURN Exit(int exitcode);
void NORETURN Abort();
int Atexit(void (*function)(void)); int Atexit(void (*function)(void));
void SortArray(uptr *array, uptr size); void SortArray(uptr *array, uptr size);
// Exit
void NORETURN Abort();
void NORETURN Exit(int exitcode);
void NORETURN Die();
void NORETURN SANITIZER_INTERFACE_ATTRIBUTE
CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
// Specific tools may override behavior of "Die" and "CheckFailed" functions
// to do tool-specific job.
void SetDieCallback(void (*callback)(void));
typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
u64, u64);
void SetCheckFailedCallback(CheckFailedCallbackType callback);
// Math // Math
INLINE bool IsPowerOfTwo(uptr x) { INLINE bool IsPowerOfTwo(uptr x) {
return (x & (x - 1)) == 0; return (x & (x - 1)) == 0;

View File

@ -43,14 +43,6 @@
extern "C" int arch_prctl(int code, __sanitizer::uptr *addr); extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
namespace __sanitizer {
void Die() {
_exit(1);
}
} // namespace __sanitizer
namespace __tsan { namespace __tsan {
#ifndef TSAN_GO #ifndef TSAN_GO

View File

@ -37,14 +37,6 @@
#include <errno.h> #include <errno.h>
#include <sched.h> #include <sched.h>
namespace __sanitizer {
void Die() {
_exit(1);
}
} // namespace __sanitizer
namespace __tsan { namespace __tsan {
ScopedInRtl::ScopedInRtl() { ScopedInRtl::ScopedInRtl() {

View File

@ -165,6 +165,9 @@ void Initialize(ThreadState *thr) {
if (is_initialized) if (is_initialized)
return; return;
is_initialized = true; is_initialized = true;
// Install tool-specific callbacks in sanitizer_common.
SetCheckFailedCallback(TsanCheckFailed);
ScopedInRtl in_rtl; ScopedInRtl in_rtl;
#ifndef TSAN_GO #ifndef TSAN_GO
InitializeAllocator(); InitializeAllocator();

View File

@ -65,6 +65,8 @@ typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
Allocator *allocator(); Allocator *allocator();
#endif #endif
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2);
void TsanPrintf(const char *format, ...); void TsanPrintf(const char *format, ...);
// FastState (from most significant bit): // FastState (from most significant bit):

View File

@ -23,10 +23,10 @@
#include "tsan_mman.h" #include "tsan_mman.h"
#include "tsan_flags.h" #include "tsan_flags.h"
namespace __sanitizer { namespace __tsan {
using namespace __tsan;
void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
ScopedInRtl in_rtl; ScopedInRtl in_rtl;
TsanPrintf("FATAL: ThreadSanitizer CHECK failed: " TsanPrintf("FATAL: ThreadSanitizer CHECK failed: "
"%s:%d \"%s\" (0x%zx, 0x%zx)\n", "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
@ -34,10 +34,6 @@ void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) {
Die(); Die();
} }
} // namespace __sanitizer
namespace __tsan {
// Can be overriden by an application/test to intercept reports. // Can be overriden by an application/test to intercept reports.
#ifdef TSAN_EXTERNAL_HOOKS #ifdef TSAN_EXTERNAL_HOOKS
bool OnReport(const ReportDesc *rep, bool suppressed); bool OnReport(const ReportDesc *rep, bool suppressed);