forked from OSchip/llvm-project
[asan] add asan option log_path=PATH to let users redirect asan reports to a file PATH.PID instead of stderr
llvm-svn: 163872
This commit is contained in:
parent
6d149412c8
commit
45d849c4bd
|
@ -53,4 +53,10 @@ typedef signed long long s64; // NOLINT
|
|||
|
||||
} // namespace __sanitizer
|
||||
|
||||
extern "C" {
|
||||
// Tell the tools to write their reports to "path.<pid>" instead of stderr.
|
||||
void __sanitizer_set_report_path(const char *path)
|
||||
SANITIZER_INTERFACE_ATTRIBUTE;
|
||||
} // extern "C"
|
||||
|
||||
#endif // SANITIZER_COMMON_INTERFACE_DEFS_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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, '%');
|
||||
|
|
Loading…
Reference in New Issue