Try   HackMD

如何 debug riscv 架構的 user program

安裝

安裝 qemu-user

sudo apt install qemu-user

安裝 pwndbg(非必要但幫助頗大)

git clone https://github.com/pwndbg/pwndbg.git
cd pwndbg
./setup.sh

使用步驟

首先編譯出一個執行檔:

riscv64-unknown-linux-gnu-gcc -static -o test test.c

然後用 qemu-riscv64 跑起來,開啟一個 gdbserver,這裡開在 localhost:1234

qemu-riscv64 ./test -g 1234

然後開啟另一個 terminal,使用對應架構的 gdb(或是對 gdb-multiarch 做對應的設定):

riscv64-unknown-linux-gnu-gdb 

接下來輸入以下命令以連上 gdbserver:

pwndbg> target remote localhost:1234

然後就可以開始 debug 了:

 ► 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 參數:

riscv64-unknown-linux-gnu-gcc -static -o test test.c -g

debug 時怎麼找到 main 函數

首先連上 gdbserver 之後,先用以下命令得到 symbol:

pwndbg> file ./test # The executable file
Reading symbols from ./test...

然後對 main 下斷點:

pwndbg> b main
Breakpoint 1 at 0x1053a: file test.c, line 4.

接下來直接執行:

pwndbg> c
Continuing.

然後你可以看到有原始碼和組合語言:

 ► 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>