auipc rd, imm20
pc
imm20 << 12
rd
jalr rd, imm12(rs)
rs + imm12
pc + 4
jalr rs
jalr ra, 0(rs)
ret
ra
jalr zero, 0(ra)
call imm32
gcc -S
auipc ra, imm32_hi
jalr ra, imm32_lo(ra)
long bar(long x) { return x; } long foo(long x) { return bar(x) + 1; } long main(void) { return foo(0) + foo(1); }
$ riscv64-unknown-elf-gcc -O -fno-omit-frame-pointer -mcmodel=medany -mno-relax -fno-pie -no-pie -fno-inline -o foo foo.c $ riscv64-unknown-elf-objdump -d foo ... 0000000000010188 <bar>: 10188: 1141 addi sp,sp,-16 1018a: e422 sd s0,8(sp) 1018c: 0800 addi s0,sp,16 1018e: 6422 ld s0,8(sp) 10190: 0141 addi sp,sp,16 10192: 8082 ret 0000000000010194 <foo>: 10194: 1141 addi sp,sp,-16 10196: e406 sd ra,8(sp) 10198: e022 sd s0,0(sp) 1019a: 0800 addi s0,sp,16 1019c: 00000097 auipc ra,0x0 101a0: fec080e7 jalr -20(ra) # 10188 <bar> 101a4: 0505 addi a0,a0,1 101a6: 60a2 ld ra,8(sp) 101a8: 6402 ld s0,0(sp) 101aa: 0141 addi sp,sp,16 101ac: 8082 ret 00000000000101ae <main>: 101ae: 1101 addi sp,sp,-32 101b0: ec06 sd ra,24(sp) 101b2: e822 sd s0,16(sp) 101b4: e426 sd s1,8(sp) 101b6: 1000 addi s0,sp,32 101b8: 4501 li a0,0 101ba: 00000097 auipc ra,0x0 101be: fda080e7 jalr -38(ra) # 10194 <foo> 101c2: 84aa mv s1,a0 101c4: 4505 li a0,1 101c6: 00000097 auipc ra,0x0 101ca: fce080e7 jalr -50(ra) # 10194 <foo> 101ce: 9526 add a0,a0,s1 101d0: 60e2 ld ra,24(sp) 101d2: 6442 ld s0,16(sp) 101d4: 64a2 ld s1,8(sp) 101d6: 6105 addi sp,sp,32 101d8: 8082 ret ...
. . . +-> +----------------+ | | | main's ra | | | | previous s0/fp ----+ | | saved s1 | | | ... | | +----------------+ <-+ | | foo's ra @main | | +---- previous s0/fp | | +----------------+ | . . .
kernel/printf.c
*(volatile int *)0 = 0;
exec()
kernel/exec.c
void backtrace(uint64 fp) { ... }
-fno-omit-frame-pointer
scause 0x000000000000000f sepc=0x0000000080004d7c stval=0x0000000000000000 PANIC: kerneltrap [<0x0000000080000594>] panic+0x46/0x62 [<0x000000008000292a>] kerneltrap+0xa8/0xcc [<0x0000000080005dd4>] kernelvec+0x44/0x90 [<0x0000000080005bb6>] sys_exec+0xde/0x128 [<0x0000000080002b02>] syscall+0x3e/0x6c [<0x00000000800027ec>] usertrap+0x6a/0x100
stvec
kernel/trap.c
printf("%d\n", *(volatile int *)0x4000000000);
main
user/call.c
sepc
lw
kernel/trampoline.S
usertrap
scause
stval
$ call usertrap(): unexpected scause 0x000000000000000d pid=3 sepc=0x0000000000000028 stval=0x0000004000000000
ecall
user/usys.S
syscall
kernel/syscall.c