KDB支持单步调试功能(ARM架构)
0
    实践发现KDB不支持step调试功能 (本文针对的是arm CotexA9架构,各种架构的实现方式不一样,
    X86的好像已经支持,不过本人没有验证过)
 1
    首先看下要调试的代码段
    1.1  C语言
    int  testPara_7(int a, int b,int c,int d, int e,int f,int g)
    {
          printk(KERN_ERR “hit one \n”);
          printk(KERN_ERR “hit two \n”);
          printk(KERN_ERR “hit three \n”);
          printk(KERN_ERR “hit four \n”);
          return 3;
    }  
    1.2  对应的汇编语言  (objdump -d vmlinux)
    c0339bf8 <testPara_7>:
    c0339bf8: e1a0c00d  mov ip, sp
    c0339bfc: e92dd800  push {fp, ip, lr, pc}
    c0339c00: e24cb004  sub fp, ip, #4 ; 0×4
    c0339c04: e59f0020  ldr r0, [pc, #32] ; c0339c2c <testPara_7+0×34>
    c0339c08: eb05bbef  bl c04a8bcc <printk>
    c0339c0c: e59f001c  ldr r0, [pc, #28] ; c0339c30 <testPara_7+0×38>
    c0339c10: eb05bbed  bl c04a8bcc <printk>
    c0339c14: e59f0018  ldr r0, [pc, #24] ; c0339c34 <testPara_7+0×3c>
    c0339c18: eb05bbeb  bl c04a8bcc <printk>
    c0339c1c: e59f0014  ldr r0, [pc, #20] ; c0339c38 <testPara_7+0×40>
    c0339c20: eb05bbe9  bl c04a8bcc <printk>
    c0339c24: e3a00003  mov r0, #3 ; 0×3
    c0339c28: e89da800  ldm sp, {fp, sp, pc}
    c0339c2c: c060bd96  .word 0xc060bd96
    c0339c30: c060bda3  .word 0xc060bda3
    c0339c34: c060bdb0  .word 0xc060bdb0
    c0339c38: c060bdbf  .word 0xc060bdbf
 3
    通过分析汇编发现指令的地址都是以4的步长递增的,这种情况就比较号解决了,
    不用去根据不同的汇编指令,改变PC的值。而只需要简单的PC=PC+4即可。
 4
    在Debug_core.c 增加函数如下:
    并在头文件中声明:  extern  void do_my_step(unsigned long addr);
 void do_my_step(unsigned long addr)
 {
      int i=0;
      for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++)
      {
          if (kgdb_break[i].bpt_addr != addr)
               continue;
         //找到地址相匹配的,修改其地址值
          kgdb_break[i].bpt_addr=kgdb_break[i].bpt_addr+4;
          kgdb_break[i].state = BP_SET;
           printk(KERN_ERR “i is %d    kgdb_break[i].bpt_addr is %p\r\n”,i,  kgdb_break[i].bpt_addr);
           break;
     }                                
 }
 5  修改 kdb_bp.c 中的 kdb_handle_bp 函数如下:
    static void kdb_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
 {
        if (KDB_DEBUG(BP))
                kdb_printf(“regs->ip = 0x%lx\n”, instruction_pointer(regs));
         //此处是新增的调用单步实现函数
       do_my_step(instruction_pointer(regs));
       /*
         * Setup single step
          */
        kdb_setsinglestep(regs);
      /*
        * Reset delay attribute
        */
       bp->bp_delay = 0;
      bp->bp_delayed = 1;
 }
 6
   实际应用,进入kdb模式后 ,(echo g > /proc/sysrq-trigger)
   输入ss即可实现单步模式(汇编级别的):
   kdb>bp c0339bf8    (在testPara_7函数处设置一个断点)
   kdb>go
   之后kernel运行到此函数,系统进入KDB模式,就可以进行单步调试
   kdb>ss
   ….
   与预想的一致,按两次ss即可打印出一条语句:(可通过串口及minicom观察)
   如: hit one
              hit two
              …..
 7
   7.1  总的来说实现了step功能,但是还是存在一些小bug
   7.2  有时间的话,希望能够实现C语言级别的step(对我来说难度太大)
 8
   kgdb_arch_handle_exception函数和自己实践,ARM结构的GKDBb,并没有
   实现step调试功能。
   曾试图去实现kgdb的step功能,由于条件及能力限制没能实现(
   kgdb需要用的一个串口通讯,调试本来也需要单独一条,但是现在只有
   一条共用的),
   int kgdb_arch_handle_exception(int exception_vector, int signo,
           int err_code, char *remcom_in_buffer,
           char *remcom_out_buffer,
           struct pt_regs *linux_regs)
   {
             unsigned long addr;
             char *ptr;
            switch (remcom_in_buffer[0]) {
                       case ‘D’:
                       case ‘k’:
                       case ‘c’:
                       ptr = &remcom_in_buffer[1];
                       if (kgdb_hex2long(&ptr, &addr))
                                     linux_regs->ARM_pc = addr;
                       else if (compiled_break == 1)
                                     linux_regs->ARM_pc += 4;
compiled_break = 0;
          return 0;
  }
return -1;
  }
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号