Index: compiler-rt/lib/asan/asan_posix.cc =================================================================== --- compiler-rt/lib/asan/asan_posix.cc +++ compiler-rt/lib/asan/asan_posix.cc @@ -36,7 +36,7 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); StartReportDeadlySignal(); - SignalContext sig = SignalContext::Create(siginfo, context); + SignalContext sig(siginfo, context); if (IsStackOverflow(sig)) ReportStackOverflow(sig); else Index: compiler-rt/lib/asan/asan_win.cc =================================================================== --- compiler-rt/lib/asan/asan_win.cc +++ compiler-rt/lib/asan/asan_win.cc @@ -57,7 +57,7 @@ // FIXME: Handle EXCEPTION_STACK_OVERFLOW here. - SignalContext sig = SignalContext::Create(exception_record, context); + SignalContext sig(exception_record, context); ReportDeadlySignal(sig); UNREACHABLE("returned from reporting deadly signal"); } Index: compiler-rt/lib/sanitizer_common/sanitizer_common.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -801,41 +801,39 @@ uptr sp; uptr bp; bool is_memory_access; - enum WriteFlag { UNKNOWN, READ, WRITE } write_flag; // VS2013 doesn't implement unrestricted unions, so we need a trivial default // constructor SignalContext() = default; + + // Creates signal context in a platform-specific manner. // SignalContext is going to keep pointers to siginfo and context without // owning them. - SignalContext(void *siginfo, void *context, uptr addr, uptr pc, uptr sp, - uptr bp, bool is_memory_access, WriteFlag write_flag) + SignalContext(void *siginfo, void *context) : siginfo(siginfo), context(context), - addr(addr), - pc(pc), - sp(sp), - bp(bp), - is_memory_access(is_memory_access), - write_flag(write_flag) {} + addr(GetAddress()), + is_memory_access(IsMemoryAccess()), + write_flag(GetWriteFlag()) { + InitPcSpBp(); + } static void DumpAllRegisters(void *context); - // Creates signal context in a platform-specific manner. - static SignalContext Create(void *siginfo, void *context); - - // Returns true if the "context" indicates a memory write. - static WriteFlag GetWriteFlag(void *context); - // Type of signal e.g. SIGSEGV or EXCEPTION_ACCESS_VIOLATION. int GetType() const; // String description of the signal. const char *Describe() const; -}; -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); + private: + // Platform specific initialization. + void InitPcSpBp(); + uptr GetAddress() const; + WriteFlag GetWriteFlag() const; + bool IsMemoryAccess() const; +}; void MaybeReexec(); Index: compiler-rt/lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1628,7 +1628,7 @@ } #endif -SignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) { +SignalContext::WriteFlag SignalContext::GetWriteFlag() const { ucontext_t *ucontext = (ucontext_t *)context; #if defined(__x86_64__) || defined(__i386__) static const uptr PF_WRITE = 1U << 1; @@ -1659,7 +1659,7 @@ // FIXME: Implement this. } -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { +static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { #if defined(__arm__) ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.arm_pc; @@ -1750,6 +1750,8 @@ #endif } +void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } + void MaybeReexec() { // No need to re-exec on Linux. } Index: compiler-rt/lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -574,7 +574,7 @@ #endif } -SignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) { +SignalContext::WriteFlag SignalContext::GetWriteFlag() const { #if defined(__x86_64__) || defined(__i386__) ucontext_t *ucontext = static_cast(context); return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ; @@ -583,7 +583,7 @@ #endif } -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { +static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { ucontext_t *ucontext = (ucontext_t*)context; # if defined(__aarch64__) *pc = ucontext->uc_mcontext->__ss.__pc; @@ -610,6 +610,8 @@ # endif } +void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } + #if !SANITIZER_GO static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; LowLevelAllocator allocator_for_env; Index: compiler-rt/lib/sanitizer_common/sanitizer_posix.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -295,15 +295,14 @@ return false; } -SignalContext SignalContext::Create(void *siginfo, void *context) { +uptr SignalContext::GetAddress() const { auto si = static_cast(siginfo); - uptr addr = (uptr)si->si_addr; - uptr pc, sp, bp; - GetPcSpBp(context, &pc, &sp, &bp); - WriteFlag write_flag = GetWriteFlag(context); - bool is_memory_access = si->si_signo == SIGSEGV; - return SignalContext(siginfo, context, addr, pc, sp, bp, is_memory_access, - write_flag); + return (uptr)si->si_addr; +} + +bool SignalContext::IsMemoryAccess() const { + auto si = static_cast(siginfo); + return si->si_signo == SIGSEGV; } int SignalContext::GetType() const { Index: compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -246,7 +246,7 @@ // Signal handler to wake up suspended threads when the tracer thread dies. static void TracerThreadSignalHandler(int signum, void *siginfo, void *uctx) { - SignalContext ctx = SignalContext::Create(siginfo, uctx); + SignalContext ctx(siginfo, uctx); Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum, ctx.addr, ctx.pc, ctx.sp); ThreadSuspender *inst = thread_suspender_instance; Index: compiler-rt/lib/sanitizer_common/sanitizer_win.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -915,33 +915,48 @@ return true; } -SignalContext SignalContext::Create(void *siginfo, void *context) { +void SignalContext::InitPcSpBp() { EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; CONTEXT *context_record = (CONTEXT *)context; - uptr pc = (uptr)exception_record->ExceptionAddress; + pc = (uptr)exception_record->ExceptionAddress; #ifdef _WIN64 - uptr bp = (uptr)context_record->Rbp; - uptr sp = (uptr)context_record->Rsp; + bp = (uptr)context_record->Rbp; + sp = (uptr)context_record->Rsp; #else - uptr bp = (uptr)context_record->Ebp; - uptr sp = (uptr)context_record->Esp; + bp = (uptr)context_record->Ebp; + sp = (uptr)context_record->Esp; #endif - uptr access_addr = exception_record->ExceptionInformation[1]; +} + +uptr SignalContext::GetAddress() const { + EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; + return exception_record->ExceptionInformation[1]; +} + +bool SignalContext::IsMemoryAccess() const { + return GetWriteFlag() != SignalContext::UNKNOWN; +} +int SignalContext::GetType() const { + return static_cast(siginfo)->si_signo; +} + +SignalContext::WriteFlag SignalContext::GetWriteFlag() const { + EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; // The contents of this array are documented at // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx // The first element indicates read as 0, write as 1, or execute as 8. The // second element is the faulting address. - WriteFlag write_flag = SignalContext::UNKNOWN; switch (exception_record->ExceptionInformation[0]) { - case 0: write_flag = SignalContext::READ; break; - case 1: write_flag = SignalContext::WRITE; break; - case 8: write_flag = SignalContext::UNKNOWN; break; + case 0: + return SignalContext::READ; + case 1: + return SignalContext::WRITE; + case 8: + return SignalContext::UNKNOWN; } - bool is_memory_access = write_flag != SignalContext::UNKNOWN; - return SignalContext(siginfo, context, access_addr, pc, sp, bp, - is_memory_access, write_flag); + return SignalContext::UNKNOWN; } void SignalContext::DumpAllRegisters(void *context) {