[asan] implement __asan_set_death_callback

llvm-svn: 150414
This commit is contained in:
Kostya Serebryany 2012-02-13 21:24:29 +00:00
parent 75e71b99ec
commit fcd535ba6c
6 changed files with 49 additions and 24 deletions

View File

@ -81,7 +81,7 @@ extern "C" {
// Performs cleanup before a NoReturn function. Must be called before things
// like _exit and execl to avoid false positives on stack.
void __asan_handle_no_return();
void __asan_handle_no_return() ASAN_INTERFACE_FUNCTION_ATTRIBUTE;
// User code should use macro instead of functions.
#if defined(__has_feature) && __has_feature(address_sanitizer)
@ -109,7 +109,13 @@ extern "C" {
// Sets the exit code to use when reporting an error.
// Returns the old value.
int __asan_set_error_exit_code(int exit_code);
int __asan_set_error_exit_code(int exit_code)
ASAN_INTERFACE_FUNCTION_ATTRIBUTE;
// Sets the callback to be called right before death on error.
// Passing NULL will unset the callback.
void __asan_set_death_callback(void (*callback)(void))
ASAN_INTERFACE_FUNCTION_ATTRIBUTE;
// Returns the estimated number of bytes that will be reserved by allocator
// for request of "size" bytes. If ASan allocator can't allocate that much

View File

@ -210,6 +210,8 @@ extern bool asan_init_is_running;
enum LinkerInitialized { LINKER_INITIALIZED = 0 };
void AsanDie();
void SleepForSeconds(int seconds);
void Exit(int exitcode);
#define CHECK(cond) do { if (!(cond)) { \
CheckFailed(#cond, __FILE__, __LINE__); \

View File

@ -69,14 +69,6 @@ void AsanDisableCoreDumper() {
setrlimit(RLIMIT_CORE, &nocore);
}
void AsanDie() {
if (FLAG_sleep_before_dying) {
Report("Sleeping for %d second(s)\n", FLAG_sleep_before_dying);
sleep(FLAG_sleep_before_dying);
}
_exit(FLAG_exitcode);
}
int GetPid() {
return getpid();
}
@ -85,6 +77,14 @@ uintptr_t GetThreadSelf() {
return (uintptr_t)pthread_self();
}
void SleepForSeconds(int seconds) {
sleep(seconds);
}
void Exit(int exitcode) {
return _exit(exitcode);
}
int AtomicInc(int *a) {
#ifdef ANDROID
return __atomic_inc(a) + 1;

View File

@ -52,6 +52,7 @@ int FLAG_sleep_before_dying;
// -------------------------- Globals --------------------- {{{1
int asan_inited;
bool asan_init_is_running;
static void (*death_callback)(void);
// -------------------------- Misc ---------------- {{{1
void ShowStatsAndAbort() {
@ -100,6 +101,16 @@ size_t ReadFileToBuffer(const char *file_name, char **buff,
return read_len;
}
void AsanDie() {
if (FLAG_sleep_before_dying) {
Report("Sleeping for %d second(s)\n", FLAG_sleep_before_dying);
SleepForSeconds(FLAG_sleep_before_dying);
}
if (death_callback)
death_callback();
Exit(FLAG_exitcode);
}
// ---------------------- mmap -------------------- {{{1
void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) {
Report("ERROR: AddressSanitizer failed to allocate "
@ -283,7 +294,6 @@ int __asan_set_error_exit_code(int exit_code) {
return old;
}
NOINLINE ASAN_INTERFACE_ATTRIBUTE
void __asan_handle_no_return() {
int local_stack;
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
@ -293,6 +303,10 @@ void __asan_handle_no_return() {
PoisonShadow(bottom, top - bottom, 0);
}
void __asan_set_death_callback(void (*callback)(void)) {
death_callback = callback;
}
void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp,
uintptr_t addr, bool is_write, size_t access_size) {
// Do not print more than one report, otherwise they will mix up.

View File

@ -48,7 +48,6 @@ void *AsanMprotect(uintptr_t fixed_addr, size_t size) {
void AsanUnmapOrDie(void *addr, size_t size) {
UNIMPLEMENTED();
}
// }}}
// ---------------------- IO ---------------- {{{1
size_t AsanWrite(int fd, const void *buf, size_t count) {
@ -75,7 +74,6 @@ int AsanClose(int fd) {
UNIMPLEMENTED();
return -1;
}
// }}}
// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
static AsanLock dbghelp_lock(LINKER_INITIALIZED);
@ -156,7 +154,6 @@ bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) {
}
return true;
}
// }}}
// ---------------------- AsanLock ---------------- {{{1
enum LockState {
@ -193,7 +190,6 @@ void AsanLock::Unlock() {
owner_ = LOCK_READY;
LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
}
// }}}
// ---------------------- TSD ---------------- {{{1
static bool tsd_key_inited = false;
@ -215,7 +211,6 @@ void AsanTSDSet(void *tsd) {
CHECK(tsd_key_inited);
fake_tsd = tsd;
}
// }}}
// ---------------------- Various stuff ---------------- {{{1
void *AsanDoesNotSupportStaticLinkage() {
@ -253,15 +248,13 @@ void AsanDisableCoreDumper() {
UNIMPLEMENTED();
}
void AsanDie() {
// FIXME: AsanDie() should be the same on all platforms.
if (FLAG_sleep_before_dying) {
Report("Sleeping for %d second(s)\n", FLAG_sleep_before_dying);
Sleep(FLAG_sleep_before_dying * 1000);
}
_exit(FLAG_exitcode);
void SleepForSeconds(int seconds) {
Sleep(seconds * 1000);
}
void Exit(int exitcode) {
_exit(exitcode);
}
// }}}
} // namespace __asan

View File

@ -199,6 +199,16 @@ TEST(AddressSanitizerInterface, ExitCode) {
::testing::ExitedWithCode(original_exit_code), "");
}
static void MyDeathCallback() {
fprintf(stderr, "MyDeathCallback\n");
}
TEST(AddressSanitizerInterface, DeathCallbackTest) {
__asan_set_death_callback(MyDeathCallback);
EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
__asan_set_death_callback(NULL);
}
static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
#define ACCESS(ptr, offset) Ident(*(ptr + offset))