为什么我的堆栈上会有奇怪的函数名?(关于符号的讨论)
符号可以包含有关全局变量、局部变量、函数名、参数、结构和源行号的信息。符号有三种类型:导出符号、pdb符号(公共符号)和专用pdb符号(专用符号)。
导出符号是dll本身的一部分。例如,ntdll.dll和kernel32.dll将其函数的很大一部分公开为导出符号,因此可以将它们称为API,但是在进程中发现的大多数dll都有一组非常小的导出符号。通常导出符号不包含函数的参数信息,并且由于很少有函数以这种方式公开,因此当只有导出符号时,您不能真正依赖堆栈的有效性。
公共符号包含一些基本符号,如函数名和全局变量,但同样,并非所有函数名都在公共符号中公开。dll的开发人员选择公开什么作为公共符号,因此他/她可以隐藏任何他们认为会泄露太多有关实现信息的内容。私人符号包含第一段中列出的几乎所有内容
调试时,通过将dll/exe链接到符号文件的GUID,符号与相应的dll或exe匹配。这意味着,如果符号搜索路径中有多个ntdll.pdb,调试器将知道哪个对应于特定版本的ntdll.dll。搜索路径由.sympath指定,除sympath中列出的内容外,调试器还将查找加载dll的目录以及环境变量_NT_SYMBOL_PATH中给定的路径中的任何内容。
如果符号是错误的的时候会发生什么?
让我们看看这个带有mscorsvr.dll公共符号的堆栈:
54 Id: 62c.1590 Suspend: 1 Teb: 7ffa2000 Unfrozen
ChildEBP RetAddr Args to Child
1212ef44 7c59a030 00000090 00000000 1212ef64 ntdll!NtWaitForSingleObject+0xb [i386\usrstubs.asm @ 2004]
1212ef6c 7c57b3db 00000090 00009c40 00000000 kernel32!WaitForSingleObjectEx+0x71 [D:\nt\private\windows\base\client\synch.c @ 1309]
1212ef7c 791b578b 00000090 00009c40 00000000 kernel32!WaitForSingleObject+0xf [D:\nt\private\windows\base\client\synch.c @ 1217]
1212efa0 791dbe6e 00000000 00000000 00000000 mscorsvr!ThreadpoolMgr::WorkerThreadStart+0x3a
1212ffb4 7c57b388 0d406838 00000002 00000000 mscorsvr!ThreadpoolMgr::intermediateThreadProc+0x44
1212ffec 00000000 791dbe2d 0d406838 00000000 kernel32!BaseThreadStart+0x52 [D:\nt\private\windows\base\client\support.c @ 460]
我们正在创建一个工作线程,然后坐下来等待工作。让我们看一看同一个堆栈,其中包含用于mscorsvr的导出符号:
0:054> kb ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 1212ef6c 7c57b3db 00000090 00009c40 00000000 ntdll!NtWaitForSingleObject+0xb *** ERROR: Symbol file could not be found. Defaulted to export symbols for mscorsvr.dll - 1212efa0 791dbe6e 00000000 00000000 00000000 kernel32!WaitForSingleObject+0xf 1212ffb4 7c57b388 0d406838 00000002 00000000 mscorsvr!GetCompileInfo+0x8e99 1212ffec 00000000 791dbe2d 0d406838 00000000 kernel32!lstrcmpiW+0xb
调试器很好,告诉我们找不到mscorsvr的符号文件,但是它给了我们一个函数名(从导出符号中),所以看起来我们正在调用一个名为GetCompileInfo的函数,嗯…很奇怪,它为什么选择这个名称?
如果我们要列出符号(导出mscorsvr的符号),我们会得到一个如下所示的列:
0:054>x mscorsvr!*
791b0000 mscorsvr!Ordinal73=791b0000 mscorsvr!Ordinal76=791b0000 mscorsvr!Ordinal77=791b0000 mscorsvr!Ordinal75=791b0000 mscorsvr!Ordinal78=791b0000 mscorsvr!Ordinal71=791b0000 mscorsvr!Ordinal79=791b0000 mscorsvr!Ordinal74=791b0000 mscorsvr!Ordinal72=791d2fd5 mscorsvr!GetCompileInfo= 791e0920 mscorsvr!GetAssemblyMDImport
- 上一篇: 仅通过转储来排除内存泄漏
- 下一篇: 使用Java中的InputStream读取文件数据