ucore lab1

练习5:实现函数调用堆栈跟踪函数 (需要编程)

我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_stackframe来跟踪函 数调用堆栈中记录的返回地址。在如果能够正确实现此函数,可在lab1中执行 “make qemu”后,在qemu模拟器中得到类似如下的输出:

尝试添加代码:

      //galaxy 2014-7-12
      uint32_t ebp_value,eip_value;
      ebp_value=read_ebp();
      while(ebp_value!=0)
      {
      
          cprintf("ebp: 0x%08x \n",ebp_value);
          ebp_value = *(uintptr_t *)ebp_value;

      }

      //galaxy 2014-7-12
      uint32_t ebp_value,func_retaddr;
      ebp_value = read_ebp();
      func_retaddr = read_eip();
      while(ebp_value!=0)
      {
          cprintf("ebp: 0x%08x eip: 0x%08x args: 0x%08x 0x%08x 0x%08x 0x%08x \n",ebp_value,func_retaddr,
                 *(uintptr_t *)(ebp_value+8),*(uintptr_t *)(ebp_value+12),*(uintptr_t *)(ebp_value+16),
                 *(uintptr_t *)(ebp_value+20));
         
          cprintf("\n");
          print_debuginfo(func_retaddr);
          ebp_value = *(uintptr_t *)ebp_value;
          func_retaddr = *(uintptr_t *)(ebp_value+4);

      }

(THU.CST) os is loading ...

Special kernel symbols:
  entry  0x00100000 (phys)
  etext  0x0010329b (phys)
  edata  0x0010ea16 (phys)
  end    0x0010fd20 (phys)
Kernel executable memory footprint: 64KB
ebp: 0x00007b08 eip: 0x001009a2 args: 0x00010094 0x00000000 0x00007b38 0x0010008d

    kern/debug/kdebug.c:309: print_stackframe+23
ebp: 0x00007b18 eip: 0x0010008d args: 0x00000000 0x00000000 0x00000000 0x00007b88

    kern/init/init.c:49: grade_backtrace2+34
ebp: 0x00007b38 eip: 0x001000b6 args: 0x00000000 0x00007b60 0xffff0000 0x00007b64

    kern/init/init.c:54: grade_backtrace1+39
ebp: 0x00007b58 eip: 0x001000d4 args: 0x00000000 0xffff0000 0x00007b84 0x00000029

    kern/init/init.c:59: grade_backtrace0+24
ebp: 0x00007b78 eip: 0x001000f9 args: 0x00000000 0x00100000 0xffff0000 0x0000001d

    kern/init/init.c:64: grade_backtrace+35
ebp: 0x00007b98 eip: 0x00100055 args: 0x001032bc 0x001032a0 0x0000130a 0x00000000

    kern/init/init.c:30: kern_init+85
ebp: 0x00007bc8 eip: 0x00007d68 args: 0x00000000 0x00000000 0x00000000 0x00010094

    <unknow>: -- 0x00007d68 --
ebp: 0x00007bf8 eip: 0x00007c4f args: 0xc031fcfa 0xc08ed88e 0x64e4d08e 0xfa7502a8

    <unknow>: -- 0x00007c4f --
++ setup timer interrupts
 我们查看源代码可以发现:

--> kern_init() --> grade_backtrace() --> grade_backtrace0(0, (int)kern_init, 0xffff0000) --> grade_backtrace1(0, 0xffff0000)

--> grade_backtrace2(0,arg1_addr,0xffff0000,arg2_addr) --> mon_backtrace(0, NULL, NULL) --> print_stackframe()

看看输出结果中的参数,发现是正确的。

练习6:完善中断初始化和处理 (需要编程)

void
idt_init(void) {
     /* LAB1 YOUR CODE : STEP 2 */
     /* (1) Where are the entry addrs of each Interrupt Service Routine (ISR)?
      *     All ISR's entry addrs are stored in __vectors. where is uintptr_t __vectors[] ?
      *     __vectors[] is in kern/trap/vector.S which is produced by tools/vector.c
      *     (try "make" command in lab1, then you will find vector.S in kern/trap DIR)
      *     You can use  "extern uintptr_t __vectors[];" to define this extern variable which will be used later.
      * (2) Now you should setup the entries of ISR in Interrupt Description Table (IDT).
      *     Can you see idt[256] in this file? Yes, it's IDT! you can use SETGATE macro to setup each item of IDT
      * (3) After setup the contents of IDT, you will let CPU know where is the IDT by using 'lidt' instruction.
      *     You don't know the meaning of this instruction? just google it! and check the libs/x86.h to know more.
      *     Notice: the argument of lidt is idt_pd. try to find it!
      */
 
      //galaxy 2014-7-12
      int i;
      extern uintptr_t __vectors[];
      for(i=0;i<256;i++){
          SETGATE(idt[i],0,8,__vectors[i],0)
      }
      
      lidt(&idt_pd);
      
}
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    switch (tf->tf_trapno) {
    case IRQ_OFFSET + IRQ_TIMER:
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        
        //galaxy 2014-7-12
        ticks++;
        if(100==ticks)
        {
           print_ticks();
           ticks=0;
        }
        
        break;

 

posted @ 2014-07-12 16:11  乾卦  阅读(162)  评论(0)    收藏  举报