debugging - 为什么ecall后踪迹丢失?
问题描述
riscv64-unknown-elf-gdb
determining executable automatically. Try using the "file" command.
0x0000000000001000 in ?? ()
(gdb) file user/_alarmtest
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from user/_alarmtest...
(gdb) b 45
Breakpoint 1 at 0x64: file user/alarmtest.c, line 45.
(gdb) c
Continuing.
Breakpoint 1, test0 () at user/alarmtest.c:45
45 sigalarm(2, periodic);
(gdb) step
sigalarm () at user/usys.S:130
130 li a7, SYS_sigalarm
(gdb) si
131 ecall
(gdb) si
0x0000003ffffff004 in ?? ()
(gdb) si
Warning:
Cannot insert breakpoint 1: Cannot access memory at address 0x64
Command aborted.
(gdb)
当我使用 gdb 调试时,为什么在 ecall 之后跟踪丢失了?它告诉我无法访问内存,如何进入内核继续跟踪?ecall指令陷入内核,执行uservec,usertrap,然后是syscall
user/alarmtest.c
//
// test program for the alarm lab.
// you can modify this file for testing,
// but please make sure your kernel
// modifications pass the original
// versions of these tests.
//
#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/riscv.h"
#include "user/user.h"
void test0();
void test1();
void periodic();
int
main(int argc, char *argv[])
{
test0();
test1();
exit(0);
}
volatile static int count;
void
periodic()
{
count = count + 1;
printf("alarm!\n");
sigreturn();
}
// tests whether the kernel calls
// the alarm handler even a single time.
void
test0()
{
int i;
printf("test0 start\n");
count = 0;
sigalarm(2, periodic);
for(i = 0; i < 1000*500000; i++){
if((i % 1000000) == 0)
write(2, ".", 1);
if(count > 0)
break;
}
sigalarm(0, 0);
if(count > 0){
printf("test0 passed\n");
} else {
printf("\ntest0 failed: the kernel never called the alarm handler\n");
}
}
user/usys.S
sigalarm:
li a7, SYS_sigalarm
ecall
ret
.global sigreturn
sigreturn:
li a7, SYS_sigreturn
ecall
kernel.asm
0000000080002dc4 <sys_sigalarm>:
uint64
sys_sigalarm(void) {
80002dc4: 1101 addi sp,sp,-32
80002dc6: ec06 sd ra,24(sp)
80002dc8: e822 sd s0,16(sp)
80002dca: 1000 addi s0,sp,32
int intervalticks;
uint64 handler;
if(
argint(0, &intervalticks) < 0 ||
80002dcc: fec40593 addi a1,s0,-20
80002dd0: 4501 li a0,0
80002dd2: 00000097 auipc ra,0x0
80002dd6: d12080e7 jalr -750(ra) # 80002ae4 <argint>
80002dda: 87aa mv a5,a0
argaddr(1, &handler) < 0) return -1;
80002ddc: 557d li a0,-1
if(
80002dde: 0007ca63 bltz a5,80002df2 <sys_sigalarm+0x2e>
argaddr(1, &handler) < 0) return -1;
80002de2: fe040593 addi a1,s0,-32
80002de6: 4505 li a0,1
80002de8: 00000097 auipc ra,0x0
80002dec: d1e080e7 jalr -738(ra) # 80002b06 <argaddr>
argint(0, &intervalticks) < 0 ||
80002df0: 957d srai a0,a0,0x3f
// printf("handler = %p\n", handler);
return 0;
}
80002df2: 60e2 ld ra,24(sp)
80002df4: 6442 ld s0,16(sp)
80002df6: 6105 addi sp,sp,32
80002df8: 8082 ret
trampoline.S
.globl uservec
uservec:
#
# trap.c sets stvec to point here, so
# traps from user space start here,
# in supervisor mode, but with a
# user page table.
#
# sscratch points to where the process's p->tf is
# mapped into user space, at TRAPFRAME.
#
# swap a0 and sscratch
# so that a0 is TRAPFRAME
csrrw a0, sscratch, a0
# save the user registers in TRAPFRAME
sd ra, 40(a0)
sd sp, 48(a0)
sd gp, 56(a0)
sd tp, 64(a0)
sd t0, 72(a0)
sd t1, 80(a0)
sd t2, 88(a0)
sd s0, 96(a0)
sd s1, 104(a0)
sd a1, 120(a0)
sd a2, 128(a0)
sd a3, 136(a0)
...
...
trap.c
void
usertrap(void)
{
int which_dev = 0;
if((r_sstatus() & SSTATUS_SPP) != 0)
panic("usertrap: not from user mode");
// send interrupts and exceptions to kerneltrap(),
// since we're now in the kernel.
w_stvec((uint64)kernelvec);
struct proc *p = myproc();
// save user program counter.
p->tf->epc = r_sepc();
if(r_scause() == 8){
// system call
if(p->killed)
exit(-1);
// sepc points to the ecall instruction,
// but we want to return to the next instruction.
p->tf->epc += 4;
// an interrupt will change sstatus &c registers,
// so don't enable until done with those registers.
intr_on();
syscall();
文件目录树
├── kernel
│ ├── bio.c
│ ├── bio.d
│ ├── bio.o
│ ├── buddy.c
│ ├── buddy.d
│ ├── buddy.o
│ ├── buf.h
│ ├── console.c
│ ├── console.d
│ ├── console.o
│ ├── date.h
│ ├── defs.h
│ ├── elf.h
│ ├── entry.o
│ ├── entry.S
│ ├── exec.c
│ ├── exec.d
│ ├── exec.o
│ ├── fcntl.h
│ ├── file.c
│ ├── file.d
│ ├── file.h
│ ├── file.o
│ ├── fs.c
│ ├── fs.d
│ ├── fs.h
│ ├── fs.o
│ ├── kalloc.c
│ ├── kalloc.d
│ ├── kalloc.o
│ ├── kernel
│ ├── kernel.asm
│ ├── kernel.ld
│ ├── kernel.sym
│ ├── kernelvec.o
│ ├── kernelvec.S
│ ├── list.c
│ ├── list.d
│ ├── list.o
│ ├── log.c
│ ├── log.d
│ ├── log.o
│ ├── main.c
│ ├── main.d
│ ├── main.o
├── LICENSE
├── Makefile
├── mkfs
│ ├── mkfs
│ └── mkfs.c
├── README
├── user
│ ├── _alarmtest
│ ├── alarmtest.asm
│ ├── alarmtest.c
│ ├── alarmtest.d
│ ├── alarmtest.o
│ ├── alarmtest.sym
│ ├── _alloctest
│ ├── alloctest.asm
│ ├── alloctest.c
│ ├── alloctest.d
│ ├── alloctest.o
│ ├── alloctest.sym
│ ├── _bcachetest
│ ├── bcachetest.asm
│ ├── bcachetest.c
│ ├── bcachetest.d
│ ├── bcachetest.o
│ ├── bcachetest.sym
│ ├── _call
│ ├── call.asm
│ ├── call.c
│ ├── call.d
│ ├── call.o
│ ├── call.sym
│ ├── usys.d
│ ├── usys.o
│ ├── usys.pl
│ ├── usys.S
解决方案
推荐阅读
- javascript - 量角器 - 如果元素被显示/呈现
- python - pymysql,连接到 SQL Server 时访问被拒绝错误
- javascript - 如果在此之前发生的 mousedown 事件延迟它,则模糊事件似乎会丢失
- python - Python Pandas ExcelWriter 附加到工作表创建一个新工作表
- xml - Android工作室,LinearLayout“匹配父-常量”
- php - 如何在没有键的情况下在数组中制作数组?
- python - 如何将 tdata 转换为 Telethon 会话?
- vim - 如何分析 :find 命令的选项卡完成情况?
- excel - 在 Excel 的条形图中隐藏空值
- c++ - 自定义类的C++数组,没有匹配的函数调用