Skip to content

Commit

Permalink
[compiler-rt] Implement DumpAllRegisters for arm-linux and aarch64-…
Browse files Browse the repository at this point in the history
…linux (llvm#99613)

Examples of the output:

ARM:
```
# ./a.out 
AddressSanitizer:DEADLYSIGNAL
=================================================================
==122==ERROR: AddressSanitizer: SEGV on unknown address 0x0000007a (pc 0x76e13ac0 bp 0x7eb7fd00 sp 0x7eb7fcc8 T0)
==122==The signal is caused by a READ memory access.
==122==Hint: address points to the zero page.
    #0 0x76e13ac0  (/lib/libc.so.6+0x7cac0)
    #1 0x76dce680 in gsignal (/lib/libc.so.6+0x37680)
    llvm#2 0x005c2250  (/root/a.out+0x145250)
    llvm#3 0x76db982c  (/lib/libc.so.6+0x2282c)
    llvm#4 0x76db9918 in __libc_start_main (/lib/libc.so.6+0x22918)

==122==Register values:
 r0 = 0x00000000   r1 = 0x0000007a   r2 = 0x0000000b   r3 = 0x76d95020  
 r4 = 0x0000007a   r5 = 0x00000001   r6 = 0x005dcc5c   r7 = 0x0000010c  
 r8 = 0x0000000b   r9 = 0x76f9ece0  r10 = 0x00000000  r11 = 0x7eb7fd00  
r12 = 0x76dce670   sp = 0x7eb7fcc8   lr = 0x76e13ab4   pc = 0x76e13ac0  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/libc.so.6+0x7cac0) 
==122==ABORTING
```

AArch64:
```
# ./a.out 
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==99==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000063 (pc 0x007fbbbc5860 bp 0x007fcfdcb700 sp 0x007fcfdcb700 T99)
==99==The signal is caused by a UNKNOWN memory access.
==99==Hint: address points to the zero page.
    #0 0x007fbbbc5860  (/lib64/libc.so.6+0x82860)
    #1 0x007fbbb81578  (/lib64/libc.so.6+0x3e578)
    llvm#2 0x00556051152c  (/root/a.out+0x3152c)
    llvm#3 0x007fbbb6e268  (/lib64/libc.so.6+0x2b268)
    llvm#4 0x007fbbb6e344  (/lib64/libc.so.6+0x2b344)
    llvm#5 0x0055604e45ec  (/root/a.out+0x45ec)

==99==Register values:
 x0 = 0x0000000000000000   x1 = 0x0000000000000063   x2 = 0x000000000000000b   x3 = 0x0000007fbbb41440  
 x4 = 0x0000007fbbb41580   x5 = 0x3669288942d44cce   x6 = 0x0000000000000000   x7 = 0x00000055605110b0  
 x8 = 0x0000000000000083   x9 = 0x0000000000000000  x10 = 0x0000000000000000  x11 = 0x0000000000000000  
x12 = 0x0000007fbbdb3360  x13 = 0x0000000000010000  x14 = 0x0000000000000039  x15 = 0x00000000004113a0  
x16 = 0x0000007fbbb81560  x17 = 0x0000005560540138  x18 = 0x000000006474e552  x19 = 0x0000000000000063  
x20 = 0x0000000000000001  x21 = 0x000000000000000b  x22 = 0x0000005560511510  x23 = 0x0000007fcfdcb918  
x24 = 0x0000007fbbdb1b50  x25 = 0x0000000000000000  x26 = 0x0000007fbbdb2000  x27 = 0x000000556053f858  
x28 = 0x0000000000000000   fp = 0x0000007fcfdcb700   lr = 0x0000007fbbbc584c   sp = 0x0000007fcfdcb700  
UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV (/lib64/libc.so.6+0x82860) 
==99==ABORTING
```
  • Loading branch information
chestnykh authored Jul 24, 2024
1 parent ddb75ca commit ef1c70d
Showing 3 changed files with 182 additions and 2 deletions.
142 changes: 140 additions & 2 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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 <signal.h>

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;
}
Original file line number Diff line number Diff line change
@@ -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 <signal.h>

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

0 comments on commit ef1c70d

Please sign in to comment.