diff options
author | Alexander Potapenko <glider@google.com> | 2012-02-27 14:06:48 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2012-02-27 14:06:48 +0000 |
commit | 7e07f568110868eeea036ceef33204a3b8396ad0 (patch) | |
tree | e747dd2026cb6fc31854e5b33c4e73a229f50f2c /compiler-rt | |
parent | 169f4368702f534b34b54f72de5ac28b787342bb (diff) | |
download | bcm5719-llvm-7e07f568110868eeea036ceef33204a3b8396ad0.tar.gz bcm5719-llvm-7e07f568110868eeea036ceef33204a3b8396ad0.zip |
Introduce __asan_set_error_report_callback() to allow the client program post-process the error reports.
If the callback is set, Report() and Printf() print the reports into a buffer (together with stderr), which is then passed to the client.
llvm-svn: 151528
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/asan/asan_interceptors.cc | 7 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_interceptors.h | 1 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_interface.h | 3 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_printf.cc | 11 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 20 | ||||
-rw-r--r-- | compiler-rt/lib/asan/tests/asan_interface_test.cc | 18 |
6 files changed, 59 insertions, 1 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index 1d85facd754..35214cbcf17 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -222,6 +222,13 @@ int internal_strcmp(const char *s1, const char *s2) { return 0; } +char *internal_strncpy(char *dst, const char *src, size_t n) { + size_t i; + for (i = 0; i < n && src[i]; i++) + dst[i] = src[i]; + return dst; +} + } // namespace __asan // ---------------------- Wrappers ---------------- {{{1 diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 80df6505778..6ef808a7b94 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -40,6 +40,7 @@ int internal_memcmp(const void* s1, const void* s2, size_t n); char *internal_strstr(const char *haystack, const char *needle); char *internal_strncat(char *dst, const char *src, size_t n); int internal_strcmp(const char *s1, const char *s2); +char *internal_strncpy(char *dst, const char *src, size_t n); // Works only for base=10 and doesn't set errno. int64_t internal_simple_strtoll(const char *nptr, char **endptr, int base); diff --git a/compiler-rt/lib/asan/asan_interface.h b/compiler-rt/lib/asan/asan_interface.h index 4deba08dbc6..f9a2e0e88b9 100644 --- a/compiler-rt/lib/asan/asan_interface.h +++ b/compiler-rt/lib/asan/asan_interface.h @@ -121,6 +121,9 @@ extern "C" { void __asan_set_death_callback(void (*callback)(void)) ASAN_INTERFACE_FUNCTION_ATTRIBUTE; + void __asan_set_error_report_callback(void (*callback)(const char*)) + 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 // memory, returns the maximal possible allocation size, otherwise returns diff --git a/compiler-rt/lib/asan/asan_printf.cc b/compiler-rt/lib/asan/asan_printf.cc index 665256e17a8..234420461d6 100644 --- a/compiler-rt/lib/asan/asan_printf.cc +++ b/compiler-rt/lib/asan/asan_printf.cc @@ -22,6 +22,9 @@ namespace __asan { +extern char *error_message_buffer; +extern size_t error_message_buffer_pos, error_message_buffer_size; + void RawWrite(const char *buffer) { static const char *kRawWriteError = "RawWrite can't output requested buffer!"; size_t length = (size_t)internal_strlen(buffer); @@ -29,6 +32,14 @@ void RawWrite(const char *buffer) { AsanWrite(2, kRawWriteError, internal_strlen(kRawWriteError)); AsanDie(); } + if (error_message_buffer) { + int remaining = error_message_buffer_size - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[error_message_buffer_size - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += remaining > length ? length : remaining; + } } static inline int AppendChar(char **buff, const char *buff_end, char c) { diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 4075d1f63fa..8d6e7561db2 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -52,6 +52,10 @@ int FLAG_sleep_before_dying; int asan_inited; bool asan_init_is_running; static void (*death_callback)(void); +static void (*error_report_callback)(const char*); +char *error_message_buffer = NULL; +size_t error_message_buffer_pos = 0; +size_t error_message_buffer_size = 0; // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { @@ -237,7 +241,7 @@ ASAN_REPORT_ERROR(store, true, 16) // dynamic libraries access the symbol even if it is not used by the executable // itself. This should help if the build system is removing dead code at link // time. -static void force_interface_symbols() { +static NOINLINE void force_interface_symbols() { volatile int fake_condition = 0; // prevent dead condition elimination. if (fake_condition) { __asan_report_load1(NULL); @@ -253,6 +257,7 @@ static void force_interface_symbols() { __asan_register_global(0, 0, NULL); __asan_register_globals(NULL, 0); __asan_unregister_globals(NULL, 0); + __asan_set_error_report_callback(NULL); } } @@ -300,6 +305,16 @@ void __asan_set_death_callback(void (*callback)(void)) { death_callback = callback; } +void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { + error_report_callback = callback; + if (callback) { + error_message_buffer_size = 1 << 14; + error_message_buffer = + (char*)AsanMmapSomewhereOrDie(error_message_buffer_size, __FUNCTION__); + error_message_buffer_pos = 0; + } +} + 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. @@ -389,6 +404,9 @@ void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp, PrintBytes(" ", (uintptr_t*)(aligned_shadow+2*kWordSize)); PrintBytes(" ", (uintptr_t*)(aligned_shadow+3*kWordSize)); PrintBytes(" ", (uintptr_t*)(aligned_shadow+4*kWordSize)); + if (error_report_callback) { + error_report_callback(error_message_buffer); + } AsanDie(); } diff --git a/compiler-rt/lib/asan/tests/asan_interface_test.cc b/compiler-rt/lib/asan/tests/asan_interface_test.cc index 782466dd37f..79d5cf375a2 100644 --- a/compiler-rt/lib/asan/tests/asan_interface_test.cc +++ b/compiler-rt/lib/asan/tests/asan_interface_test.cc @@ -342,3 +342,21 @@ TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) { kInvalidPoisonMessage); free(array); } + +static void ErrorReportCallbackOneToZ(const char *report) { + int len = strlen(report); + char *dup = (char*)malloc(len); + strcpy(dup, report); + for (int i = 0; i < len; i++) { + if (dup[i] == '1') dup[i] = 'Z'; + } + write(2, dup, len); + free(dup); +} + +TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) { + __asan_set_error_report_callback(ErrorReportCallbackOneToZ); + char *array = Ident((char*)malloc(120)); + EXPECT_DEATH(ACCESS(array, 120), "size Z"); + __asan_set_error_report_callback(NULL); +} |