From c11da58c80228330f89fe594a60dfcb411c3374f Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Wed, 24 Jul 2024 17:56:06 +0300 Subject: [PATCH 1/2] [compiler-rt] Implement `DumpAllRegisters` for arm-linux and aarch64-linux Reland with a couple of build fixes --- .../lib/sanitizer_common/sanitizer_linux.cpp | 150 +++++++++++++++++- .../Linux/dump_registers_aarch64.cpp | 23 +++ .../TestCases/Linux/dump_registers_arm.cpp | 19 +++ 3 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_aarch64.cpp create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/dump_registers_arm.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 483a1042a62383..8879f70004e513 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -2172,15 +2172,125 @@ static const char *RegNumToRegName(int reg) { return "ebp"; case REG_ESP: return "esp"; +# elif defined(__arm__) +# ifdef MAKE_CASE +# undef MAKE_CASE +# endif +# 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 +# endif // SANITIZER_LINUX 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__) +# ifdef MAKE_CASE +# undef MAKE_CASE +# endif +# 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,11 +2299,16 @@ 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 } -# endif void SignalContext::DumpAllRegisters(void *context) { ucontext_t *ucontext = (ucontext_t *)context; @@ -2236,6 +2351,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 00000000000000..e01b826c86b8ac --- /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 00000000000000..e17dbf196227b6 --- /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; +} From 815c9d3209f38aa1118befc0149bcf635453ebaa Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Wed, 24 Jul 2024 18:07:02 +0300 Subject: [PATCH 2/2] [compiler-rt] Adjust code style --- .../lib/sanitizer_common/sanitizer_linux.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 8879f70004e513..2ea61b1cb424ce 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -2247,10 +2247,10 @@ static const char *RegNumToRegName(int reg) { return NULL; } -# if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) +# if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) static uptr GetArmRegister(ucontext_t *ctx, int RegNum) { switch (RegNum) { -# if defined(__arm__) +# if defined(__arm__) # ifdef MAKE_CASE # undef MAKE_CASE # endif @@ -2278,18 +2278,18 @@ static uptr GetArmRegister(ucontext_t *ctx, int RegNum) { return ctx->uc_mcontext.arm_lr; case REG_R15: return ctx->uc_mcontext.arm_pc; -# elif defined(__aarch64__) +# elif defined(__aarch64__) case 0 ... 30: return ctx->uc_mcontext.regs[RegNum]; case 31: return ctx->uc_mcontext.sp; -# endif +# endif default: return 0; } return 0; } -# endif // SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) +# endif // SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__)) UNUSED static void DumpSingleReg(ucontext_t *ctx, int RegNum) { @@ -2299,15 +2299,15 @@ 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__) +# elif defined(__arm__) Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName, GetArmRegister(ctx, RegNum)); -# elif defined(__aarch64__) +# elif defined(__aarch64__) Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName, GetArmRegister(ctx, RegNum)); -# else +# else (void)RegName; -# endif +# endif } void SignalContext::DumpAllRegisters(void *context) {