给 continue_execution 打补丁
在我们测试我们的更改之前,我们如今可以实现一个更健全的 continue_execution 版本。因为我们可以获取法度榜样计数器,我们可以检查我们的断点映射来断定我们是否处于一个断点。如不雅是的话,我们可以停用断抱病在持续之前跳过它。
为了清楚和简洁起见,起首我们要添加一些赞助函数:
就快完成啦,如今我们已经有了存放器名称查找:
然后我们可以编写函数来跳过断点:
如今我们会给我们的用户界面添加敕令:
- void debugger::step_over_breakpoint() {
- // - 1 because execution will go past the breakpoint
- auto possible_breakpoint_location = get_pc() - 1;
- if (m_breakpoints.count(possible_breakpoint_location)) {
- auto& bp = m_breakpoints[possible_breakpoint_location];
- if (bp.is_enabled()) {
- auto previous_instruction_address = possible_breakpoint_location;
- set_pc(previous_instruction_address);
- bp.disable();
- ptrace(PTRACE_SINGLESTEP, m_pid, nullptr, nullptr);
- wait_for_signal();
- bp.enable();
- }
- }
- }
起首我们检查当前法度榜样寂?骥的值是否设置了一个断点。如不雅有,起首我们把履行返回到断点之前,停用它,跳过本来的指令,再从新启用断点。
wait_for_signal 封装了我们常用的 waitpid 模式:
- void debugger::wait_for_signal() {
- int wait_status;
- auto options = 0;
- waitpid(m_pid, &wait_status, options);
- }
最后我们像下面如许重写 continue_execution:
- void debugger::continue_execution() {
- step_over_breakpoint();
- ptrace(PTRACE_CONT, m_pid, nullptr, nullptr);
- wait_for_signal();
- }
测试效不雅
如今我们可以攫取和修改存放器了,我们可以对我们的 hello world 法度榜样做一些有意思的更改。类似第一次测试,再次测验测验在 call 指令处设置断点然后大年夜那边持续履行。你可以看到输出了 Hello world。如今是有趣的部分,在输出调用后设一个断点、持续、将 call 参数设置代码的地址写入法度榜样计数器(rip)并持续。因为法度榜样计数器把持,你应当再次看到输出了 Hello world。为了以防你不肯定在哪里设置断点,下面是我上一篇博文中的 objdump 输出: