一篇掌握GDB调试程序的核心技术-ptrace系统调用与使用示例( 四 )

  • eflags 寄存器的各个标志如下图:

  • 一篇掌握GDB调试程序的核心技术-ptrace系统调用与使用示例

    文章插图
     
    ?
    • 从上图可知 , eflags 寄存器的第8位就是单步调试模式的标志 。
    • 所以 ptrace() 函数的以下2行代码就是设置 eflags 进程的单步调试标志:
    【一篇掌握GDB调试程序的核心技术-ptrace系统调用与使用示例】tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;put_stack_long(child, EFL_OFFSET, tmp);
    • 而 get_stack_long(proccess, offset) 函数用于获取进程栈 offset 处的值 , 而 EFL_OFFSET 偏移量就是 eflags 寄存器的值 。
    • 所以上面两行代码的意思就是:
    1. 获取进程的 eflags 寄存器的值 , 并且设置 Trap Flag 标志 。
    2. 把新的值设置到进程的 eflags 寄存器中 。
    • 设置完 eflags 寄存器的值后 , 就调用 wake_up_process() 函数把被调试的进程唤醒 , 让其进入运行状态 。 单步调试过程如下图:

    一篇掌握GDB调试程序的核心技术-ptrace系统调用与使用示例

    文章插图
     
    ?
     
    • 处于单步调试模式时 , 被调试进程每执行一条指令都会触发一次 SIGTRAP 信号 , 而被调试进程处理 SIGTRAP 信号时会发送一个 SIGCHLD 信号给父进程(调试进程) , 并且让自己停止执行 。
    • 而父进程(调试进程)接收到 SIGCHLD 后面 , 就可以对被调试的进程进行各种操作 , 比如读取被调试进程内存的数据和寄存器的数据 , 或者通过调用 ptrace(PTRACE_CONT, child,...) 来让被调试进程进行运行等 。
    四 , 小结
    • 由于 ptrace() 的功能十分强大 , 所以本文只能抛砖引玉 , 没能对其所有功能进行分析 。另外断点功能并不是通过 ptrace() 函数实现的 , 而是通过 int3 指令来实现的 , 在 Eli Bendersky 大神的文章有所介绍 。而对于 ptrace() 的所有功能 , 只能读者自己慢慢看代码来体会了 。




    推荐阅读