这里的大年夜部分代码都是跟踪状况;真正神奇的处所是 enable 和 disable 函数。
正如我们膳绫擎学到的,我们要用 int 3 指令 - 编码为 0xcc - 调换当前指定地址的指令。我们还要保存该地址之前的值,以便后面恢复该代码;我们不想忘了履行用户(本来)的代码。
我前面说软件断点是经由过程修改┞俘在履行的代码实现的,那么问题就来了:
- 我们若何修改代码?
- 为了设置断点我们要做什么修改?
- 若何告诉调试器?
- void breakpoint::enable() {
- m_saved_data = ptrace(PTRACE_PEEKDATA, m_pid, m_addr, nullptr);
- uint64_t int3 = 0xcc;
- uint64_t data_with_int3 = ((m_saved_data & ~0xff) | int3); //set bottom byte to 0xcc
- ptrace(PTRACE_POKEDATA, m_pid, m_addr, data_with_int3);
- m_enabled = true;
- }
PTRACE_PEEKDATA 请求告诉 ptrace 若何攫取被跟踪过程的内存。我们给它一个过程 ID 和一个地址,然后它返回给我们该地址当前的 64 位内容。 (m_saved_data & ~0xff) 把这个数据的低位字节置零,然后我们用它和我们的 int 3 指令按位或(OR)来设置断点。最后我们经由过程 PTRACE_POKEDATA 用我们的新数据覆盖那部分内存来设置断点。
disable 的实现比较简单,我们只须要恢复竽暌姑 0xcc 所覆盖的原始数据。
- void breakpoint::disable() {
- ptrace(PTRACE_POKEDATA, m_pid, m_addr, m_saved_data);
- m_enabled = false;
- }
在调试器中增长断点
为了支撑经由过程用户界面设置断点,我们要在 debugger 类修改三个处所:
- 给 debugger 添加断点存储数据构造
- 添加 set_breakpoint_at_address 函数
- 给我们的 handle_command 函数添加 break 敕令
总结
我会将我的断点保存到 std::unordered_map<std::intptr_t, breakpoint> 构造,以便能简单快速地断定一个给定的地址是否有断点,如不雅有的话,取回该 breakpoint 对象。
- class debugger {
- //...
- void set_breakpoint_at_address(std::intptr_t addr);
- //...
- private:
- //...
- std::unordered_map<std::intptr_t,breakpoint> m_breakpoints;
- }
在 set_breakpoint_at_address 函数中我们会新建一个 breakpoint 对象,启用它,把它添加到数据构造里,并给用户打印一条信息。如不雅你爱好的话,你可以重构所有的输出信息,大年夜而你可以将调试器作为库或者敕令行对象应用,为了简便,我把它们都整合到了一路。
- void debugger::set_breakpoint_at_address(std::intptr_t addr) {
- std::cout << "Set breakpoint at address 0x" << std::hex << addr << std::endl;
- breakpoint bp {m_pid, addr};
推荐阅读
《筹划》强调,“十三五”时代金融业要周全支撑深化改革,积极对标国际先辈,推动立异普惠成长,保持安然与成长并重,并环绕兼顾监管体系重要性金融机构、兼顾监管金融控股公司>>>详细阅读
本文标题:开发一个Linux调试器(二):断点
地址:http://www.17bianji.com/lsqh/35948.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示