开发一个Linux调试器(三):寄存器和内存

  • 时间:
  • 浏览:0
  • 来源:大发彩神UU直播_大发神彩UU直播官方

在大家真正读取任何寄存器完后 ,大家才能 告诉调试器全都关于大家的目标平台的信息,这里是 x8664 平台。除了多组通用和专用目的寄存器,x8664 还提供浮点和向量寄存器。为了冗杂,我将跳完后 一种寄存器,但有你在身边肯能喜欢说说也还才能选者支持它们。x86_64 也允许你像访问 32、16 肯能 8 位寄存器那样访问全都 64 位寄存器,但我只会介绍 64 位寄存器。肯能那些冗杂,对于每个寄存器大家只才能 它的名称、它的 DWARF 寄存器编号以及 ptrace 返回形态体中的存储地址。我使用范围枚举引用那些寄存器,但会 我列出了一有一个全局寄存器描述符数组,其中元素顺序和 ptrace 中寄存器形态体相同。

set_register_value 非常类事,大家还会写入该位置并在最后写回寄存器:

随着底下文章的发布,那些链接会逐渐生效。

但会 大家还才能编写函数来跳过断点:

系列文章索引

wait_for_signal 封装了大家常用的 waitpid 模式:

给你在这里找到这篇博文的代码。

现在大家还才能编写一堆函数来和寄存器交互。大家希望还才能读取寄存器、写入数据、根据 DWARF 寄存器编号获取值,以及通过名称查找寄存器,反之类事。我不想们先从实现 get_register_value 开始英文英文英文:

为了清晰和简洁起见,首先大家要加在全都帮助函数:

在下一篇博客中,大家会第一次接触到 DWARF 信息并给大家的调试器加在一系列逐步调试的功能。完后 ,大家会一有一个功能工具,它能逐步执行代码、在不想的地方设置断点、修改数据以及其它。一如以往,肯能你有任何难题请留下你的评论!

作者:Simon Brand

到 uint64_t 的转换是安全的,肯能 user_regs_struct 是一有一个标准布局类型,但我认为指针算术技术上是未定义的行为undefined behavior。当前那末 编译器会对此产生警告,我也懒得修改,但会 肯能你想保持最严格的正确性,那就写一有一个大的 switch 说说。

显示大家的寄存器

在大家测试大家的更改完后 ,大家现在还才能实现一有一个更健全的 continue_execution 版本。肯能大家还才能获取多多任务管理器 计数器,大家还才能检查大家的断点映射来判断大家不是处在一有一个断点。肯能是说说,大家还才能停用断点并在继续完后 跳过它。

就快完成啦,现在大家肯能有了寄存器名称查找:

ptrace 使得大家还才能轻易获得大家不想的数据。大家只才能 构造一有一个 user_regs_struct 实例并把它和 PTRACE_GETREGS 请求传递给 ptrace。

最后大家像下面完后 重写 continue_execution:

来源:51CTO

给 continue_execution 打补丁

现在大家还才能读取和修改寄存器了,大家还才能对大家的 hello world 多多任务管理器 做全都有意思的更改。类事第一次测试,再次尝试在 call 指令处设置断点但会 从那里继续执行。给你看得人输出了 Hello world。现在是有趣的每种,在输出调用后设一有一个断点、继续、将 call 参数设置代码的地址写入多多任务管理器 计数器(rip)并继续。肯能多多任务管理器 计数器操纵,你应该再次看得人输出了 Hello world。为了以防你不选者在哪里设置断点,下面是我上一篇博文中的 objdump 输出:

你肯能不想加在支持一次读取肯能写入多个字节,给你在每次希望读取完后 字节时通过递增地址来实现。肯能你才能 说说,你也还才能使用 process_vm_readv 和 process_vm_writev 或 /proc/<pid>/mem 代替 ptrace。

我不想将多多任务管理器 计数器移回 0x100093a 以便正确设置 esi 和 edi 寄存器。

注册大家的寄存器

最后大家会加在一有一个简单的帮助函数用于导出所有寄存器的内容:

设置断点的完后 大家肯能读取和写入内存,但会 大家只才能 加在全都函数用于隐藏 ptrace 调用。

下一步是通过 DWARF 寄存器编号查找。这次我会真正检查一有一个错误条件以防大家得到全都奇怪的 DWARF 信息。

首先大家检查当前多多任务管理器 计算器的值不是设置了一有一个断点。肯能有,首先大家把执行返回到断点完后 ,停用它,跳过完后 的指令,再重新启用断点。

现在大家会给大家的用户界面加在命令:

这里大家要做的还会给 handle_command 函数加在一有一个命令。通过下面的代码,用户还才能输入 register read rax、 register write rax 0x42 以及类事的说说。

接下来做那些?

肯能你想自己看看说说,你通常还才能在 /usr/include/sys/user.h 找到寄存器数据形态,另外 DWARF 寄存器编号取自 System V x86_64 ABI。

测试效果

上一篇博文中大家给调试器加在了一有一个简单的地址断点。这次,大家将加在读写寄存器和内存的功能,这将使大家才能使用大家的多多任务管理器 计数器、观察请况和改变多多任务管理器 的行为。

现在根据要请求的寄存器,大家要读取 regs。大家还才能写一有一个很大的 switch 说说,但肯能大家 g_register_descriptors 表的布局顺序和 user_regs_struct 相同,大家只才能 搜索寄存器描述符的索引,但会 作为 uint64_t 数组访问 user_regs_struct 就行。(你也还才能重新排序 reg 枚举变量,但会 使用索引把它们转换为底层类型,但第一次给你使用全都 辦法 编写,它能正常工作,我也就懒得改它了。)

正如你看得人的,iostreams 有非常精确的接口用于美观地输出十六进制数据(啊哈哈哈哈哈哈)。肯能你喜欢你也还才能通过 I/O 操纵器来摆脱全都 混乱。

那些肯能足够支持大家在调试器接下来的每种轻松处在理寄存器,全都大家现在还才能把那些加在到大家的用户界面。