" (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);
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();
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;
// 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__)
}
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
#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) {
--- /dev/null
+// 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.