diff options
author | Kostya Serebryany <kcc@google.com> | 2016-02-04 02:02:09 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2016-02-04 02:02:09 +0000 |
commit | 2b9be250660eaf563fc9a3520363b7f19569daf1 (patch) | |
tree | cdbbf1887c8640137ed1518636cb4788d351c060 | |
parent | 155402c9c23b12fcbb49d31bc7e238ecd88c999e (diff) | |
download | bcm5719-llvm-2b9be250660eaf563fc9a3520363b7f19569daf1.tar.gz bcm5719-llvm-2b9be250660eaf563fc9a3520363b7f19569daf1.zip |
[asan] When catching a signal caused by a memory access, print if it's a READ or a WRITE. This touches win/mac files which I have not tested, if a win/mac bot fails I'll try to quick-fix
llvm-svn: 259741
7 files changed, 50 insertions, 8 deletions
diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 8cf1bf6406c..f5bfa3cbbdc 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -761,10 +761,15 @@ void ReportDeadlySignal(const char *description, const SignalContext &sig) { " (pc %p bp %p sp %p T%d)\n", description, (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, (void *)sig.sp, GetCurrentTidOrInvalid()); - if (sig.pc < GetPageSizeCached()) { + Printf("%s", d.EndWarning()); + if (sig.pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n"); + if (sig.is_memory_access) { + Report("The signal is caused by a %s memory access.\n", + sig.is_write ? "WRITE" : "READ"); + if (sig.addr < GetPageSizeCached()) + Report("Hint: address points to the zero page.\n"); } - Printf("%s", d.EndWarning()); GET_STACK_TRACE_SIGNAL(sig); stack.Print(); MaybeDumpInstructionBytes(sig.pc); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 5a036b0a3f9..67ec76457a1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -749,15 +749,20 @@ struct SignalContext { uptr pc; uptr sp; uptr bp; + bool is_memory_access; + bool is_write; - SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) : - context(context), addr(addr), pc(pc), sp(sp), bp(bp) { - } + SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp, + bool is_memory_access, bool is_write) + : context(context), addr(addr), pc(pc), sp(sp), bp(bp), + is_memory_access(is_memory_access), is_write(is_write) {} // Creates signal context in a platform-specific manner. static SignalContext Create(void *siginfo, void *context); }; +// Returns true if the "context" indicates a memory write. +bool GetSigContextWriteFlag(void *context); void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); void DisableReexec(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 89fa80e29ab..80009ea4e91 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1155,6 +1155,11 @@ void *internal_start_thread(void (*func)(void *), void *arg) { return 0; } void internal_join_thread(void *th) {} #endif +bool GetSigContextWriteFlag(void *context) { + ucontext_t *ucontext = (ucontext_t*)context; + return ucontext->uc_mcontext.gregs[REG_ERR] & 2; +} + void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { #if defined(__arm__) ucontext_t *ucontext = (ucontext_t*)context; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 073f031889f..632bc7b9373 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -491,6 +491,10 @@ void LogFullErrorReport(const char *buffer) { // The report is added to CrashLog as part of logging all of Printf output. } +bool GetSigContextWriteFlag(void *context) { + return false; // FIXME: implement this. +} + void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { ucontext_t *ucontext = (ucontext_t*)context; # if defined(__aarch64__) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index e677e33c660..e8e9017033f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -323,10 +323,13 @@ bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { } SignalContext SignalContext::Create(void *siginfo, void *context) { - uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; + auto si = (siginfo_t*)siginfo; + uptr addr = (uptr)si->si_addr; uptr pc, sp, bp; GetPcSpBp(context, &pc, &sp, &bp); - return SignalContext(context, addr, pc, sp, bp); + bool is_write = GetSigContextWriteFlag(context); + bool is_memory_access = si->si_signo == SIGSEGV; + return SignalContext(context, addr, pc, sp, bp, is_memory_access, is_write); } } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index 7dd4c071953..0b8026562c1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -744,7 +744,10 @@ SignalContext SignalContext::Create(void *siginfo, void *context) { #endif uptr access_addr = exception_record->ExceptionInformation[1]; - return SignalContext(context, access_addr, pc, sp, bp); + bool is_write = false; // FIXME: compute this. + bool is_memory_access = false; // FIXME: compute this. + return SignalContext(context, access_addr, pc, sp, bp, is_memory_access, + is_write); } uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { diff --git a/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c b/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c new file mode 100644 index 00000000000..84103713737 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c @@ -0,0 +1,17 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=READ +// RUN: not %run %t write 2>&1 | FileCheck %s --check-prefix=WRITE + +static volatile int sink; +__attribute__((noinline)) void Read(int *ptr) { sink = *ptr; } +__attribute__((noinline)) void Write(int *ptr) { *ptr = 0; } +int main(int argc, char **argv) { + if (argc == 1) + Read((int *)0); + else + Write((int *)0); +} +// READ: AddressSanitizer: SEGV on unknown address +// READ: The signal is caused by a READ memory access. +// WRITE: AddressSanitizer: SEGV on unknown address +// WRITE: The signal is caused by a WRITE memory access. |