Index: include/sanitizer/common_interface_defs.h =================================================================== --- include/sanitizer/common_interface_defs.h +++ include/sanitizer/common_interface_defs.h @@ -55,6 +55,11 @@ // the error message. This function can be overridden by the client. void __sanitizer_report_error_summary(const char *error_summary); + // This function is called by the user to provide a callback + // for all messages produced by the sanitizer. The callback + // receives the error message. This function should not be overriden. + void __sanitizer_report_message_callback(void (*callback)(const char*)); + // Some of the sanitizers (e.g. asan/tsan) may miss bugs that happen // in unaligned loads/stores. In order to find such bugs reliably one needs // to replace plain unaligned loads/stores with these calls. Index: lib/asan/asan_interface.inc =================================================================== --- lib/asan/asan_interface.inc +++ lib/asan/asan_interface.inc @@ -164,6 +164,7 @@ INTERFACE_FUNCTION(__sanitizer_unaligned_store16) INTERFACE_FUNCTION(__sanitizer_unaligned_store32) INTERFACE_FUNCTION(__sanitizer_unaligned_store64) +INTERFACE_FUNCTION(__sanitizer_report_message_callback) INTERFACE_WEAK_FUNCTION(__asan_default_options) INTERFACE_WEAK_FUNCTION(__asan_default_suppressions) INTERFACE_WEAK_FUNCTION(__asan_on_error) Index: lib/asan/asan_rtl.cc =================================================================== --- lib/asan/asan_rtl.cc +++ lib/asan/asan_rtl.cc @@ -396,7 +396,7 @@ // Install tool-specific callbacks in sanitizer_common. AddDieCallback(AsanDie); SetCheckFailedCallback(AsanCheckFailed); - SetPrintfAndReportCallback(AppendToErrorMessageBuffer); + AddPrintfAndReportCallback(AppendToErrorMessageBuffer); __sanitizer_set_report_path(common_flags()->log_path); Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -221,7 +221,7 @@ void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); -void SetPrintfAndReportCallback(void (*callback)(const char *)); +void AddPrintfAndReportCallback(void (*callback)(const char *)); #define VReport(level, ...) \ do { \ if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \ Index: lib/sanitizer_common/sanitizer_common.cc =================================================================== --- lib/sanitizer_common/sanitizer_common.cc +++ lib/sanitizer_common/sanitizer_common.cc @@ -358,6 +358,11 @@ } SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_report_message_callback(void (*callback)(const char*)){ + AddPrintfAndReportCallback(callback); +} + +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } Index: lib/sanitizer_common/sanitizer_common_interface.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interface.inc +++ lib/sanitizer_common/sanitizer_common_interface.inc @@ -15,6 +15,7 @@ INTERFACE_FUNCTION(__sanitizer_set_report_fd) INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary) +INTERFACE_WEAK_FUNCTION(__sanitizer_report_message_callback) INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify) // Sanitizer weak hooks INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp) Index: lib/sanitizer_common/sanitizer_printf.cc =================================================================== --- lib/sanitizer_common/sanitizer_printf.cc +++ lib/sanitizer_common/sanitizer_printf.cc @@ -206,9 +206,17 @@ return result; } -static void (*PrintfAndReportCallback)(const char *); -void SetPrintfAndReportCallback(void (*callback)(const char *)) { - PrintfAndReportCallback = callback; +#define MAX_PRINTF_AND_REPORT_CALLBACKS 8 +static void (*PrintfAndReportCallbacks[MAX_PRINTF_AND_REPORT_CALLBACKS])(const char *); +static int PrintfAndReportCallbacksSize = 0; + +void AddPrintfAndReportCallback(void (*callback)(const char *)) { + CHECK(callback); + CHECK_LT(PrintfAndReportCallbacksSize, MAX_PRINTF_AND_REPORT_CALLBACKS); + CHECK(!PrintfAndReportCallbacks[PrintfAndReportCallbacksSize]); + + PrintfAndReportCallbacks[PrintfAndReportCallbacksSize] = callback; + PrintfAndReportCallbacksSize++; } // Can be overriden in frontend. @@ -223,8 +231,8 @@ static void CallPrintfAndReportCallback(const char *str) { OnPrint(str); - if (PrintfAndReportCallback) - PrintfAndReportCallback(str); + for (int i = 0; i < PrintfAndReportCallbacksSize; ++i) + PrintfAndReportCallbacks[i](str); } static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid, Index: test/asan/TestCases/error_report_callback.cc =================================================================== --- test/asan/TestCases/error_report_callback.cc +++ test/asan/TestCases/error_report_callback.cc @@ -11,6 +11,7 @@ int main(int argc, char **argv) { __asan_set_error_report_callback(ErrorReportCallbackOneToZ); + __sanitizer_report_message_callback(ErrorReportCallbackOneToZ); __asan_report_error( (void *)__builtin_extract_return_addr(__builtin_return_address(0)), 0, 0, 0, true, 1);