summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2012-02-27 14:06:48 +0000
committerAlexander Potapenko <glider@google.com>2012-02-27 14:06:48 +0000
commit7e07f568110868eeea036ceef33204a3b8396ad0 (patch)
treee747dd2026cb6fc31854e5b33c4e73a229f50f2c /compiler-rt
parent169f4368702f534b34b54f72de5ac28b787342bb (diff)
downloadbcm5719-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.cc7
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.h1
-rw-r--r--compiler-rt/lib/asan/asan_interface.h3
-rw-r--r--compiler-rt/lib/asan/asan_printf.cc11
-rw-r--r--compiler-rt/lib/asan/asan_rtl.cc20
-rw-r--r--compiler-rt/lib/asan/tests/asan_interface_test.cc18
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);
+}
OpenPOWER on IntegriCloud