From 1dd3584ec06d034aaf897edec30b3adb4cb2df25 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Wed, 25 Apr 2018 16:21:00 +0000 Subject: [PATCH] [mips] Implement GetWriteFlag() for mips The read/write flag is set by manually decoding the instruction that caused the exception. It is implemented this way because the cause register which contains the needed flag was removed from the signal context structure which the user handler receives from the kernel. Patch by Milos Stojanovic. Differential Revision: https://reviews.llvm.org/D45768 llvm-svn: 330840 --- .../lib/sanitizer_common/sanitizer_linux.cc | 49 ++++++++++++++++++++++ .../TestCases/Posix/illegal_read_test.cc | 14 +++++++ .../TestCases/Posix/illegal_write_test.cc | 13 ++++++ 3 files changed, 76 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 0669618..94bc9ff 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1736,6 +1736,55 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const { uptr err = ucontext->uc_mcontext.gregs[REG_ERR]; #endif // SANITIZER_FREEBSD return err & PF_WRITE ? WRITE : READ; +#elif defined(__mips__) + uint32_t *exception_source; + uint32_t faulty_instruction; + uint32_t op_code; + + exception_source = (uint32_t *)ucontext->uc_mcontext.pc; + faulty_instruction = (uint32_t)(*exception_source); + + op_code = (faulty_instruction >> 26) & 0x3f; + + // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions. + switch (op_code) { + case 0x28: // sb + case 0x29: // sh + case 0x2b: // sw + case 0x3f: // sd +#if __mips_isa_rev < 6 + case 0x2c: // sdl + case 0x2d: // sdr + case 0x2a: // swl + case 0x2e: // swr +#endif + return SignalContext::WRITE; + + case 0x20: // lb + case 0x24: // lbu + case 0x21: // lh + case 0x25: // lhu + case 0x23: // lw + case 0x27: // lwu + case 0x37: // ld +#if __mips_isa_rev < 6 + case 0x1a: // ldl + case 0x1b: // ldr + case 0x22: // lwl + case 0x26: // lwr +#endif + return SignalContext::READ; +#if __mips_isa_rev == 6 + case 0x3b: // pcrel + op_code = (faulty_instruction >> 19) & 0x3; + switch (op_code) { + case 0x1: // lwpc + case 0x2: // lwupc + return SignalContext::READ; + } +#endif + } + return SignalContext::UNKNOWN; #elif defined(__arm__) static const uptr FSR_WRITE = 1U << 11; uptr fsr = ucontext->uc_mcontext.error_code; diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc b/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc new file mode 100644 index 0000000..1cfd0d6 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc @@ -0,0 +1,14 @@ +// Test that there was an illegal READ memory access. +// RUN: %clangxx -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +volatile int *null = 0; +volatile int a; + +int main(int argc, char **argv) { + a = *null; + return 0; +} + +// CHECK: The signal is caused by a READ memory access. diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc b/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc new file mode 100644 index 0000000..b76e905 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc @@ -0,0 +1,13 @@ +// Test that there was an illegal WRITE memory access. +// RUN: %clangxx -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +volatile int *null = 0; + +int main(int argc, char **argv) { + *null = 0; + return 0; +} + +// CHECK: The signal is caused by a WRITE memory access. -- 2.7.4