为啥我得到错误的调试符号?

Posted

技术标签:

【中文标题】为啥我得到错误的调试符号?【英文标题】:Why i got wrong debug symbols?为什么我得到错误的调试符号? 【发布时间】:2017-07-22 02:44:30 【问题描述】:

我有下一个工作流程:

1) 构建 dll 和 pdb 文件。

2) 分享 dll 给客户

3) 分析来自客户的内存转储。

当我在 WinDbg 中运行 !analyze -v 时,我得到了(低于输出的一部分)

....
MANAGED_STACK_COMMAND:  _EFN_StackTrace
PRIMARY_PROBLEM_CLASS:  WRONG_SYMBOLS
BUGCHECK_STR:  APPLICATION_FAULT_WRONG_SYMBOLS
// some callstack here
MODULE_NAME: RTPLogic
IMAGE_NAME:  RTPLogic.dll
DEBUG_FLR_IMAGE_TIMESTAMP:  58a43706
STACK_COMMAND:  ~541s; .ecxr ; kb
FAILURE_BUCKET_ID:  WRONG_SYMBOLS_c0000374_RTPLogic.dll!CSRTPStack::Finalize
BUCKET_ID:     X64_APPLICATION_FAULT_WRONG_SYMBOLS_rtplogic!CSRTPStack::Finalize+1da

看起来我们为RTPLogic.dll 设置了错误的调试符号。 我下载了ChkMatch 工具。 我从windbg得到pdb路径

0:541> !lmi RTPlogic.dll
Loaded Module Info: [rtplogic.dll] 
         Module: RTPLogic
.....
            Age: 1, Pdb: D:\Work\path_to_original_pdb\RTPLogic.pdb
     Image Type: MEMORY   - Image read successfully from loaded memory.
    Symbol Type: PDB      - Symbols loaded successfully from image header.
                 C:\ProgramData\dbg\sym\RTPLogic.pdb\9F82CDF359044635ADEBA578CA1D1D031\RTPLogic.pdb
       Compiler: Resource - front end [0.0 bld 0] - back end [9.0 bld 21022]
    Load Report: private symbols & lines, not source indexed 
                 C:\ProgramData\dbg\sym\RTPLogic.pdb\9F82CDF359044635ADEBA578CA1D1D031\RTPLogic.pdb

我有与此转储相关的日志,并且我看到我的更改出现在日志中。所以客户在获取 memdump 之前不要忘记安装我的 DLL。 我跑ChkMatch

PS D:\tools> .\ChkMatch.exe -c "D:\Work\path_to_dll\RTPLogic.dll" "C:\Progra
mData\dbg\sym\RTPLogic.pdb\9F82CDF359044635ADEBA578CA1D1D031\RTPLogic.pdb"
.....
Result: Matched

在这种情况下我怎么可能得到错误的调试符号?

【问题讨论】:

信息太少,太模糊。你能发布一些具体的输出吗? ChkMatch 的确切输出是什么,WinDbg 中的确切警告文本是什么。符号路径是什么?这两个工具真的使用相同的文件吗?将lm.symopt.sympath 的输出发布到WinDbg 中。通常 WinDbg 根本不会加载不匹配的符号。如果是这样,你已经“调整”了一些东西 好的,但现在看起来不同的问题 您在问题中添加的内容证实了我的想法。我现在可以更有信心地回答你的问题了。 +1 用于跟进并提供必要的信息 c0000374 = 堆损坏,激活 appverifier/pageheap 以检测真正的原因,损坏发生在您的终结器尝试释放内存之前。 是的,你是对的。我只是想了解我是否拥有所有调试符号来继续使用这些标志进行调查。我担心内存损坏是我看到“错误调试符号”的原因。 【参考方案1】:

RTPLogic.dll!CSRTPStack::Finalize 的符号正确,但重建调用堆栈所需的其他符号不正确。很可能您的调用堆栈上有一些操作系统方法,并且缺少ntdll 或类似符号。

由于使用 ChkMatch,您只检查一个 PDB 文件,因此 ChkMatch 的结果(对于一个 PDB)与 WinDbg(对于许多 PDB)一样可靠和正确,并且它们不会相互矛盾。

您的 sympath 可能仅包含您自己的 DLL 的本地路径,并且不包含有关 Microsoft 符号服务器的任何信息。在.sympath(您没有发布)的输出中,我希望看到类似

0:000> .sympath
D:\Work\path_to_dll

您还应该包含 Microsoft 符号,如 How to set up symbols in WinDbg 中所述。要解决此问题,请使用以下命令:

.symfix+ c:\symbols
.reload /f

.sympath 的输出现在应该是这样的

0:000> .sympath
D:\Work\path_to_dll;SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

这应该有助于 WinDbg 重建完整的调用堆栈,解析ntdll 和其他的操作系统方法,从而摆脱“错误符号”消息。

【讨论】:

以上是关于为啥我得到错误的调试符号?的主要内容,如果未能解决你的问题,请参考以下文章

链接器错误 - 未定义的符号

为啥 gcc 在非调试版本中添加符号?

如何将调试符号添加到 Audacious?

为啥 XCode 会抛出重复的符号错误?

为啥我的 C 结构在输入中没有得到任何数据?

使用安装了 GCC 4.9 的 MacPorts 调试符号错误?