
debugger
文章平均质量分 70
瑜陀
Sophomore, major in Computer Science.
展开
-
debugger(七):栈帧(backtrace)
通过读取帧指针(frame pointer)和返回地址来遍历整个调用栈,直到达到main函数为止。每次循环都会输出当前函数的栈帧信息,并更新帧指针和返回地址以跳转到下一个栈帧。原创 2024-06-11 20:37:04 · 202 阅读 · 0 评论 -
debugger(六):source level 断点
这个可以在所有的编译单元中搜索。对于每一个 **cu**,只需要判断:`(die.has(dwarf::DW_AT::name) && at_name(die) == name)`,如果条件成立,那么就可以获取 **line entry** 了,但是这个 **entry** 并不好用,这一行可能是函数名,我们需要跳过这个 **prologue** 或者没用的行。原创 2024-06-11 18:37:27 · 213 阅读 · 0 评论 -
debugger(五):source level stepping
返回地址实际上是在调用函数之前的步骤中由调用指令(如 call)隐式处理的,它会将下一条指令的地址(即函数 f() 的地址)压入栈中,作为返回时应该跳转的地址。这里就很清晰了,因为在这之后,紧接着入栈的是 rbp,接着是把 rsp 放入 rbp,当前 rbp 中值就是那时候的 rsp,也是新的栈帧。我们只要把 rbp+8,就能得到它了。原创 2024-06-11 18:00:33 · 935 阅读 · 0 评论 -
debugger(四):源代码
注意这个 pc 是一个 offset addr,传参的时候一定要转换。思路很简单,首先遍历所有的 cu,然后判断 cu 的 low_pc 和 high_pc,如果在这个 cu 符合,那么就通过 cu 拿到 cu.root。cu.root 是一个根 die,通过它可以遍历所有的 die。之后再判断 die的 tag 是不是一个函数,如果是且包含 pc,那么就是我们要找的函数。原创 2024-06-10 22:36:15 · 426 阅读 · 0 评论 -
debugger(三):dwarf 文件
在讨论 DWARF 格式的调试信息时,编译单元(Compilation Unit, CU)和行表(Line Table)是两个核心概念。这些信息极大地促进了源码级调试,使调试器能够有效地将执行的机器代码映射回源代码。原创 2024-06-10 21:46:30 · 1424 阅读 · 0 评论 -
debugger(二):读、写内存以及寄存器
可以看到非常成功,利用 memory write 成功打了一个“断点”。事实上,这个断点只是暂时的,它并没有被记录在 debug 信息系统中,不过这不重要,这只是在验证 memory write 的功能。原创 2024-06-10 20:40:27 · 626 阅读 · 0 评论 -
debugger(一):打断点的实现以及案例分析
编译后,我们要打断点进行测试,可以看到目前只能传入一个地址,这个地址还是 0x 开头的 16 进制地址,我们对于这个地址丝毫没有头绪,因为我们不知道 std::cerr原创 2024-05-25 23:32:01 · 945 阅读 · 0 评论