diff options
author | Kostya Serebryany <kcc@google.com> | 2012-09-14 04:35:14 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2012-09-14 04:35:14 +0000 |
commit | 81dfbb76f858fbc4084771fce4967ede04ed5f44 (patch) | |
tree | abb184ff829cf56b9ce130f5b22ee1cf9a0faf21 /lib | |
parent | 484db99999ebadcc62bd5ac5a702d1fdad391111 (diff) |
[asan] add asan option log_path=PATH to let users redirect asan reports to a file PATH.PID instead of stderr
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@163872 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_flags.h | 2 | ||||
-rw-r--r-- | lib/asan/asan_rtl.cc | 3 | ||||
-rw-r--r-- | lib/asan/lit_tests/log-path_test.cc | 39 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 30 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_printf.cc | 7 |
5 files changed, 78 insertions, 3 deletions
diff --git a/lib/asan/asan_flags.h b/lib/asan/asan_flags.h index de7475bc1..989784df0 100644 --- a/lib/asan/asan_flags.h +++ b/lib/asan/asan_flags.h @@ -93,6 +93,8 @@ struct Flags { // but also thread creation stacks for threads that created those threads, // etc. up to main thread. bool print_full_thread_history; + // ASan will write logs to "log_path.pid" instead of stderr. + const char *log_path; }; Flags *flags(); diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 41fbe6a44..97cb061d8 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -99,6 +99,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix"); ParseFlag(str, &f->allow_reexec, "allow_reexec"); ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history"); + ParseFlag(str, &f->log_path, "log_path"); } extern "C" { @@ -137,6 +138,7 @@ void InitializeFlags(Flags *f, const char *env) { f->strip_path_prefix = ""; f->allow_reexec = true; f->print_full_thread_history = true; + f->log_path = 0; // Override from user-specified string. ParseFlagsFromString(f, __asan_default_options()); @@ -295,6 +297,7 @@ void __asan_init() { // initialization steps look at flags(). const char *options = GetEnv("ASAN_OPTIONS"); InitializeFlags(flags(), options); + __sanitizer_set_report_path(flags()->log_path); if (flags()->verbosity && options) { Report("Parsed ASAN_OPTIONS: %s\n", options); diff --git a/lib/asan/lit_tests/log-path_test.cc b/lib/asan/lit_tests/log-path_test.cc new file mode 100644 index 000000000..1072670fb --- /dev/null +++ b/lib/asan/lit_tests/log-path_test.cc @@ -0,0 +1,39 @@ +// RUN: %clangxx_asan %s -o %t + +// Regular run. +// RUN: not %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.out + +// Good log_path. +// RUN: rm -f %t.log.* +// RUN: ASAN_OPTIONS=log_path=%t.log not %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.* + +// Invalid log_path. +// RUN: ASAN_OPTIONS=log_path=/INVALID not %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-INVALID < %t.out + +// Too long log_path. +// RUN: ASAN_OPTIONS=log_path=`for((i=0;i<10000;i++)); do echo -n $i; done` \ +// RUN: not %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-LONG < %t.out + +// Run w/o errors should not produce any log. +// RUN: rm -f %t.log.* +// RUN: ASAN_OPTIONS=log_path=%t.log %t ARG ARG ARG +// RUN: not cat %t.log.* + + +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + if (argc > 2) return 0; + char *x = (char*)malloc(10); + memset(x, 0, 10); + int res = x[argc * 10]; // BOOOM + free(x); + return res; +} +// CHECK-ERROR: ERROR: AddressSanitizer +// CHECK-INVALID: ERROR: Can't open file: /INVALID +// CHECK-LONG: ERROR: Path is too long: 01234 diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 22c7093db..614b7b9d4 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -16,6 +16,9 @@ namespace __sanitizer { +static fd_t report_fd = 2; // By default, dump to stderr. +static char report_path[4096]; // Set via __sanitizer_set_report_path. + static void (*DieCallback)(void); void SetDieCallback(void (*callback)(void)) { DieCallback = callback; @@ -46,8 +49,17 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, void RawWrite(const char *buffer) { static const char *kRawWriteError = "RawWrite can't output requested buffer!"; uptr length = (uptr)internal_strlen(buffer); - if (length != internal_write(2, buffer, length)) { - internal_write(2, kRawWriteError, internal_strlen(kRawWriteError)); + if (report_fd == kInvalidFd) { + fd_t fd = internal_open(report_path, true); + if (fd == kInvalidFd) { + report_fd = 2; + Report("ERROR: Can't open file: %s\n", report_path); + Die(); + } + report_fd = fd; + } + if (length != internal_write(report_fd, buffer, length)) { + internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError)); Die(); } } @@ -125,3 +137,17 @@ void SortArray(uptr *array, uptr size) { } } // namespace __sanitizer + +void __sanitizer_set_report_path(const char *path) { + if (!path) return; + uptr len = internal_strlen(path); + if (len > sizeof(__sanitizer::report_path) - 100) { + Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", + path[0], path[1], path[2], path[3], + path[4], path[5], path[6], path[7]); + Die(); + } + internal_snprintf(__sanitizer::report_path, + sizeof(__sanitizer::report_path), "%s.%d", path, GetPid()); + __sanitizer::report_fd = kInvalidFd; +} diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 22f10fb1a..6aeedabdf 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -86,7 +86,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) { int VSNPrintf(char *buff, int buff_length, const char *format, va_list args) { static const char *kPrintfFormatsHelp = "Supported Printf formats: " - "%%[z]{d,u,x}; %%p; %%s\n"; + "%%[z]{d,u,x}; %%p; %%s; %%c\n"; RAW_CHECK(format); RAW_CHECK(buff_length > 0); const char *buff_end = &buff[buff_length - 1]; @@ -127,6 +127,11 @@ int VSNPrintf(char *buff, int buff_length, result += AppendString(&buff, buff_end, va_arg(args, char*)); break; } + case 'c': { + RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + result += AppendChar(&buff, buff_end, va_arg(args, uptr)); + break; + } case '%' : { RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); result += AppendChar(&buff, buff_end, '%'); |