[compiler-rt] r287957 - [asan] Add a "dump_registers" flag to print out CPU registers after a SIGSEGV

Kuba Mracek via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 25 16:50:08 PST 2016


Author: kuba.brecka
Date: Fri Nov 25 18:50:08 2016
New Revision: 287957

URL: http://llvm.org/viewvc/llvm-project?rev=287957&view=rev
Log:
[asan] Add a "dump_registers" flag to print out CPU registers after a SIGSEGV

This patch prints out all CPU registers after a SIGSEGV. These are available in the signal handler context. Only implemented for Darwin. Can be turned off with the dump_registers flag.

Differential Revision: https://reviews.llvm.org/D11365


Added:
    compiler-rt/trunk/test/asan/TestCases/Darwin/dump_registers.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_errors.cc
    compiler-rt/trunk/lib/asan/asan_flags.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc

Modified: compiler-rt/trunk/lib/asan/asan_errors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_errors.cc?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.cc Fri Nov 25 18:50:08 2016
@@ -53,6 +53,11 @@ static void MaybeDumpInstructionBytes(up
   Report("%s", str.data());
 }
 
+static void MaybeDumpRegisters(void *context) {
+  if (!flags()->dump_registers) return;
+  SignalContext::DumpAllRegisters(context);
+}
+
 void ErrorDeadlySignal::Print() {
   Decorator d;
   Printf("%s", d.Warning());
@@ -78,6 +83,7 @@ void ErrorDeadlySignal::Print() {
                                   common_flags()->fast_unwind_on_fatal);
   stack.Print();
   MaybeDumpInstructionBytes(pc);
+  MaybeDumpRegisters(context);
   Printf("AddressSanitizer can not provide additional info.\n");
   ReportErrorSummary(description, &stack);
 }

Modified: compiler-rt/trunk/lib/asan/asan_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.inc?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.inc (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.inc Fri Nov 25 18:50:08 2016
@@ -133,6 +133,9 @@ ASAN_FLAG(int, detect_odr_violation, 2,
           "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 "

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Fri Nov 25 18:50:08 2016
@@ -798,6 +798,8 @@ struct SignalContext {
         is_memory_access(is_memory_access),
         write_flag(write_flag) {}
 
+  static void DumpAllRegisters(void *context);
+
   // Creates signal context in a platform-specific manner.
   static SignalContext Create(void *siginfo, void *context);
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Fri Nov 25 18:50:08 2016
@@ -1304,6 +1304,10 @@ SignalContext::WriteFlag SignalContext::
 #endif
 }
 
+void SignalContext::DumpAllRegisters(void *context) {
+  // FIXME: Implement this.
+}
+
 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
 #if defined(__arm__)
   ucontext_t *ucontext = (ucontext_t*)context;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Fri Nov 25 18:50:08 2016
@@ -793,6 +793,56 @@ uptr FindAvailableMemoryRange(uptr shado
 // FIXME implement on this platform.
 void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
 
+void SignalContext::DumpAllRegisters(void *context) {
+  Report("Register values:\n");
+
+  ucontext_t *ucontext = (ucontext_t*)context;
+# define DUMPREG64(r) \
+    Printf("%s = 0x%016llx  ", #r, ucontext->uc_mcontext->__ss.__ ## r);
+# define DUMPREG32(r) \
+    Printf("%s = 0x%08x  ", #r, ucontext->uc_mcontext->__ss.__ ## r);
+# define DUMPREG_(r)   Printf(" "); DUMPREG(r);
+# define DUMPREG__(r)  Printf("  "); DUMPREG(r);
+# define DUMPREG___(r) Printf("   "); DUMPREG(r);
+
+# if defined(__x86_64__)
+#  define DUMPREG(r) DUMPREG64(r)
+  DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
+  DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
+  DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
+  DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
+# elif defined(__i386__)
+#  define DUMPREG(r) DUMPREG32(r)
+  DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
+  DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
+# elif defined(__aarch64__)
+#  define DUMPREG(r) DUMPREG64(r)
+  DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
+  DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
+  DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
+  DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
+  DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
+  DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
+  DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
+  DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n");
+# elif defined(__arm__)
+#  define DUMPREG(r) DUMPREG32(r)
+  DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
+  DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
+  DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
+  DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
+# else
+# error "Unknown architecture"
+# endif
+
+# undef DUMPREG64
+# undef DUMPREG32
+# undef DUMPREG_
+# undef DUMPREG__
+# undef DUMPREG___
+# undef DUMPREG
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=287957&r1=287956&r2=287957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Fri Nov 25 18:50:08 2016
@@ -872,6 +872,10 @@ SignalContext SignalContext::Create(void
                        write_flag);
 }
 
+void SignalContext::DumpAllRegisters(void *context) {
+  // FIXME: Implement this.
+}
+
 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
   // FIXME: Actually implement this function.
   CHECK_GT(buf_len, 0);

Added: compiler-rt/trunk/test/asan/TestCases/Darwin/dump_registers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Darwin/dump_registers.cc?rev=287957&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Darwin/dump_registers.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Darwin/dump_registers.cc Fri Nov 25 18:50:08 2016
@@ -0,0 +1,26 @@
+// Check that ASan dumps the CPU registers on a SIGSEGV.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+  fprintf(stderr, "Hello\n");
+  char *ptr;
+
+  if (sizeof(void *) == 8)
+    ptr = (char *)0x6666666666666666;
+  else if (sizeof(void *) == 4)
+    ptr = (char *)0x55555555;
+  else
+    assert(0 && "Your computer is weird.");
+
+  char c = *ptr;  // BOOM
+  // CHECK: ERROR: AddressSanitizer: SEGV
+  // CHECK: Register values:
+  // CHECK: {{0x55555555|0x6666666666666666}}
+  fprintf(stderr, "World\n");
+  return c;
+}




More information about the llvm-commits mailing list