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

Dav*_*vid 105 delphi stack local-variables debug-symbols

我的目标是:

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

第一个很好,这是这个问题的第二个问题.在高级别,如何在Delphi中给出堆栈条目枚举局部变量?


在较低的水平,这是我一直在调查:

RTTI:没有列出有关方法的这类信息.这不是我实际上认为是一个现实的选择,但无论如何列在这里.

调试信息:加载为调试版本生成的调试信息.

  • 映射文件:即使是详细的映射文件(文本格式文件!打开并查看)也不包含本地变量信息.它基本上是地址列表和源文件行号.非常适合文件和行相关的地址,例如装订线中的蓝点; 不是更好的更详细的信息
  • 远程调试信息(RSM文件) - 没有关于其内容或格式的已知信息.
  • TD32/TDS文件:我目前的研究方向.它们包含许多其他信息中的全局和局部符号.

我遇到的问题是:

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

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

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

Top*_*ret 2

检查是否有任何调试符号不是二进制的。也可以使用 GDB(在 Windows 上是它的一个端口)。如果您找到 .dbg 或 .dSYM 文件,那就太好了。它们包含源代码,例如。

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 }
Run Code Online (Sandbox Code Playgroud)

如果您没有任何调试文件,您可以尝试获取 MinGW 或 Cygwin,并使用 nm(1) (手册页)。它将从二进制中读取符号名称。它们可能包含一些类型,例如 C++ 类型:

int abc::def::Ghi::jkl(const std::string, int, const void*)
Run Code Online (Sandbox Code Playgroud)

不要忘记添加--demangle选项,否则你会得到类似的结果:

__ZN11MRasterFont21getRasterForCharacterEh
Run Code Online (Sandbox Code Playgroud)

代替:

MRasterFont::getRasterForCharacter(unsigned char)
Run Code Online (Sandbox Code Playgroud)

  • 雅各布,谢谢你的回答。不幸的是,我可能需要阅读特定的调试格式 - TDS。Delphi 应用程序在 Windows 上不使用与 GDB 兼容的调试信息进行编译。我也不确定 nm 将如何提供帮助,因为它将依赖于一种特定的调试文件格式,而该格式可能不是 Delphi 生成的格式。或者我是否误解了你的答案 - 例如,GDB 可以读取 Delphi 的符号吗? (2认同)