From 2eaff6eec07f4e8ac7698bde99cd91ef01b7a0b1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 13 Sep 2017 18:30:06 +0000 Subject: [compiler-rt] Add siginfo into SignalContext Summary: Information stored there is often been passed along with SignalContext. Part of https://github.com/google/sanitizers/issues/637 Reviewers: eugenis, alekseyshl Subscribers: kubamracek, llvm-commits, dberris Differential Revision: https://reviews.llvm.org/D37792 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@313167 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_errors.h | 4 ++-- lib/asan/asan_posix.cc | 4 ++-- lib/asan/asan_report.cc | 4 ++-- lib/asan/asan_report.h | 2 +- lib/sanitizer_common/sanitizer_common.h | 18 ++++++++++++++---- lib/sanitizer_common/sanitizer_posix.cc | 9 +++++++-- lib/sanitizer_common/sanitizer_posix_libcdep.cc | 6 ++++-- lib/sanitizer_common/sanitizer_win.cc | 8 ++++++-- 8 files changed, 38 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/asan/asan_errors.h b/lib/asan/asan_errors.h index 9a1249244..55b8360a3 100644 --- a/lib/asan/asan_errors.h +++ b/lib/asan/asan_errors.h @@ -57,14 +57,14 @@ struct ErrorDeadlySignal : ErrorBase { // VS2013 doesn't implement unrestricted unions, so we need a trivial default // constructor ErrorDeadlySignal() = default; - ErrorDeadlySignal(u32 tid, const SignalContext &sig, int signo_) + ErrorDeadlySignal(u32 tid, const SignalContext &sig) : ErrorBase(tid), addr(sig.addr), pc(sig.pc), bp(sig.bp), sp(sig.sp), context(sig.context), - signo(signo_), + signo(sig.GetType()), write_flag(sig.write_flag), is_memory_access(sig.is_memory_access) { scariness.Clear(); diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index 8f788bd13..497af02d7 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -37,10 +37,10 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); StartReportDeadlySignal(); SignalContext sig = SignalContext::Create(siginfo, context); - if (IsStackOverflow(((siginfo_t *)siginfo)->si_code, sig)) + if (IsStackOverflow(sig)) ReportStackOverflow(sig); else - ReportDeadlySignal(signo, sig); + ReportDeadlySignal(sig); } // ---------------------- TSD ---------------- {{{1 diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 312dcaeae..6055304e8 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -266,9 +266,9 @@ void ReportStackOverflow(const SignalContext &sig) { in_report.ReportError(error); } -void ReportDeadlySignal(int signo, const SignalContext &sig) { +void ReportDeadlySignal(const SignalContext &sig) { ScopedInErrorReport in_report(/*fatal*/ true); - ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig, signo); + ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig); in_report.ReportError(error); } diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h index 5a3533a31..259177bc7 100644 --- a/lib/asan/asan_report.h +++ b/lib/asan/asan_report.h @@ -47,7 +47,7 @@ bool ParseFrameDescription(const char *frame_descr, void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, uptr access_size, u32 exp, bool fatal); void ReportStackOverflow(const SignalContext &sig); -void ReportDeadlySignal(int signo, const SignalContext &sig); +void ReportDeadlySignal(const SignalContext &sig); void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack); void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index d2021a0c9..32fd381cc 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -312,7 +312,7 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler); const char *DescribeSignalOrException(int signo); // Signal reporting. void StartReportDeadlySignal(); -bool IsStackOverflow(int code, const SignalContext &sig); +bool IsStackOverflow(const SignalContext &sig); // FIXME: Hide after moving more signal handling code into common. void MaybeReportNonExecRegion(uptr pc); void MaybeDumpInstructionBytes(uptr pc); @@ -795,6 +795,7 @@ static inline void SanitizerBreakOptimization(void *arg) { } struct SignalContext { + void *siginfo; void *context; uptr addr; uptr pc; @@ -804,9 +805,12 @@ struct SignalContext { enum WriteFlag { UNKNOWN, READ, WRITE } write_flag; - SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp, - bool is_memory_access, WriteFlag write_flag) - : context(context), + // 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) + : siginfo(siginfo), + context(context), addr(addr), pc(pc), sp(sp), @@ -821,6 +825,12 @@ struct SignalContext { // 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 { return DescribeSignalOrException(GetType()); } }; void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index b8f4575f7..b74b1f995 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -296,13 +296,18 @@ bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { } SignalContext SignalContext::Create(void *siginfo, void *context) { - auto si = (siginfo_t *)siginfo; + 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(context, addr, pc, sp, bp, is_memory_access, write_flag); + return SignalContext(siginfo, context, addr, pc, sp, bp, is_memory_access, + write_flag); +} + +int SignalContext::GetType() const { + return static_cast(siginfo)->si_signo; } const char *DescribeSignalOrException(int signo) { diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index d7d0e7d44..e49101a7b 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -215,7 +215,7 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) { MaybeInstallSigaction(SIGILL, handler); } -bool IsStackOverflow(int code, const SignalContext &sig) { +bool IsStackOverflow(const SignalContext &sig) { // Access at a reasonable offset above SP, or slightly below it (to account // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is // probably a stack overflow. @@ -257,7 +257,9 @@ bool IsStackOverflow(int code, const SignalContext &sig) { // We also check si_code to filter out SEGV caused by something else other // then hitting the guard page or unmapped memory, like, for example, // unaligned memory access. - return IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR); + auto si = static_cast(sig.siginfo); + return IsStackAccess && + (si->si_code == si_SEGV_MAPERR || si->si_code == si_SEGV_ACCERR); } void StartReportDeadlySignal() { diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index a13a4c5a5..65898a709 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -966,14 +966,18 @@ SignalContext SignalContext::Create(void *siginfo, void *context) { case 8: write_flag = SignalContext::UNKNOWN; break; } bool is_memory_access = write_flag != SignalContext::UNKNOWN; - return SignalContext(context, access_addr, pc, sp, bp, is_memory_access, - write_flag); + return SignalContext(siginfo, context, access_addr, pc, sp, bp, + is_memory_access, write_flag); } void SignalContext::DumpAllRegisters(void *context) { // FIXME: Implement this. } +int SignalContext::GetType() const { + return static_cast(siginfo)->ExceptionCode; +} + uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { // FIXME: Actually implement this function. CHECK_GT(buf_len, 0); -- cgit v1.2.3