Index: lib/asan/asan_flags.inc =================================================================== --- lib/asan/asan_flags.inc +++ lib/asan/asan_flags.inc @@ -135,3 +135,4 @@ ASAN_FLAG(bool, halt_on_error, true, "Crash the program after printing the first error report " "(WARNING: USE AT YOUR OWN RISK!)") +ASAN_FLAG(bool, print_cmdline, false, "Print cmdline on crash.") Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -238,6 +238,16 @@ DescribeThread(t->context()); } +static void PrintReproducerCmdline() { + char **argv, **envp; + __sanitizer::GetArgsAndEnv(&argv, &envp); + + Printf("\nReproducer cmdline: "); + for (uptr i = 0; argv[i] != 0; ++i) + Printf("%s ", argv[i]); + Printf("\n\n"); +} + // ---------------------- Address Descriptions ------------------- {{{1 static bool IsASCII(unsigned char c) { @@ -687,6 +697,9 @@ if (flags()->print_stats) __asan_print_accumulated_stats(); + if (flags()->print_cmdline) + PrintReproducerCmdline(); + // Copy the message buffer so that we could start logging without holding a // lock that gets aquired during printing. InternalScopedBuffer buffer_copy(kErrorMessageBufferSize); Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -282,6 +282,7 @@ u32 GetUid(); void ReExec(); +void GetArgsAndEnv(char ***argv, char ***envp); bool StackSizeIsUnlimited(); void SetStackSizeLimitInBytes(uptr limit); bool AddressSpaceIsUnlimited(); Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -424,7 +424,7 @@ } #endif -static void GetArgsAndEnv(char*** argv, char*** envp) { +void GetArgsAndEnv(char ***argv, char ***envp) { #if !SANITIZER_GO if (&__libc_stack_end) { #endif Index: test/asan/TestCases/Posix/print_cmdline.cc =================================================================== --- /dev/null +++ test/asan/TestCases/Posix/print_cmdline.cc @@ -0,0 +1,19 @@ +// Check that ASan can print reproducer cmdline for failed binary if desired. +// +// RUN: %clang_asan %s -o %t-exe +// +// RUN: env not %run %t-exe 2>&1 | FileCheck %s +// RUN: %env_asan_opts=print_cmdline=false not %run %t-exe 2>&1 | FileCheck %s --check-prefix CHECK-DONT-PRINT +// RUN: %env_asan_opts=print_cmdline=true not %run %t-exe first second/third [fourth] 2>&1 | FileCheck %s --check-prefix CHECK-PRINT + +volatile int ten = 10; + +int main() { + char x[10]; + // CHECK-NOT: Reproducer cmdline: + // CHECK-DONT-PRINT-NOT: Reproducer cmdline: + // CHECK-PRINT: {{Reproducer cmdline: .*-exe first second/third \[fourth\]}} + x[ten] = 1; // BOOM + return 0; +} +