zoukankan      html  css  js  c++  java
  • gdb 详解

    环境:gcc (OpenWrt/Linaro GCC 4.8)

    以如下的简单代码为例,说明gdb的使用。

     1 void func1(int a, int b)
     2 {
     3     int c;
     4     c = a + b;
     5 }
     6 
     7 int main(void)
     8 {
     9 
    10     func1(11,22);
    11     return 100;
    12 }

    1. gdb 下一步的命令

    a.执行下一行语句(语句级别)
      next(或n) 执行下一行语句,如果是函数调用则直接将函数执行完;相当于visual studio调试器中的"Step Over (单步跟踪)"
      step(或s) 执行下一行语句,如果是函数调用则进入函数中。即常说的单步调试,相当于visual studio调试器中的"Step Into (单步跟踪进入)"
      这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)
    b.执行下一条指令(指令级)
      si 类似于s;
      ni 类似于n;
      这两个命令(si/ni)所针对的是汇编指令

    2. disassemble

    可以反汇编当前函数或者指定的函数,
    单独用disassemble命令是反汇编当前函数,
    如果disassemble命令后面跟函数名或地址,则反汇编指定的函数.

    (gdb) disassemble
    Dump of assembler code for function main:
       0x00008440 <+0>:     push    {r11, lr}
       0x00008444 <+4>:     add     r11, sp, #4
    => 0x00008448 <+8>:     mov     r0, #11
       0x0000844c <+12>:    mov     r1, #22
       0x00008450 <+16>:    bl      0x8410 <func1>
       0x00008454 <+20>:    mov     r3, #100        ; 0x64
       0x00008458 <+24>:    mov     r0, r3
       0x0000845c <+28>:    pop     {r11, pc}
    End of assembler dump.
    
    (gdb) disassemble
    Dump of assembler code for function func1:
       0x00008410 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)
       0x00008414 <+4>:     add     r11, sp, #0
       0x00008418 <+8>:     sub     sp, sp, #20
       0x0000841c <+12>:    str     r0, [r11, #-16]
       0x00008420 <+16>:    str     r1, [r11, #-20]
    => 0x00008424 <+20>:    ldr     r2, [r11, #-16]
       0x00008428 <+24>:    ldr     r3, [r11, #-20]
       0x0000842c <+28>:    add     r3, r2, r3
       0x00008430 <+32>:    str     r3, [r11, #-8]
       0x00008434 <+36>:    sub     sp, r11, #0
       0x00008438 <+40>:    pop     {r11}           ; (ldr r11, [sp], #4)
       0x0000843c <+44>:    bx      lr
    End of assembler dump.

    3. 显示寄存器的信息

    info registers可以显示所有寄存器的当前值(不包括浮点寄存器)

    info all-registers(包括浮点寄存器)
    简写: i r

     1 (gdb) info registers
     2 r0             0xb      11
     3 r1             0x16     22
     4 r2             0xbefffe2c       3204447788
     5 r3             0x8440   33856
     6 r4             0xbeffff14       3204448020
     7 r5             0x8304   33540
     8 r6             0xbefffc80       3204447360
     9 r7             0x8      8
    10 r8             0x0      0
    11 r9             0x0      0
    12 r10            0xb6ffef7c       3070226300
    13 r11            0xbefffc64       3204447332
    14 r12            0xbefffd68       3204447592
    15 sp             0xbefffc50       0xbefffc50
    16 lr             0x8454   33876
    17 pc             0x8424   0x8424 <func1+20>
    18 cpsr           0x60000010       1610612752
    19 (gdb) i r
    20 r0             0xb      11
    21 r1             0x16     22
    22 r2             0xbefffe2c       3204447788
    23 r3             0x8440   33856
    24 r4             0xbeffff14       3204448020
    25 r5             0x8304   33540
    26 r6             0xbefffc80       3204447360
    27 r7             0x8      8
    28 r8             0x0      0
    29 r9             0x0      0
    30 r10            0xb6ffef7c       3070226300
    31 r11            0xbefffc64       3204447332
    32 r12            0xbefffd68       3204447592
    33 sp             0xbefffc50       0xbefffc50
    34 lr             0x8454   33876
    35 pc             0x8424   0x8424 <func1+20>
    36 cpsr           0x60000010       1610612752

    4.查看内存的值:

    gdb中使用"x"命令来打印内存的值,格式为"x/nfu addr"。含义为以f格式打印从addr开始的n个长度单元为u的内存值。参数具体含义如下:

    a)n:输出单元的个数。
    b)f:是输出格式。比如x是以16进制形式输出,o是以8进制形式输出,等等。
      x(hex) 按十六进制格式显示变量。
      d(decimal) 按十进制格式显示变量。
      u(unsigned decimal) 按十进制格式显示无符号整型。
      o(octal) 按八进制格式显示变量。
      t(binary) 按二进制格式显示变量。
      a(address) 按十六进制格式显示变量。
      c(char) 按字符格式显示变量。
      f(float) 按浮点数格式显示变量
    c)u:标明一个单元的长度。b是一个byte,h是两个byte(halfword),w是四个byte(word),g是八个byte(giant word)

    1 举例:
    2 以16进制格式打印从add开始的16个byte的值:
    3 (gdb) x/16xb $r11
    4 0xbefffc64:     0x6c    0xfc    0xff    0xbe    0x00    0x00    0x00    0x00
    5 0xbefffc6c:     0xc4    0xcc    0xfc    0xb6    0x00    0x90    0xfd    0xb6

    5.打印栈帧信息:

    frame 打印当前栈帧的简要信息。

    1 (gdb) frame
    2 #0  func1 (a=11, b=22) at hello.c:17
    3 17      in hello.c

    6.info frame 打印当前栈帧的详细信息。

    1 (gdb) info frame
    2 Stack level 0, frame at 0xbefffc68:
    3  pc = 0x8434 in func1 (hello.c:17); saved pc 0x8454
    4  called by frame at 0xbefffc70
    5  source language c.
    6  Arglist at 0xbefffc64, args: a=11, b=22
    7  Locals at 0xbefffc64, Previous frame's sp is 0xbefffc68
    8  Saved registers:
    9   r11 at 0xbefffc64

    7.info frame args 打印指定栈帧的详细信息

    1 (gdb) i f 1
    2 Stack frame at 0xbefffc70:
    3  pc = 0x8454 in main (hello.c:22); saved pc 0xb6fcccc4
    4  caller of frame at 0xbefffc68
    5  source language c.
    6  Arglist at 0xbefffc6c, args:
    7  Locals at 0xbefffc6c, Previous frame's sp is 0xbefffc70
    8  Saved registers:
    9   r11 at 0xbefffc68, lr at 0xbefffc6c

    8.info args 打印函数参数信息

    1 (gdb) info args
    2 a = 11
    3 b = 22

    9.info locals 打印当前可访问的局部变量的信息。

    1 (gdb) info locals
    2 c = 0

    10.怎样知道一个栈帧的大小?

    fp和sp之间的区域就是一个函数的栈帧的大小。
    fp一般是指r11寄存器。
    sp一般是指r13寄存器。

     1 (gdb) i r
     2 r0             0xb      11
     3 r1             0x16     22
     4 r2             0xb      11
     5 r3             0x8440   33856
     6 r4             0xbeffff14       3204448020
     7 r5             0x8304   33540
     8 r6             0xbefffc80       3204447360
     9 r7             0x8      8
    10 r8             0x0      0
    11 r9             0x0      0
    12 r10            0xb6ffef7c       3070226300
    13 r11            0xbefffc64       3204447332
    14 r12            0xbefffd68       3204447592
    15 sp             0xbefffc50       0xbefffc50
    16 lr             0x8454   33876
    17 pc             0x8428   0x8428 <func1+24>
    18 cpsr           0x60000010       1610612752
    19 
    20 (gdb) disassemble
    21 Dump of assembler code for function func1:
    22    0x00008410 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)
    23 => 0x00008414 <+4>:     add     r11, sp, #0        ;将sp中的内存地址放入r11,即设置fp
    24    0x00008418 <+8>:     sub     sp, sp, #20        ;将sp中的内存地址减小20,即设置func1的栈顶指针,如上两条指令执行完后,该函数的栈帧的大小就确定了,20 bytes
    25    0x0000841c <+12>:    str     r0, [r11, #-16]    ;函数参数赋值,将r0中的值存入[r11, #-16]内存地址,即函数实参入栈
    26    0x00008420 <+16>:    str     r1, [r11, #-20]    ;函数参数赋值,将r1中的值存入[r11, #-16]内存地址
    27    0x00008424 <+20>:    ldr     r2, [r11, #-16]
    28    0x00008428 <+24>:    ldr     r3, [r11, #-20]
    29    0x0000842c <+28>:    add     r3, r2, r3
    30    0x00008430 <+32>:    str     r3, [r11, #-8]
    31    0x00008434 <+36>:    sub     sp, r11, #0
    32    0x00008438 <+40>:    pop     {r11}           ; (ldr r11, [sp], #4)
    33    0x0000843c <+44>:    bx      lr
    34 End of assembler dump.

    有时在调试过程中,想记录下来操作的过程及相关信息,那么 执行set logging on即可打卡记录,默认存在gdb.txt。

    当然也可以自己指定log文件,set logging file logname

    set logging overwrite on命令可以让输出覆盖之前的日志文件;而 “set logging redirect on”命令会让gdb的日志不会打印在终端

  • 相关阅读:
    按钮的样式
    UIButton的状态
    什么是按钮
    图标下载网站 http://www.easyicon.net/
    开发中常用的颜色
    iOS中播放音效
    imagenamed和imageWithContentOfFile的区别
    资源存放问题
    UIImageView的序列帧动画
    UIImageView的frame设置
  • 原文地址:https://www.cnblogs.com/black-mamba/p/7061248.html
Copyright © 2011-2022 走看看