[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
This commit is contained in:
Petar Jovanovic 2018-04-25 16:21:00 +00:00
parent f3e043f67b
commit 1dd3584ec0
3 changed files with 76 additions and 0 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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.