首页 > 解决方案 > 为什么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



标签: debugginglinux-kernelgdb

解决方案


推荐阅读