在X86上用gdb设置带函数入参判断的条件断点

来源:互联网 发布:淘宝买隐形眼镜靠谱吗 编辑:程序博客网 时间:2024/06/05 12:03

        最近在X86虚拟机上调试单板代码,使用gdb的时候遇到一个问题。

        有时候我们为一个函数设置断点,但是这个函数被调用到的频率太大,会频繁的被断住,实际上只需要一些特殊的情况才需要停住, 这就需要在断点处进行条件判断。

如果需要判断的是一个全局变量,则可以这样:

  b   func if g_val=0      //当全局变量为0的时候,才会在func的入口处停止。

或者是一个全局地址:

  b func  if  *(int*)address=0    //当地址address的int型数据为0的时候,才在func的入口处停止。

    但是如果你想判断一个函数入参的时候,如果这样做:

   b func if p1=0   //p1是func(int p1, int p2, int p3, int p4)的第一个入参名。

  会返回错误:

    No symbol "p1" in current context.

  为什么?这是因为p1是一个临时变量,你在进行断点设置的时候(进行全局动作)这个参数不存在的。

 

   那么怎么对函数的输入参数进行判断呢? 这需要先了解一下不同平台的函数调用和参数传递规则。

   如果是我们熟悉的arm板上,则很明了,一般对r0-r3寄存器值进行判断就好了,但是在x86上该怎么做呢?

   首先,看下面这篇文档了解下基本概念:

    http://blog.sinzy.net/ifyr/entry/4929

   可以知道在X86平台上一般是使用栈(esp)来传递调用函数参数的。

   然后写下面一段代码

    func(1,2,3,4)  //调用函数func(int p1, int p2, int p3, int p4)

    使用objdump反汇编,得出如下:
 826fbce: c7 44 24 10 00 00 00  movl   $0x4,0xc(%esp)   //第4个参数压栈到0xc偏移
 826fbd5: 00
 826fbd6: c7 44 24 0c 01 00 00  movl   $0x3,0x8(%esp)   //第3个参数压栈到0x8偏移
 826fbdd: 00 
 826fbe2: c7 44 24 04 66 09 00  movl   $0x2,0x4(%esp)  //第2个参数压栈到0x4偏移
 826fbe9: 00
 826fbea: c7 04 24 0a 00 00 00  movl   $0x1,(%esp)       //第1个参数压栈到0x0偏移
 826fbf1: e8 99 18 f9 ff        call   820148f <func>              //调用func,esp为栈顶指针寄存器,传入参数。

  然后运行程序,在func设断点停住后:

 (gdb) p $esp
$18 = (void *) 0xbffff4ec
(gdb) x/16 $esp
0xbffff4ec:     0x0826ab98      0x00000001      0x00000002     0x00000003
0xbffff4fc:     0x00000004      0x00000000      0x00000000      0x00000000
0xbffff50c:     0x00000001      0x00000000      0x00000000      0x00000000
0xbffff51c:     0x000000c8      0x08a88ff4      0x08a88ff4      0xbffff568
(gdb)

可以看到esp的值是0xbffff4ec,但是参数1的值保存在他的下一个地址,就是0xbffff4f0

这样就可以推算出入参条件断点的表达式了:

b func if *((int*)$esp+1)=11    //当第一个输入参数值为11的时候才停住。

b func if *((int*)$esp+2)=22 //当第二个输入参数值为22的时候才停住。

b func if *((int*)$esp+3)=33 //当第三个输入参数值为33的时候才停住。

b func if *((int*)$esp+4)=44 //当第四个输入参数值为44的时候才停住。

 

 

 

0 0
原创粉丝点击