Skip to content

Commit 073cea6

Browse files
committed
[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 llvm-svn: 287957
1 parent a363d42 commit 073cea6

File tree

7 files changed

+95
-0
lines changed

7 files changed

+95
-0
lines changed

compiler-rt/lib/asan/asan_errors.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ static void MaybeDumpInstructionBytes(uptr pc) {
5353
Report("%s", str.data());
5454
}
5555

56+
static void MaybeDumpRegisters(void *context) {
57+
if (!flags()->dump_registers) return;
58+
SignalContext::DumpAllRegisters(context);
59+
}
60+
5661
void ErrorDeadlySignal::Print() {
5762
Decorator d;
5863
Printf("%s", d.Warning());
@@ -78,6 +83,7 @@ void ErrorDeadlySignal::Print() {
7883
common_flags()->fast_unwind_on_fatal);
7984
stack.Print();
8085
MaybeDumpInstructionBytes(pc);
86+
MaybeDumpRegisters(context);
8187
Printf("AddressSanitizer can not provide additional info.\n");
8288
ReportErrorSummary(description, &stack);
8389
}

compiler-rt/lib/asan/asan_flags.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ ASAN_FLAG(int, detect_odr_violation, 2,
133133
"have different sizes")
134134
ASAN_FLAG(bool, dump_instruction_bytes, false,
135135
"If true, dump 16 bytes starting at the instruction that caused SEGV")
136+
ASAN_FLAG(bool, dump_registers, true,
137+
"If true, dump values of CPU registers when SEGV happens. Only "
138+
"available on OS X for now.")
136139
ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
137140
ASAN_FLAG(bool, halt_on_error, true,
138141
"Crash the program after printing the first error report "

compiler-rt/lib/sanitizer_common/sanitizer_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ struct SignalContext {
798798
is_memory_access(is_memory_access),
799799
write_flag(write_flag) {}
800800

801+
static void DumpAllRegisters(void *context);
802+
801803
// Creates signal context in a platform-specific manner.
802804
static SignalContext Create(void *siginfo, void *context);
803805

compiler-rt/lib/sanitizer_common/sanitizer_linux.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,10 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) {
13041304
#endif
13051305
}
13061306

1307+
void SignalContext::DumpAllRegisters(void *context) {
1308+
// FIXME: Implement this.
1309+
}
1310+
13071311
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
13081312
#if defined(__arm__)
13091313
ucontext_t *ucontext = (ucontext_t*)context;

compiler-rt/lib/sanitizer_common/sanitizer_mac.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,56 @@ uptr FindAvailableMemoryRange(uptr shadow_size,
793793
// FIXME implement on this platform.
794794
void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
795795

796+
void SignalContext::DumpAllRegisters(void *context) {
797+
Report("Register values:\n");
798+
799+
ucontext_t *ucontext = (ucontext_t*)context;
800+
# define DUMPREG64(r) \
801+
Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
802+
# define DUMPREG32(r) \
803+
Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
804+
# define DUMPREG_(r) Printf(" "); DUMPREG(r);
805+
# define DUMPREG__(r) Printf(" "); DUMPREG(r);
806+
# define DUMPREG___(r) Printf(" "); DUMPREG(r);
807+
808+
# if defined(__x86_64__)
809+
# define DUMPREG(r) DUMPREG64(r)
810+
DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
811+
DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
812+
DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
813+
DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
814+
# elif defined(__i386__)
815+
# define DUMPREG(r) DUMPREG32(r)
816+
DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
817+
DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
818+
# elif defined(__aarch64__)
819+
# define DUMPREG(r) DUMPREG64(r)
820+
DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
821+
DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
822+
DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
823+
DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
824+
DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
825+
DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
826+
DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
827+
DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n");
828+
# elif defined(__arm__)
829+
# define DUMPREG(r) DUMPREG32(r)
830+
DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
831+
DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
832+
DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
833+
DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
834+
# else
835+
# error "Unknown architecture"
836+
# endif
837+
838+
# undef DUMPREG64
839+
# undef DUMPREG32
840+
# undef DUMPREG_
841+
# undef DUMPREG__
842+
# undef DUMPREG___
843+
# undef DUMPREG
844+
}
845+
796846
} // namespace __sanitizer
797847

798848
#endif // SANITIZER_MAC

compiler-rt/lib/sanitizer_common/sanitizer_win.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,10 @@ SignalContext SignalContext::Create(void *siginfo, void *context) {
872872
write_flag);
873873
}
874874

875+
void SignalContext::DumpAllRegisters(void *context) {
876+
// FIXME: Implement this.
877+
}
878+
875879
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
876880
// FIXME: Actually implement this function.
877881
CHECK_GT(buf_len, 0);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Check that ASan dumps the CPU registers on a SIGSEGV.
2+
3+
// RUN: %clangxx_asan %s -o %t
4+
// RUN: not %run %t 2>&1 | FileCheck %s
5+
6+
#include <assert.h>
7+
#include <stdio.h>
8+
9+
int main() {
10+
fprintf(stderr, "Hello\n");
11+
char *ptr;
12+
13+
if (sizeof(void *) == 8)
14+
ptr = (char *)0x6666666666666666;
15+
else if (sizeof(void *) == 4)
16+
ptr = (char *)0x55555555;
17+
else
18+
assert(0 && "Your computer is weird.");
19+
20+
char c = *ptr; // BOOM
21+
// CHECK: ERROR: AddressSanitizer: SEGV
22+
// CHECK: Register values:
23+
// CHECK: {{0x55555555|0x6666666666666666}}
24+
fprintf(stderr, "World\n");
25+
return c;
26+
}

0 commit comments

Comments
 (0)