From 1188d2933b2771bd9eaba8d423eb3c4f8a487c63 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 10 Aug 2025 09:55:12 +0200 Subject: [PATCH] SIGSEGV: handle and pretty-print on arm64-linux --- src/stub/Makefile | 2 + src/stub/src/arm64-linux.elf-entry.S | 186 +++++++++++++++++++++++++++ src/stub/src/arm64-linux.elf-fold.S | 11 ++ 3 files changed, 199 insertions(+) diff --git a/src/stub/Makefile b/src/stub/Makefile index f4984f70..9b9a68da 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -836,6 +836,8 @@ tc.arm64-linux.elf.gcc = arm64-linux-gcc-4.9.2 -nostdinc -DDAISY_CHAIN=1 -MMD - tc.arm64-linux.elf.gcc += -fno-exceptions -fno-asynchronous-unwind-tables tc.arm64-linux.elf.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototypes -Wwrite-strings -Werror +#arm64-linux.elf-entry.h arm64-linux.elf-fold.h: tc.arm64-linux.elf.gcc += -DTEST_SIGSEGV + tc.arm64-expand.gcc = $(tc.arm64-linux.elf.gcc) tc.arm64-linux.elf-upxfd_linux.gcc = $(tc.arm64-linux.elf.gcc) diff --git a/src/stub/src/arm64-linux.elf-entry.S b/src/stub/src/arm64-linux.elf-entry.S index fb47f4c0..c0b92c01 100644 --- a/src/stub/src/arm64-linux.elf-entry.S +++ b/src/stub/src/arm64-linux.elf-entry.S @@ -76,12 +76,18 @@ PAGE_SIZE = -(~0< 64 bits + mov x2,xzr // do not save old_sigaction + mov x1,sp // &new_sigaction + mov w0,#SIGSEGV + do_sys __NR_sigaction + add sp,sp,sa_frame + +#if 0 //{ TEST ONLY +mov x0,#0xc0;mov x1,#0xc1;mov x2,#0xc2;mov x3,#0xc3;mov x4,#0xc4;mov x5,#0xc5;mov x6,#0xc6;mov x7,#0xc7 +mov x8,#0xc8;mov x9,#0xc9;mov x10,#0xca;mov x11,#0xcb;mov x12,#0xcc;mov x13,#0xcd;mov x14,#0xce;mov x15,#0xcf +mov x16,#0xd0;mov x17,#0xd1;mov x18,#0xd2;mov x19,#0xd3;mov x20,#0xd4;mov x21,#0xd5;mov x22,#0xd6;mov x23,#0xd7 +mov x24,#0xd8;mov x25,#0xd9;mov x26,#0xda;mov x27,#0xdb;mov x28,#0xdc;mov x29,#0xdd;mov x30,#0xde + ldr x0,[x0] // cause SIGSEGV +#endif //} +#endif // TEST_SIGSEGV + add x0,sp,#(1+ 2)*NBPW call zfind // avoid feint of 0==argc; out: x0= &envp call zfind; mov xauxv,x0 // &Elf64_auxv @@ -262,6 +300,154 @@ wmeth .req w4 add xADRC,xelfa,x1 // &b_info of compressed input data jr lr // goto unfolded stub +#if TEST_SIGSEGV +proc_self_cmdline: + .asciz "/proc/self/cmdline" +announce_sigaction: + .asciz "\n\nSIGSEGV address space:\n" +end_announce_sigaction: + +proc_self_maps: + .asciz "/proc/self/maps" +minus_q: + .asciz "-q" +path_gdb: + .asciz "/usr/bin/gdb" +commands_gdb: + .ascii "set prompt\n" // null string prompt + .ascii "info inferiors\n" + .ascii "print \"x0-x7\"\n" + .ascii "x/8xg $sp + 0x138\n" + .ascii "print \"x8-x15\"\n" + .ascii "x/8xg\n" + .ascii "print \"x16-x23\"\n" + .ascii "x/8xg\n" + .ascii "print \"x24-x30\"\n" + .ascii "x/7xg\n" + .ascii "set $pc = *(long *)($sp + 0x238)\n" + .ascii "print \"faulting instr\"\n" + .ascii "x/i $pc\n" + .ascii "print \"fault context\"\n" + .ascii "x/15i $pc - 7*4\n" + //.ascii "print \"intercept stack\"\n" + //.ascii "x/76xg $sp\n" + .ascii "set $sp = *(long *)($sp + 0x230)\n" + .ascii "print \"user stack\"\n" + .ascii "x/64xg $sp\n" + .ascii "kill\n" + .ascii "quit 1" + .byte 0 +commands_gdb_end: + .balign 4 + +#define r_fd w19 +PATH_MAX= 4096 +child: +#if 1 //{ pipe input to gdb + mov arg1w,#0; do_sys __NR_close // fd_stdin + stp xzr,xzr,[sp,-2 * NBPW]! // &fd_pipe[2]; 4 bytes each; but stack align + mov arg2w,#0 + mov arg1,sp + do_sys __NR_pipe2 // read size will be 0 (fd_stdin) + add x16,sp,#4 + ldr r_fd,[x16] // write side of pipe + add sp,sp,#2*NBPW + + mov w2,#commands_gdb_end - commands_gdb // arg3 len + adr x1,commands_gdb // arg2 + mov w0,r_fd // arg1 fd + do_sys __NR_write + mov w0,r_fd; do_sys __NR_close +#endif //} + + sub sp,sp,#PATH_MAX + mov arg3w,#O_RDONLY + adr arg2,proc_self_cmdline + mov arg1,#-1 // fake FD_CWD + do_sys __NR_openat; mov r_fd,w0 // fd + mov arg2,sp // buffer + mov arg3w,#PATH_MAX + do_sys __NR_read + mov arg1w,r_fd; do_sys __NR_close + + do_sys __NR_getppid + stp xzr,xzr,[sp,-2 * NBPW]! // decimal(pid) fits in 16 bytes + mov w1,w0; mov x0,sp; call unsimal + + mov arg4,sp // &"pid" (result of unsimal) + add arg3,sp,#2 * NBPW // cmdline argv[0] [skip "pid"] + adr arg2,minus_q + adr arg1,path_gdb // arg1 path + stp arg1,arg2,[sp,-6 *NBPW]! // path_gdb, "-q" + stp arg3,arg4,[sp,2 *NBPW] // argv[0], "pid" + str xzr,[sp,4 * NBPW] // NULL + mov arg3,#0 // _envviron BUG + mov arg2,sp // &argv + do_sys __NR_execve +0: + b 0b + +// ucontext_t, mcontext_t, gregset_t, gret_t, REG_xxx: +// stack_t +__restore_rt: + nop + +sigsegv_sigaction: + stp x1,x2,[sp,-2 * NBPW] // save siginfo *, ucontext * +// print /proc/self/maps of child (same as parent: the beauty of fork()) + mov x2,#end_announce_sigaction - announce_sigaction // arg3 len + adr x1,announce_sigaction // arg2 buf + mov w0,#2 // arg1 fd_stderr + do_sys __NR_write + + mov w2,#O_RDONLY // arg3 flags + adr x1,proc_self_maps // arg2 path + mov w0,#-1 // fake FD_CWD + do_sys __NR_openat + mov r_fd,w0 // fd_maps +BUFLEN= 4096 + sub sp,sp,#BUFLEN +loop_maps: + mov x2,#BUFLEN // arg3 buflen + mov x1,sp // arg2 buffer + mov w0,r_fd // arg1 fd_maps + do_sys __NR_read + cbz w0,done_maps + mov x2,x0 // arg3 buflen + mov x1,sp // arg2 buf + mov w0,#2 // fd_stderr + do_sys __NR_write + b loop_maps +done_maps: + add sp,sp,#BUFLEN // discard buffer + mov x0,x16; do_sys __NR_close +// end printing of /proc/self/maps + + mov arg1,#0; mov arg2,#0; mov arg3,#0; mov arg4,#0 // paranoia + do_sys __NR_fork; cbz x0,child +parent: + b parent // spin; paused by gdb + +unsimal: // (dst, value) + stp lr,xzr,[sp,-2 * NBPW]!; call 0f + ldp lr,x1,[sp],#2 * NBPW + strb w1,[x0] // terminator + ret +0: + mov w2,#0xcccc + movk w2, 0xcccc, lsl 16 // 0xcccccccc ==> 4/5 as 32-bit fraction + umull x2,w1,w2 + add x2,x2,#0x1000 // BUG? unsimal(p, 730) + lsr x3,x2,35 // quo(value, 10) + add w2,w3,w3,lsl 2 // 5 * quo + sub w1,w1,w2,lsl 1 // rem = (val - (10 * quo)) + stp lr,x1,[sp,-2 * NBPW]! + cbz x3,1f; mov w1,w3; call 0b +1: + ldp lr,x1,[sp],#2 * NBPW; add w1,w1,#'0'; strb w1,[x0],#1 + ret +#endif // TEST_SIGSEGV + zfind: ldr x1,[x0],#NBPW; cbnz x1,zfind ret diff --git a/src/stub/src/arm64-linux.elf-fold.S b/src/stub/src/arm64-linux.elf-fold.S index a236076a..eb112644 100644 --- a/src/stub/src/arm64-linux.elf-fold.S +++ b/src/stub/src/arm64-linux.elf-fold.S @@ -271,6 +271,17 @@ no_env_pse: add sp,sp,#MAX_ELF_HDR_64 + OVERHEAD // un-alloca mov xfexp,x0 // entry address +#if TEST_SIGSEGV +// Uninstall SIGSEGV handler +SIGSEGV= 11 +__NR_sigaction = 0x86 // 134 + mov w3,#8 // minimal byte count + mov x2,#0 // no old + mov x1,#0 // no new + mov w0,#SIGSEGV + do_sys __NR_sigaction +#endif // TEST_SIGSEGV + // Discard pages of compressed input data (includes [ADRC,+LENC) ) ldr x1,[xelfa,#p_memsz+sz_Phdr+sz_Ehdr] // Phdr[C_TEXT= 1].p_memsz mov x0,xelfa // hi &Elf64_Ehdr