# 如何 debug riscv 架構的 user program ## 安裝 ### 安裝 qemu-user ```bash sudo apt install qemu-user ``` ### 安裝 pwndbg(非必要但幫助頗大) ```bash git clone https://github.com/pwndbg/pwndbg.git cd pwndbg ./setup.sh ``` ## 使用步驟 首先編譯出一個執行檔: ```bash riscv64-unknown-linux-gnu-gcc -static -o test test.c ``` 然後用 `qemu-riscv64` 跑起來,開啟一個 gdbserver,這裡開在 `localhost:1234`: ```bash qemu-riscv64 -g 1234 ./test ``` 然後開啟另一個 terminal,使用對應架構的 gdb(或是對 gdb-multiarch 做對應的設定): ```bash riscv64-unknown-linux-gnu-gdb ``` 接下來輸入以下命令以連上 gdbserver: ```bash pwndbg> target remote localhost:1234 ``` 然後就可以開始 debug 了: ```bash ► 0x10450 jal 0x24 <0x10474> 0x10454 c.mv a5, a0 0x10456 auipc a0, 0 A0 => 0x10456 0x1045a addi a0, a0, 0x1c 0x1045e c.ldsp a1, 0(sp) 0x10460 c.addi4spn a2, sp, 8 0x10462 andi sp, sp, -0x10 0x10466 c.li a3, 0 A3 => 0 0x10468 c.li a4, 0 A4 => 0 0x1046a c.mv a6, sp 0x1046c jal 0x19a <0x10606> ──────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────── 00:0000│ sp 0x2aaaab2ab420 ◂— 1 01:0008│ 0x2aaaab2ab428 —▸ 0x2aaaab2ab642 ◂— 0x5300747365742f2e /* './test' */ 02:0010│ 0x2aaaab2ab430 ◂— 0 03:0018│ 0x2aaaab2ab438 —▸ 0x2aaaab2ab649 ◂— 'SHELL=/bin/bash' 04:0020│ 0x2aaaab2ab440 —▸ 0x2aaaab2ab659 ◂— 'PWD=/root/test' 05:0028│ 0x2aaaab2ab448 —▸ 0x2aaaab2ab668 ◂— 'LOGNAME=root' 06:0030│ 0x2aaaab2ab450 —▸ 0x2aaaab2ab675 ◂— 'XDG_SESSION_TYPE=tty' 07:0038│ 0x2aaaab2ab458 —▸ 0x2aaaab2ab68a ◂— 'HOME=/root' ────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────── ► 0 0x10450 None ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── pwndbg> ``` ## 一些技巧 ### 編譯時不去除 symbol 加上 `-g` 參數: ```bash riscv64-unknown-linux-gnu-gcc -static -o test test.c -g ``` ### debug 時怎麼找到 `main` 函數 首先連上 gdbserver 之後,先用以下命令得到 symbol: ```bash pwndbg> file ./test # The executable file Reading symbols from ./test... ``` 然後對 `main` 下斷點: ```bash pwndbg> b main Breakpoint 1 at 0x1053a: file test.c, line 4. ``` 接下來直接執行: ```bash pwndbg> c Continuing. ``` 然後你可以看到有原始碼和組合語言: ```bash ► 0x1053a <main+8> lui a5, 0x4f A5 => 0x4f000 (__memcpy_generic+28) 0x1053e <main+12> addi a0, a5, 0x478 A0 => 0x4f478 (0x4f000 + 0x478) 0x10542 <main+16> jal 0x8ca <puts> 0x10546 <main+20> c.li a5, 0 A5 => 0 0x10548 <main+22> c.mv a0, a5 0x1054a <main+24> c.ldsp ra, 8(sp) 0x1054c <main+26> c.ldsp s0, 0(sp) 0x1054e <main+28> c.addi sp, 0x10 0x10550 <main+30> c.jr ra 0x10552 <call_fini> c.addi sp, -0x20 0x10554 <call_fini+2> c.sdsp s0, 0x10(sp) ──────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────── In file: /root/test/test.c:4 1 #include <stdio.h> 2 3 int main(){ ► 4 puts("Helloworld"); 5 } ──────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────── 00:0000│ sp 0x2aaaab2ab270 —▸ 0x783e0 (__fini_array_start) —▸ 0x104d0 (__do_global_dtors_aux) ◂— c.addi sp, -0x10 01:0008│ 0x2aaaab2ab278 —▸ 0x105d2 (__libc_start_call_main+72) ◂— jal 0x826 02:0010│ s0 0x2aaaab2ab280 ◂— 0x3a /* ':' */ 03:0018│ 0x2aaaab2ab288 —▸ 0x10472 (__wrap_main) ◂— c.j 0xc0 04:0020│ 0x2aaaab2ab290 ◂— 1 05:0028│ 0x2aaaab2ab298 —▸ 0x2aaaab2ab428 —▸ 0x2aaaab2ab642 ◂— 0x5300747365742f2e /* './test' */ 06:0030│ 0x2aaaab2ab2a0 ◂— 0x3a /* ':' */ 07:0038│ 0x2aaaab2ab2a8 —▸ 0x1059c (__libc_start_call_main+18) ◂— c.bnez a0, 0x3a ────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────── ► 0 0x1053a main+8 1 0x105d2 __libc_start_call_main+72 2 0x107d8 __libc_start_main_impl+466 3 0x10470 _start+32 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── pwndbg> ```