实施跨步,矮人
我正在开发源代码级调试器。 elf 中可用的调试信息 格式。如何实现“跨步”? 问题出在“Point1”,无论如何我可以等待 下一个源代码行(从 .debug_line 表中读取)。
谢谢
if (a == 1)
x = 1; //Point1
else if (a == 2)
x = 1;
z = 1;
Im working on a source level debugger. The debug info available in elf
format. How could be 'step over' implemented?
The problem is at 'Point1', anyway I can wait for the
next source line (reading it from the .debug_line table).
Thanks
if (a == 1)
x = 1; //Point1
else if (a == 2)
x = 1;
z = 1;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定我完全理解这个问题,但我可以告诉你 GDB 如何实现它的
step
命令。一旦控制进入特定的编译单元,GDB 就会读取该 CU 的调试信息;特别是,它读取 .debug_line 部分的 CU 部分,并构建一个将指令地址映射到源代码位置的表。
当
步骤
开始时,GDB查找当前PC的源位置。然后它按照机器指令逐步执行,每次查找新PC的源位置,直到源位置发生变化。当源位置发生更改时,步骤
即完成。它还在每一步之后计算帧 ID(堆栈帧的基地址和函数的起始地址),并检查是否已更改。如果有,则意味着我们已进入递归调用或从递归调用中返回,并且
step
已完成。要了解为什么需要检查帧 ID 以及源位置,请考虑单步执行对以下函数的调用:
由于该函数完全在同一源代码行上定义,因此按指令单步执行直到源代码行更改将逐步执行不间断地完成所有递归调用。然而,当我们进入对fact的新调用时,堆栈帧基地址将发生变化,表明我们应该停止。这为我们提供了以下行为:
GDB 的
next
命令将此一般行为与识别函数调用并让它们返回完成的适当逻辑相结合。和以前一样,必须使用帧 ID 来确定调用何时真正返回到原始帧;还有其他并发症。值得思考一下如何处理函数的内联实例(DWARF 确实描述了这一点)。但这对于这个问题来说有点太多了。
不是为了阻止实验,但如果我要开始一个调试器项目,我想看看 Apple 的正在进行中的调试器, lldb,它是开源的。
I'm not sure I understand the question entirely, but I can tell you how GDB implements its
step
command.Once control has entered a particular compilation unit, GDB reads that CU's debugging information; in particular, it reads the CU's portion of the .debug_line section and builds a table that maps instruction addresses to source code positions.
When the
step
begins, GDB looks up the source location for the current PC. Then it steps by machine instruction, looking up the source location of the new PC each time, until the source location changes. When the source location changes, thestep
is complete.It also computes the frame ID—the base address of the stack frame, and the start address of the function—after each step, and checks if that has changed. If it has, that means that we've stepped into or returned from a recursive call, and the
step
is complete.To see why it's necessary to check the frame ID as well as the source location, consider stepping through a call to the following function:
Since this function is defined entirely on the same source line, stepping by instruction until the source line changes would step you through all the recursive calls without stopping. However, when we enter a new call to fact, the stack frame base address will have changed, indicating that we should stop. This gives us the following behavior:
GDB's
next
command combines this general behavior with appropriate logic for recognizing function calls and letting them return to completion. As before, one must use frame IDs in deciding when calls have truly returned to the original frame; and there are other complications.It's worth thinking a bit about how to treat inlined instances of functions (which DWARF does describe). But that's a bit much for this question.
Not to discourage experimentation, but if I were beginning a debugger project, I would want to look at Apple's work-in-progress debugger, lldb, which is open source.