做推广 vim wavedorm 动态条形图 jpa eloquent outlook vue router linux内存管理 jquery触发change事件 erp项目描述 coreldraw学习 js获取月份 ceb转换成pdf在线转换 c语言求和 python数据 python写文件 python模块下载 java时间戳转换成时间 java学习手册 javafloat kafka中文教程 vbscript程序员参考手册 刷机工具下载 lseek函数 只狼鬼佛 idea重命名快捷键 keytool下载 java核心技术 HTML5从入门到精通 ps调整边缘抠头发丝 子节点 备份数据的软件 超过响应缓冲区限制 数据结构与算法分析 逆战丛林魅影 ipad内存怎么清理 idea下载 ae渲染设置 谷歌浏览器xp版下载
当前位置: 首页 > 学习教程  > 编程语言

GDB使用技巧(3)——查看栈信息

2020/9/19 16:25:50 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

查看栈信息

当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。

下面是一些查看函数调用栈信息的GDB命令:

  • backtrace
  • bt

    打印当前的函数调用栈的所有信息。如:

  •     (gdb) bt
  •     #0  func (n=250) at tst.c:6
  •     #1  0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
  •     #2  0x400409ed in __libc_start_main () from /lib/libc.so.6 

    从上可以看出函数的调用栈信息:__libc_start_main --> main() --> func()
   

  • backtrace <n>
  • bt <n>

    n是一个正整数,表示只打印栈顶上n层的栈信息。

  • backtrace <-n>
  • bt <-n>

    -n表一个负整数,表示只打印栈底下n层的栈信息。
       
如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。

  • frame <n>
  • f <n>

    n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

  • up <n>

    表示向栈的上面移动n层,可以不打n,表示向上移动一层。
   

  • down <n>

    表示向栈的下面移动n层,可以不打n,表示向下移动一层。
   

上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:

  •     select-frame <n> 对应于 frame 命令。
  •     up-silently <n> 对应于 up 命令。
  •     down-silently <n> 对应于 down 命令。

查看当前栈层的信息,你可以用以下GDB命令:

  • frame 或 f

    会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。

  • info frame
  • info f

        这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:

(gdb) info f
Stack level 0, frame at 0xbffff5d4:
eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
called by frame at 0xbffff60c
source language c.
Arglist at 0xbffff5d4, args: n=250
Locals at 0xbffff5d4, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8   
  • info args

   打印出当前函数的参数名及其值。

  • info locals

   打印出当前函数中所有局部变量及其值。
  

  • info catch

   打印出当前的函数中的异常处理信息。

            
查看源程序

一、显示源代码

GDB 可以打印出所调试程序的源代码,当然,在程序编译时一定要加上-g的参数,把源程序信息编译到执行文件中。不然就看不到源程序了。当程序停下来以后,GDB会报告程序停在了那个文件的第几行上。你可以用list命令来打印程序的源代码。还是来看一看查看源代码的GDB命令吧。
   

  • list <linenum>

    显示程序第linenum行的周围的源程序。

  • list <function>

    显示函数名为function的函数的源程序。
   

  • list

    显示当前行后面的源程序。

  • list -

    显示当前行前面的源程序。

一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。

  • set listsize <count>

    设置一次显示源代码的行数。
   

  • show listsize

    查看当前listsize的设置。
       

list命令还有下面的用法:

  • list <first>, <last>

    显示从first行到last行之间的源代码。

  • list , <last>

    显示从当前行到last行之间的源代码。
   

  • list +

    往后显示源代码。
       

 

<linenum>   行号。
<+offset>   当前行号的正偏移量。
<-offset>   当前行号的负偏移量。
<filename:linenum>  哪个文件的哪一行。
<function>  函数名。
<filename:function> 哪个文件中的哪个函数。
<*address>  程序运行时的语句在内存中的地址。

一般来说在list后面可以跟以下这们的参数:

 

二、搜索源代码

不仅如此,GDB还提供了源代码搜索的命令:

  • forward-search <regexp>
  • search <regexp>

    向前面搜索。

  • reverse-search <regexp>

        全部搜索。
       
其中,<regexp>就是正则表达式,也主一个字符串的匹配模式,关于正则表达式,我就不在这里讲了,还请各位查看相关资料。


三、指定源文件的路径

某些时候,用-g编译过后的执行程序中只是包括了源文件的名字,没有路径名。GDB提供了可以让你指定源文件的路径的命令,以便GDB进行搜索。

  • directory <dirname ... >
  • dir <dirname ... >

    加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可以使用“:”,Windows下你可以使用“;”。

  • directory

    清除所有的自定义的源文件搜索路径信息。

  • show directories

    显示定义了的源文件搜索路径。
       

四、源代码的内存

你可以使用info line命令来查看源代码在内存中的地址。info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”,这个命令会打印出所指定的源码在运行时的内存地址,如:

(gdb) info line tst.c:func
Line 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <func+13>.

还有一个命令(disassemble)你可以查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令dump出来。如下面的示例表示查看函数func的汇编代码。

(gdb) disassemble func
Dump of assembler code for function func:
0x8048450 <func>:       push   %ebp
0x8048451 <func+1>:     mov    %esp,%ebp
0x8048453 <func+3>:     sub    $0x18,%esp
0x8048456 <func+6>:     movl   $0x0,0xfffffffc(%ebp)
0x804845d <func+13>:    movl   $0x1,0xfffffff8(%ebp)
0x8048464 <func+20>:    mov    0xfffffff8(%ebp),%eax
0x8048467 <func+23>:    cmp    0x8(%ebp),%eax
0x804846a <func+26>:    jle    0x8048470 <func+32>
0x804846c <func+28>:    jmp    0x8048480 <func+48>
0x804846e <func+30>:    mov    %esi,%esi
0x8048470 <func+32>:    mov    0xfffffff8(%ebp),%eax
0x8048473 <func+35>:    add    %eax,0xfffffffc(%ebp)
0x8048476 <func+38>:    incl   0xfffffff8(%ebp)
0x8048479 <func+41>:    jmp    0x8048464 <func+20>
0x804847b <func+43>:    nop
0x804847c <func+44>:    lea    0x0(%esi,1),%esi
0x8048480 <func+48>:    mov    0xfffffffc(%ebp),%edx
0x8048483 <func+51>:    mov    %edx,%eax
0x8048485 <func+53>:    jmp    0x8048487 <func+55>
0x8048487 <func+55>:    mov    %ebp,%esp
0x8048489 <func+57>:    pop    %ebp
0x804848a <func+58>:    ret
End of assembler dump.

 


本文链接: http://www.dtmao.cc/news_show_200422.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?