如何从 Delphi 程序或编译器生成的调试信息中提取局部变量信息(地址和类型) ?

我的目标是:

  • 在 Delphi 编译的32位或64位 Windows 程序中给定一个挂起的线程,遍历堆栈(可行)
  • 给定堆栈条目,枚举每个方法中的局部变量及其值。也就是说,至少可以找到它们的地址和类型(intger32/64/signed/unsigned,string,float,record,class...) ,它们的组合可以用来找到它们的值。

第一个是好的,这是第二个,这个问题是关于。在高层次上,如何在 Delphi 中枚举给定堆栈条目的局部变量?


从低层面来说,这就是我一直在调查的:

RTTI: 没有列出这种关于方法的信息。这不是我真正认为是一个现实的选择,但列在这里无论如何。

调试信息: 加载为调试构建生成的调试信息。

  • 地图文件: 甚至一个详细的地图文件(文本格式的文件!打开一个并查看)不包含本地变量信息。它基本上是一个地址和源文件行号的列表。对于地址到文件和行的相关性很好,例如在排水沟中的蓝点; 对于更详细的信息不太好
  • 远程调试信息(RSM 文件)-关于其内容或格式的 没有已知信息
  • TD32/TDS 文件: 我目前的研究方向。它们包含全局和局部符号以及许多其他信息。

我在这里遇到的问题是:

  • 没有关于 TD32文件格式的文档(我可以找到)
  • 我对它们的大部分知识来自使用它们的绝地 JCL 代码(JclTD32.pas) ,我不确定如何使用该代码,或者那里的结构是否足够广泛以显示局部变量。我很确定它能处理全局符号,但我不确定局部符号。定义了各种各样的常量,但是没有关于格式的文档,我只能靠猜测来理解它们的含义。但是,这些常量和它们的名称必须来自某个地方。
  • 来源我可以找到使用 TDS 信息 不加载或处理本地符号。

如果这是正确的方法,那么这个问题就变成了‘是否有 TDS/TD32文件格式的文档,是否有加载本地变量的代码示例?'

代码示例不是必需的,但可能非常有用,即使它非常小。

2316 次浏览

Check if any debugging symbols weren't in binary. Also possible is using GDB (on Windows a port of it). It would be great if you found a .dbg or .dSYM file. They contain source code, eg.

gdb> list foo
56 void foo()
57 {
58  bar();
59  sighandler_t fnc = signal(SIGHUP, SIG_IGN);
60  raise(SIGHUP);
61  signal(SIGHUP, fnc);
62  baz(fnc);
63 }

If you don't have any debugging files, you may try to get MinGW or Cygwin, and use nm(1) (man page). It will read symbol names from binary. They may contain some types, like C++ ones:

int abc::def::Ghi::jkl(const std::string, int, const void*)

Don't forget to add --demangle option then or you'll get something like:

__ZN11MRasterFont21getRasterForCharacterEh

instead of:

MRasterFont::getRasterForCharacter(unsigned char)

Take a look at the http://download.xskernel.org/docs/file%20formats/omf/borland.txt Open Architecture Handbook. It is old, but maybe you find some relevant information about the file format.