Skip to content

Commit ef1c70d

Browse files
authored
[compiler-rt] Implement DumpAllRegisters for arm-linux and aarch64-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) #2 0x005c2250 (/root/a.out+0x145250) #3 0x76db982c (/lib/libc.so.6+0x2282c) #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) #2 0x00556051152c (/root/a.out+0x3152c) #3 0x007fbbb6e268 (/lib64/libc.so.6+0x2b268) #4 0x007fbbb6e344 (/lib64/libc.so.6+0x2b344) #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 ```
1 parent ddb75ca commit ef1c70d

File tree

3 files changed

+182
-2
lines changed

3 files changed

+182
-2
lines changed

Diff for: compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp

+140-2
Original file line numberDiff line numberDiff line change
@@ -2172,15 +2172,118 @@ static const char *RegNumToRegName(int reg) {
21722172
return "ebp";
21732173
case REG_ESP:
21742174
return "esp";
2175+
# elif defined(__arm__)
2176+
# define REG_STR(reg) #reg
2177+
# define MAKE_CASE(N) \
2178+
case REG_R##N: \
2179+
return REG_STR(r##N)
2180+
MAKE_CASE(0);
2181+
MAKE_CASE(1);
2182+
MAKE_CASE(2);
2183+
MAKE_CASE(3);
2184+
MAKE_CASE(4);
2185+
MAKE_CASE(5);
2186+
MAKE_CASE(6);
2187+
MAKE_CASE(7);
2188+
MAKE_CASE(8);
2189+
MAKE_CASE(9);
2190+
MAKE_CASE(10);
2191+
MAKE_CASE(11);
2192+
MAKE_CASE(12);
2193+
case REG_R13:
2194+
return "sp";
2195+
case REG_R14:
2196+
return "lr";
2197+
case REG_R15:
2198+
return "pc";
2199+
# elif defined(__aarch64__)
2200+
# define REG_STR(reg) #reg
2201+
# define MAKE_CASE(N) \
2202+
case N: \
2203+
return REG_STR(x##N)
2204+
MAKE_CASE(0);
2205+
MAKE_CASE(1);
2206+
MAKE_CASE(2);
2207+
MAKE_CASE(3);
2208+
MAKE_CASE(4);
2209+
MAKE_CASE(5);
2210+
MAKE_CASE(6);
2211+
MAKE_CASE(7);
2212+
MAKE_CASE(8);
2213+
MAKE_CASE(9);
2214+
MAKE_CASE(10);
2215+
MAKE_CASE(11);
2216+
MAKE_CASE(12);
2217+
MAKE_CASE(13);
2218+
MAKE_CASE(14);
2219+
MAKE_CASE(15);
2220+
MAKE_CASE(16);
2221+
MAKE_CASE(17);
2222+
MAKE_CASE(18);
2223+
MAKE_CASE(19);
2224+
MAKE_CASE(20);
2225+
MAKE_CASE(21);
2226+
MAKE_CASE(22);
2227+
MAKE_CASE(23);
2228+
MAKE_CASE(24);
2229+
MAKE_CASE(25);
2230+
MAKE_CASE(26);
2231+
MAKE_CASE(27);
2232+
MAKE_CASE(28);
2233+
case 29:
2234+
return "fp";
2235+
case 30:
2236+
return "lr";
2237+
case 31:
2238+
return "sp";
21752239
# endif
2176-
# endif
21772240
default:
21782241
return NULL;
21792242
}
21802243
return NULL;
21812244
}
21822245

2183-
# if SANITIZER_LINUX
2246+
# if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__))
2247+
static uptr GetArmRegister(ucontext_t *ctx, int RegNum) {
2248+
switch (RegNum) {
2249+
# if defined(__arm__)
2250+
# define MAKE_CASE(N) \
2251+
case REG_R##N: \
2252+
return ctx->uc_mcontext.arm_r##N
2253+
MAKE_CASE(0);
2254+
MAKE_CASE(1);
2255+
MAKE_CASE(2);
2256+
MAKE_CASE(3);
2257+
MAKE_CASE(4);
2258+
MAKE_CASE(5);
2259+
MAKE_CASE(6);
2260+
MAKE_CASE(7);
2261+
MAKE_CASE(8);
2262+
MAKE_CASE(9);
2263+
MAKE_CASE(10);
2264+
case REG_R11:
2265+
return ctx->uc_mcontext.arm_fp;
2266+
case REG_R12:
2267+
return ctx->uc_mcontext.arm_ip;
2268+
case REG_R13:
2269+
return ctx->uc_mcontext.arm_sp;
2270+
case REG_R14:
2271+
return ctx->uc_mcontext.arm_lr;
2272+
case REG_R15:
2273+
return ctx->uc_mcontext.arm_pc;
2274+
# elif defined(__aarch64__)
2275+
case 0 ... 30:
2276+
return ctx->uc_mcontext.regs[RegNum];
2277+
case 31:
2278+
return ctx->uc_mcontext.sp;
2279+
# endif
2280+
default:
2281+
return 0;
2282+
}
2283+
return 0;
2284+
}
2285+
# endif // SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__))
2286+
21842287
UNUSED
21852288
static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
21862289
const char *RegName = RegNumToRegName(RegNum);
@@ -2189,6 +2292,12 @@ static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
21892292
RegName, ctx->uc_mcontext.gregs[RegNum]);
21902293
# elif defined(__i386__)
21912294
Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]);
2295+
# elif defined(__arm__)
2296+
Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
2297+
GetArmRegister(ctx, RegNum));
2298+
# elif defined(__aarch64__)
2299+
Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
2300+
GetArmRegister(ctx, RegNum));
21922301
# else
21932302
(void)RegName;
21942303
# endif
@@ -2236,6 +2345,35 @@ void SignalContext::DumpAllRegisters(void *context) {
22362345
DumpSingleReg(ucontext, REG_EBP);
22372346
DumpSingleReg(ucontext, REG_ESP);
22382347
Printf("\n");
2348+
# elif defined(__arm__)
2349+
Report("Register values:\n");
2350+
DumpSingleReg(ucontext, REG_R0);
2351+
DumpSingleReg(ucontext, REG_R1);
2352+
DumpSingleReg(ucontext, REG_R2);
2353+
DumpSingleReg(ucontext, REG_R3);
2354+
Printf("\n");
2355+
DumpSingleReg(ucontext, REG_R4);
2356+
DumpSingleReg(ucontext, REG_R5);
2357+
DumpSingleReg(ucontext, REG_R6);
2358+
DumpSingleReg(ucontext, REG_R7);
2359+
Printf("\n");
2360+
DumpSingleReg(ucontext, REG_R8);
2361+
DumpSingleReg(ucontext, REG_R9);
2362+
DumpSingleReg(ucontext, REG_R10);
2363+
DumpSingleReg(ucontext, REG_R11);
2364+
Printf("\n");
2365+
DumpSingleReg(ucontext, REG_R12);
2366+
DumpSingleReg(ucontext, REG_R13);
2367+
DumpSingleReg(ucontext, REG_R14);
2368+
DumpSingleReg(ucontext, REG_R15);
2369+
Printf("\n");
2370+
# elif defined(__aarch64__)
2371+
Report("Register values:\n");
2372+
for (int i = 0; i <= 31; ++i) {
2373+
DumpSingleReg(ucontext, i);
2374+
if (i % 4 == 3)
2375+
Printf("\n");
2376+
}
22392377
# else
22402378
(void)ucontext;
22412379
# endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Check that sanitizer prints registers dump_registers on dump_registers=1
2+
// RUN: %clangxx %s -o %t
3+
// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP
4+
// RUN: not %run %t 2>&1 | FileCheck %s --strict-whitespace --check-prefix=CHECK-DUMP
5+
//
6+
// REQUIRES: aarch64-target-arch
7+
8+
#include <signal.h>
9+
10+
int main() {
11+
raise(SIGSEGV);
12+
// CHECK-DUMP: Register values
13+
// CHECK-DUMP-NEXT: x0 = {{0x[0-9a-f]+}} x1 = {{0x[0-9a-f]+}} x2 = {{0x[0-9a-f]+}} x3 = {{0x[0-9a-f]+}}
14+
// CHECK-DUMP-NEXT: x4 = {{0x[0-9a-f]+}} x5 = {{0x[0-9a-f]+}} x6 = {{0x[0-9a-f]+}} x7 = {{0x[0-9a-f]+}}
15+
// CHECK-DUMP-NEXT: x8 = {{0x[0-9a-f]+}} x9 = {{0x[0-9a-f]+}} x10 = {{0x[0-9a-f]+}} x11 = {{0x[0-9a-f]+}}
16+
// CHECK-DUMP-NEXT:x12 = {{0x[0-9a-f]+}} x13 = {{0x[0-9a-f]+}} x14 = {{0x[0-9a-f]+}} x15 = {{0x[0-9a-f]+}}
17+
// CHECK-DUMP-NEXT:x16 = {{0x[0-9a-f]+}} x17 = {{0x[0-9a-f]+}} x18 = {{0x[0-9a-f]+}} x19 = {{0x[0-9a-f]+}}
18+
// CHECK-DUMP-NEXT:x20 = {{0x[0-9a-f]+}} x21 = {{0x[0-9a-f]+}} x22 = {{0x[0-9a-f]+}} x23 = {{0x[0-9a-f]+}}
19+
// CHECK-DUMP-NEXT:x24 = {{0x[0-9a-f]+}} x25 = {{0x[0-9a-f]+}} x26 = {{0x[0-9a-f]+}} x27 = {{0x[0-9a-f]+}}
20+
// CHECK-DUMP-NEXT:x28 = {{0x[0-9a-f]+}} fp = {{0x[0-9a-f]+}} lr = {{0x[0-9a-f]+}} sp = {{0x[0-9a-f]+}}
21+
// CHECK-NODUMP-NOT: Register values
22+
return 0;
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Check that sanitizer prints registers dump_registers on dump_registers=1
2+
// RUN: %clangxx %s -o %t
3+
// RUN: %env_tool_opts=dump_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP
4+
// RUN: not %run %t 2>&1 | FileCheck %s --strict-whitespace --check-prefix=CHECK-DUMP
5+
//
6+
// REQUIRES: arm-target-arch
7+
8+
#include <signal.h>
9+
10+
int main() {
11+
raise(SIGSEGV);
12+
// CHECK-DUMP: Register values
13+
// CHECK-DUMP-NEXT: r0 = {{0x[0-9a-f]+}} r1 = {{0x[0-9a-f]+}} r2 = {{0x[0-9a-f]+}} r3 = {{0x[0-9a-f]+}}
14+
// CHECK-DUMP-NEXT: r4 = {{0x[0-9a-f]+}} r5 = {{0x[0-9a-f]+}} r6 = {{0x[0-9a-f]+}} r7 = {{0x[0-9a-f]+}}
15+
// CHECK-DUMP-NEXT: r8 = {{0x[0-9a-f]+}} r9 = {{0x[0-9a-f]+}} r10 = {{0x[0-9a-f]+}} r11 = {{0x[0-9a-f]+}}
16+
// CHECK-DUMP-NEXT:r12 = {{0x[0-9a-f]+}} sp = {{0x[0-9a-f]+}} lr = {{0x[0-9a-f]+}} pc = {{0x[0-9a-f]+}}
17+
// CHECK-NODUMP-NOT: Register values
18+
return 0;
19+
}

0 commit comments

Comments
 (0)