diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 483a1042a623837..bc2cb247f2a8a8c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -2172,15 +2172,118 @@ static const char *RegNumToRegName(int reg) { return "ebp"; case REG_ESP: return "esp"; +# elif defined(__arm__) +# define REG_STR(reg) #reg +# define MAKE_CASE(N) \ + case REG_R##N: \ + return REG_STR(r##N) + MAKE_CASE(0); + MAKE_CASE(1); + MAKE_CASE(2); + MAKE_CASE(3); + MAKE_CASE(4); + MAKE_CASE(5); + MAKE_CASE(6); + MAKE_CASE(7); + MAKE_CASE(8); + MAKE_CASE(9); + MAKE_CASE(10); + MAKE_CASE(11); + MAKE_CASE(12); + case REG_R13: + return "sp"; + case REG_R14: + return "lr"; + case REG_R15: + return "pc"; +# elif defined(__aarch64__) +# define REG_STR(reg) #reg +# define MAKE_CASE(N) \ + case N: \ + return REG_STR(x##N) + MAKE_CASE(0); + MAKE_CASE(1); + MAKE_CASE(2); + MAKE_CASE(3); + MAKE_CASE(4); + MAKE_CASE(5); + MAKE_CASE(6); + MAKE_CASE(7); + MAKE_CASE(8); + MAKE_CASE(9); + MAKE_CASE(10); + MAKE_CASE(11); + MAKE_CASE(12); + MAKE_CASE(13); + MAKE_CASE(14); + MAKE_CASE(15); + MAKE_CASE(16); + MAKE_CASE(17); + MAKE_CASE(18); + MAKE_CASE(19); + MAKE_CASE(20); + MAKE_CASE(21); + MAKE_CASE(22); + MAKE_CASE(23); + MAKE_CASE(24); + MAKE_CASE(25); + MAKE_CASE(26); + MAKE_CASE(27); + MAKE_CASE(28); + case 29: + return "fp"; + case 30: + return "lr"; + case 31: + return "sp"; # endif -# endif default: return NULL; } return NULL; } -# if SANITIZER_LINUX +# if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) +static uptr GetArmRegister(ucontext_t *ctx, int RegNum) { + switch (RegNum) { +# if defined(__arm__) +# define MAKE_CASE(N) \ + case REG_R##N: \ + return ctx->uc_mcontext.arm_r##N + MAKE_CASE(0); + MAKE_CASE(1); + MAKE_CASE(2); + MAKE_CASE(3); + MAKE_CASE(4); + MAKE_CASE(5); + MAKE_CASE(6); + MAKE_CASE(7); + MAKE_CASE(8); + MAKE_CASE(9); + MAKE_CASE(10); + case REG_R11: + return ctx->uc_mcontext.arm_fp; + case REG_R12: + return ctx->uc_mcontext.arm_ip; + case REG_R13: + return ctx->uc_mcontext.arm_sp; + case REG_R14: + return ctx->uc_mcontext.arm_lr; + case REG_R15: + return ctx->uc_mcontext.arm_pc; +# elif defined(__aarch64__) + case 0 ... 30: + return ctx->uc_mcontext.regs[RegNum]; + case 31: + return ctx->uc_mcontext.sp; +# endif + default: + return 0; + } + return 0; +} +# endif // SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) + UNUSED static void DumpSingleReg(ucontext_t *ctx, int RegNum) { const char *RegName = RegNumToRegName(RegNum); @@ -2189,6 +2292,12 @@ static void DumpSingleReg(ucontext_t *ctx, int RegNum) { RegName, ctx->uc_mcontext.gregs[RegNum]); # elif defined(__i386__) Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]); +# elif defined(__arm__) + Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName, + GetArmRegister(ctx, RegNum)); +# elif defined(__aarch64__) + Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName, + GetArmRegister(ctx, RegNum)); # else (void)RegName; # endif @@ -2236,6 +2345,35 @@ void SignalContext::DumpAllRegisters(void *context) { DumpSingleReg(ucontext, REG_EBP); DumpSingleReg(ucontext, REG_ESP); Printf("\n"); +# elif defined(__arm__) + Report("Register values:\n"); + DumpSingleReg(ucontext, REG_R0); + DumpSingleReg(ucontext, REG_R1); + DumpSingleReg(ucontext, REG_R2); + DumpSingleReg(ucontext, REG_R3); + Printf("\n"); + DumpSingleReg(ucontext, REG_R4); + DumpSingleReg(ucontext, REG_R5); + DumpSingleReg(ucontext, REG_R6); + DumpSingleReg(ucontext, REG_R7); + Printf("\n"); + DumpSingleReg(ucontext, REG_R8); + DumpSingleReg(ucontext, REG_R9); + DumpSingleReg(ucontext, REG_R10); + DumpSingleReg(ucontext, REG_R11); + Printf("\n"); + DumpSingleReg(ucontext, REG_R12); + DumpSingleReg(ucontext, REG_R13); + DumpSingleReg(ucontext, REG_R14); + DumpSingleReg(ucontext, REG_R15); + Printf("\n"); +# elif defined(__aarch64__) + Report("Register values:\n"); + for (int i = 0; i <= 31; ++i) { + DumpSingleReg(ucontext, i); + if (i % 4 == 3) + Printf("\n"); + } # else (void)ucontext; # endif diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_aarch64.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_aarch64.cpp new file mode 100644 index 000000000000000..e01b826c86b8ac0 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_aarch64.cpp @@ -0,0 +1,23 @@ +// Check that sanitizer prints registers dump_registers on dump_registers=1 +// RUN: %clangxx %s -o %t +// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP +// RUN: not %run %t 2>&1 | FileCheck %s --strict-whitespace --check-prefix=CHECK-DUMP +// +// REQUIRES: aarch64-target-arch + +#include + +int main() { + raise(SIGSEGV); + // CHECK-DUMP: Register values + // CHECK-DUMP-NEXT: x0 = {{0x[0-9a-f]+}} x1 = {{0x[0-9a-f]+}} x2 = {{0x[0-9a-f]+}} x3 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT: x4 = {{0x[0-9a-f]+}} x5 = {{0x[0-9a-f]+}} x6 = {{0x[0-9a-f]+}} x7 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT: x8 = {{0x[0-9a-f]+}} x9 = {{0x[0-9a-f]+}} x10 = {{0x[0-9a-f]+}} x11 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:x12 = {{0x[0-9a-f]+}} x13 = {{0x[0-9a-f]+}} x14 = {{0x[0-9a-f]+}} x15 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:x16 = {{0x[0-9a-f]+}} x17 = {{0x[0-9a-f]+}} x18 = {{0x[0-9a-f]+}} x19 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:x20 = {{0x[0-9a-f]+}} x21 = {{0x[0-9a-f]+}} x22 = {{0x[0-9a-f]+}} x23 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:x24 = {{0x[0-9a-f]+}} x25 = {{0x[0-9a-f]+}} x26 = {{0x[0-9a-f]+}} x27 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:x28 = {{0x[0-9a-f]+}} fp = {{0x[0-9a-f]+}} lr = {{0x[0-9a-f]+}} sp = {{0x[0-9a-f]+}} + // CHECK-NODUMP-NOT: Register values + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_arm.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_arm.cpp new file mode 100644 index 000000000000000..e17dbf196227b67 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_arm.cpp @@ -0,0 +1,19 @@ +// Check that sanitizer prints registers dump_registers on dump_registers=1 +// RUN: %clangxx %s -o %t +// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP +// RUN: not %run %t 2>&1 | FileCheck %s --strict-whitespace --check-prefix=CHECK-DUMP +// +// REQUIRES: arm-target-arch + +#include + +int main() { + raise(SIGSEGV); + // CHECK-DUMP: Register values + // CHECK-DUMP-NEXT: r0 = {{0x[0-9a-f]+}} r1 = {{0x[0-9a-f]+}} r2 = {{0x[0-9a-f]+}} r3 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT: r4 = {{0x[0-9a-f]+}} r5 = {{0x[0-9a-f]+}} r6 = {{0x[0-9a-f]+}} r7 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT: r8 = {{0x[0-9a-f]+}} r9 = {{0x[0-9a-f]+}} r10 = {{0x[0-9a-f]+}} r11 = {{0x[0-9a-f]+}} + // CHECK-DUMP-NEXT:r12 = {{0x[0-9a-f]+}} sp = {{0x[0-9a-f]+}} lr = {{0x[0-9a-f]+}} pc = {{0x[0-9a-f]+}} + // CHECK-NODUMP-NOT: Register values + return 0; +}