• gdb之jump指令及修改函数返回值


    一、进程调试
    主要发生在一些调试环境中,文件的编译我们可以认为比较麻烦,或者说我们并不像真正的修改源代码,因为测试的代码修改之后还要改回来;麻烦不说,如果修改之后测试代码没有改回来,那么问题就更加严重了,所以我们尽量希望通过gdb工具来环保的修改程序的行为,这样我们就可能使用到下面的一些方法和指令。
    二、修改变量值
    这个其实是比较简单的,就是大家比较常见的通过gdb的内置命令set来完成,例如,一个函数的返回值保存在一个变量iRet变量中,如果我们想修改这个变量的值,可以通过
    set iRet=10
    来动态设置变量iRet的值为10,这样其实可以改变运行的流程。
    三、跳过一些代码
    由于一些代码可能会对系统做持久性操作,例如删除文件,写数据库等操作,我们希望跳过一些函数或者代码段的执行,此时就可以使用jump指令来完成该功能。
    gdb的jump指令是对汇编语言中的jump指令的模拟,或者说是对C语言中goto语言的模拟。在被调试任务刚开始运行的时候,就可以通过jump指令来动态的修改被调试任务的PC指针,这个做法简单粗暴,但是比较有效。
    gdb中代码
    jump_command
      resolve_sal_pc (&sal);    /* May error out */
    ……
      addr = sal.pc;
    ……
      proceed (addr, TARGET_SIGNAL_0, 0);

    关键的proceed函数中对于这个解析出来的地址的处理为
    void
    proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      if (addr == (CORE_ADDR) -1)
        {
    ……
        }
      else
        {
          write_pc (addr);直接修改了被调试任务的PC指针,所以被调试任务开始运行之后直接从pc地址直接继续运行。
        }
    四、修改函数返回值。
    有些调用者并没有保存调用函数的返回值,而是直接把函数调用作为一个判断语句,例如
    if (func())
    {}
    else
    {}
    此时我们如何修改这个函数func的返回,从而让程序执行和返回值相反的操作。
    此时其实是通过体系结构相关的一些指令来完成,但是对于特定的处理器,这个指令却是可以确定的。因为386下函数的返回值都是通过eax保存的,所以我们可以直接修改这个寄存器的值即可,而修改的指令同样还是set,即
    set $eax=10
    五、一个测试的例子
    [root@Harry changereturn]# cat func.cpp 
    #include <stdio.h>
    int test()
    {
        printf("In test function ");
        return true;
    }
    int main()
    {
        if (test())
        {
        printf("return is true ");
    }
    else
    {
        printf("Return is false ");
    }
    }
    [root@Harry changereturn]# g++ func.cpp -g -o func.c.exe 
    [root@Harry changereturn]# gdb func.c.exe 
    GNU gdb (GDB) Fedora (7.0-3.fc12)
    Copyright (C) 2009 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i686-redhat-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/tsecer/CodeTest/changereturn/func.c.exe...done.
    (gdb) b main
    Breakpoint 1 at 0x8048496: file func.cpp, line 9.
    (gdb) r
    Starting program: /home/tsecer/CodeTest/changereturn/func.c.exe 

    Breakpoint 1, main () at func.cpp:9
    9        if (test())
    Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-3.i686 libgcc-4.4.2-7.fc12.i686 libstdc++-4.4.2-7.fc12.i686
    (gdb) s
    test () at func.cpp:4
    4        printf("In test function ");
    (gdb) jump 5  通过jump5直接设置地址到源代码第5行,可以看到接下来的输出中没有打印"In test function "
    Continuing at 0x8048486.
    return is true

    Program exited normally.
    (gdb) r
    Starting program: /home/tsecer/CodeTest/changereturn/func.c.exe 

    Breakpoint 1, main () at func.cpp:9
    9        if (test())
    (gdb) s
    test () at func.cpp:4
    4        printf("In test function ");
    (gdb) finish
    Run till exit from #0  test () at func.cpp:4
    In test function
    0x0804849b in main () at func.cpp:9
    9        if (test())
    Value returned is $1 = 1
    (gdb) set $eax=0 修改test函数返回值,此时主函数执行流程被修改
    (gdb) c
    Continuing.
    Return is false

    Program exited normally.
    (gdb)

  • 相关阅读:
    解决chrome浏览器无法得到window.showModalDialog返回值的问题
    Javascript 中 null、NaN和undefined的区别
    Windows Server 2003 asp网页不能访问的常见问题
    关于SQLServer无法对数据库'XXX'执行删除,因为它正用于复制。错误:'3724' 的解决方案
    关于Gridview激发了未处理的事件“RowDeleting”错误的处理
    ASP.NET中实现文件下载功能
    C#中ref和out的作用和区别
    关于Pascal(帕斯卡)以及Camel(驼峰)命名法
    期末作业验收
    SDN第五次上机作业
  • 原文地址:https://www.cnblogs.com/tsecer/p/10487424.html
Copyright © 2020-2023  润新知