Index: compiler-rt/trunk/lib/asan/asan_descriptions.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_descriptions.h +++ compiler-rt/trunk/lib/asan/asan_descriptions.h @@ -69,7 +69,6 @@ return Default(); } } - const char *MemoryByte() { return Magenta(); } }; enum ShadowKind : u8 { Index: compiler-rt/trunk/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.cc +++ compiler-rt/trunk/lib/asan/asan_errors.cc @@ -38,37 +38,6 @@ ReportErrorSummary(scariness.GetDescription(), &stack); } -static void MaybeDumpInstructionBytes(uptr pc) { - if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) return; - InternalScopedString str(1024); - str.append("First 16 instruction bytes at pc: "); - if (IsAccessibleMemoryRange(pc, 16)) { - for (int i = 0; i < 16; ++i) { - PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/ false, " "); - } - str.append("\n"); - } else { - str.append("unaccessible\n"); - } - Report("%s", str.data()); -} - -static void MaybeDumpRegisters(void *context) { - if (!flags()->dump_registers) return; - SignalContext::DumpAllRegisters(context); -} - -static void MaybeReportNonExecRegion(uptr pc) { -#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD - MemoryMappingLayout proc_maps(/*cache_enabled*/ true); - MemoryMappedSegment segment; - while (proc_maps.Next(&segment)) { - if (pc >= segment.start && pc < segment.end && !segment.IsExecutable()) - Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n"); - } -#endif -} - void ErrorDeadlySignal::Print() { Decorator d; Printf("%s", d.Warning()); Index: compiler-rt/trunk/lib/asan/asan_flags.inc =================================================================== --- compiler-rt/trunk/lib/asan/asan_flags.inc +++ compiler-rt/trunk/lib/asan/asan_flags.inc @@ -147,11 +147,6 @@ "If >=2, detect violation of One-Definition-Rule (ODR); " "If ==1, detect ODR-violation only if the two variables " "have different sizes") -ASAN_FLAG(bool, dump_instruction_bytes, false, - "If true, dump 16 bytes starting at the instruction that caused SEGV") -ASAN_FLAG(bool, dump_registers, true, - "If true, dump values of CPU registers when SEGV happens. Only " - "available on OS X for now.") ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.") ASAN_FLAG(bool, halt_on_error, true, "Crash the program after printing the first error report " Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h @@ -313,6 +313,10 @@ // Signal reporting. void StartReportDeadlySignal(); bool IsStackOverflow(int code, const SignalContext &sig); +// FIXME: Hide after moving more signal handling code into common. +void MaybeReportNonExecRegion(uptr pc); +void MaybeDumpInstructionBytes(uptr pc); +void MaybeDumpRegisters(void *context); // Alternative signal stack (POSIX-only). void SetAlternateSignalStack(); void UnsetAlternateSignalStack(); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -16,6 +16,8 @@ #include "sanitizer_allocator_interface.h" #include "sanitizer_file.h" #include "sanitizer_flags.h" +#include "sanitizer_procmaps.h" +#include "sanitizer_report_decorator.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" #include "sanitizer_symbolizer.h" @@ -145,6 +147,45 @@ } #endif +void MaybeReportNonExecRegion(uptr pc) { +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD + MemoryMappingLayout proc_maps(/*cache_enabled*/ true); + MemoryMappedSegment segment; + while (proc_maps.Next(&segment)) { + if (pc >= segment.start && pc < segment.end && !segment.IsExecutable()) + Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n"); + } +#endif +} + +static void PrintMemoryByte(InternalScopedString *str, const char *before, + u8 byte) { + SanitizerCommonDecorator d; + str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15, + d.Default()); +} + +void MaybeDumpInstructionBytes(uptr pc) { + if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) + return; + InternalScopedString str(1024); + str.append("First 16 instruction bytes at pc: "); + if (IsAccessibleMemoryRange(pc, 16)) { + for (int i = 0; i < 16; ++i) { + PrintMemoryByte(&str, "", ((u8 *)pc)[i]); + } + str.append("\n"); + } else { + str.append("unaccessible\n"); + } + Report("%s", str.data()); +} + +void MaybeDumpRegisters(void *context) { + if (!common_flags()->dump_registers) return; + SignalContext::DumpAllRegisters(context); +} + void WriteToSyslog(const char *msg) { InternalScopedString msg_copy(kErrorMessageBufferSize); msg_copy.append("%s", msg); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc @@ -229,3 +229,8 @@ "(asan only).") COMMON_FLAG(bool, html_cov_report, false, "Generate html coverage report.") COMMON_FLAG(const char *, sancov_path, "sancov", "Sancov tool location.") +COMMON_FLAG(bool, dump_instruction_bytes, false, + "If true, dump 16 bytes starting at the instruction that caused SEGV") +COMMON_FLAG(bool, dump_registers, true, + "If true, dump values of CPU registers when SEGV happens. Only " + "available on OS X for now.") Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_report_decorator.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_report_decorator.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_report_decorator.h @@ -28,6 +28,7 @@ const char *Bold() const { return ansi_ ? "\033[1m" : ""; } const char *Default() const { return ansi_ ? "\033[1m\033[0m" : ""; } const char *Warning() const { return Red(); } + const char *MemoryByte() { return Magenta(); } protected: const char *Black() const { return ansi_ ? "\033[1m\033[30m" : ""; } Index: compiler-rt/trunk/test/asan/TestCases/Posix/dump_instruction_bytes.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Posix/dump_instruction_bytes.cc +++ compiler-rt/trunk/test/asan/TestCases/Posix/dump_instruction_bytes.cc @@ -1,20 +0,0 @@ -// Check that ASan prints the faulting instruction bytes on -// dump_instruction_bytes=1 -// RUN: %clangxx_asan %s -o %t -// RUN: %env_asan_opts=dump_instruction_bytes=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP -// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP -// -// REQUIRES: x86-target-arch - -int main() { -#if defined(__x86_64__) - asm("movq $0, %rax"); - asm("movl $0xcafebabe, 0x0(%rax)"); -#elif defined(i386) - asm("movl $0, %eax"); - asm("movl $0xcafebabe, 0x0(%eax)"); -#endif - // CHECK-DUMP: First 16 instruction bytes at pc: c7 00 be ba fe ca - // CHECK-NODUMP-NOT: First 16 instruction bytes - return 0; -} Index: compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc =================================================================== --- compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc +++ compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc @@ -0,0 +1,21 @@ +// Check that sanitizer prints the faulting instruction bytes on +// dump_instruction_bytes=1 +// RUN: %clangxx %s -o %t +// RUN: %env_tool_opts=dump_instruction_bytes=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP +// +// REQUIRES: x86-target-arch +// XFAIL: lsan, msan, tsan, ubsan + +int main() { +#if defined(__x86_64__) + asm("movq $0, %rax"); + asm("movl $0xcafebabe, 0x0(%rax)"); +#elif defined(i386) + asm("movl $0, %eax"); + asm("movl $0xcafebabe, 0x0(%eax)"); +#endif + // CHECK-DUMP: First 16 instruction bytes at pc: c7 00 be ba fe ca + // CHECK-NODUMP-NOT: First 16 instruction bytes + return 0; +}