【问题标题】:How to read the parent thread or parent function of a thread or call stack如何读取父线程或线程或调用堆栈的父函数
【发布时间】:2018-08-06 14:24:54
【问题描述】:

我正在尝试解密 StackOverflowException 崩溃转储。

调用堆栈,如 Visual Studio 中所示,如下所示:

ntdll.dll!RtlAllocateHeap()
[Inline Frame] combase.dll!CRetailMalloc_Alloc(IMalloc *) Line 640
combase.dll!CoTaskMemAlloc(unsigned __int64 stcb) Line 459
shell32.dll!CFSFolder::_InitFolder()
shell32.dll!CFSFolder::_Bind()
shell32.dll!CFSFolder::BindToObject()
shell32.dll!CRegFolder::BindToObject()
shell32.dll!CRegFolder::BindToObject()
shell32.dll!SHBindToObject()
shell32.dll!SHGetAttributesWithBindCtx()
shell32.dll!CShellLink::_IsTargetAnotherLink()
shell32.dll!CShellLink::_LoadIDList()
shell32.dll!CShellLink::_LoadFromStream()
shell32.dll!CShellLink::_LoadFromFile()
shell32.dll!CShellLink::Load(unsigned short const *,unsigned long)

这似乎不是很有趣。然而,在 Windbg 中,~kb 命令提供了更多信息:

0:040> ~kb
 # RetAddr           : Args to Child                                                           : Call Site
00 00007ffc`9d5f184a : 00000000`000001b0 00000000`00000002 00000000`00000002 00000000`1e492250 : ntdll!RtlAllocateHeap+0xd2
01 (Inline Function) : --------`-------- --------`-------- --------`-------- --------`-------- : combase!CRetailMalloc_Alloc+0x12 [d:\blue\com\combase\class\memapi.cxx @ 640] 
02 00007ffc`9e3dd4fe : 00000000`000001ad 00000000`00000000 00000000`000001ad 00007ffc`9fa30d67 : combase!CoTaskMemAlloc+0x3a [d:\blue\com\combase\class\memapi.cxx @ 459] 
03 00007ffc`9e3dcf2d : 00007ffc`9e561188 00000000`00000000 00000000`1a6053e0 00007ffc`9e561188 : shell32!CFSFolder::_InitFolder+0xd2
04 00007ffc`9e3dc685 : 00000000`1b803198 00007ffc`9e34203d 00000000`1a1a8580 00007ffc`9e3420c0 : shell32!CFSFolder::_Bind+0x9d1
05 00007ffc`9e3de676 : 00000000`1e7c4af4 00007ffc`9e561188 00000000`00000000 00007ffc`9fa30d67 : shell32!CFSFolder::BindToObject+0x664
06 00007ffc`9e3db94c : 00007ffc`9d5f1860 00430072`006f0046 00000000`00000003 ffffffff`fffffffe : shell32!CRegFolder::BindToObject+0x8bd
07 00007ffc`9e3dafda : 00000000`1e638820 00000000`00000000 00000000`1e7c4ae0 00007ffc`9e3dff07 : shell32!CRegFolder::BindToObject+0x687
08 00007ffc`9e40c041 : 00000000`00000000 00000000`1e80c2a0 00000000`00000000 00006567`8ccde5e5 : shell32!SHBindToObject+0x11d
09 00007ffc`9e408a7b : 00000000`1e638820 00000000`1e7c4ae0 00000000`00000001 00000000`00410000 : shell32!SHGetAttributesWithBindCtx+0x1a0
0a 00007ffc`9e40958f : 00000000`00000000 00000000`00000000 00000000`1a1a9630 00000000`00000000 : shell32!CShellLink::_IsTargetAnotherLink+0x7b
0b 00007ffc`9e40886b : 00000000`00000048 00000000`1e6389e0 00000000`00000000 00000000`1a1a96a0 : shell32!CShellLink::_LoadIDList+0x4b
0c 00007ffc`9e40b3f9 : 00000000`00000000 00000000`1e638820 00000000`00000000 00000000`80000000 : shell32!CShellLink::_LoadFromStream+0x2da
0d 00007ffc`9e40b359 : 00007ffc`8d49c3d9 00000000`1a1a99f8 00000000`00003201 00000000`1f95b1e4 : shell32!CShellLink::_LoadFromFile+0x8f
0e 00007ffc`2ea805f9 : 00000000`00000000 00000000`1a1a9d20 00000000`00000000 00000000`1f95b280 : shell32!CShellLink::Load+0x25
0f 00007ffc`2ea80479 : 00000000`1f95b280 00000000`00000000 00000000`1f95b1d8 00000000`00000000 : 0x00007ffc`2ea805f9
10 00007ffc`2ea8036c : 00000000`00000000 00000000`00000000 00000000`1f95b1b8 00000000`022c55e8 : 0x00007ffc`2ea80479
11 00007ffc`2ea802cd : 00000000`1f95b1d8 00007ffc`2e5d4a3c 00000000`00000000 00000000`022c55e8 : 0x00007ffc`2ea8036c
12 00007ffc`2ea7eae2 : 00000000`04233f90 00009ebd`de3821dd 00000000`00000003 00000000`00000003 : 0x00007ffc`2ea802cd
13 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f9571c0 00000000`00000003 : 0x00007ffc`2ea7eae2
14 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f94ec10 00000000`00000003 : 0x00007ffc`2ea7ee80
15 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f946660 00000000`00000003 : 0x00007ffc`2ea7ee80
16 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f93e0b0 00000000`00000003 : 0x00007ffc`2ea7ee80
17 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f935b00 00000000`00000003 : 0x00007ffc`2ea7ee80
...
ff 00007ffc`2ea7ee80 : 00000000`02619df0 00009ebd`de3821dd 00000000`1f744808 00000000`00000003 : 0x00007ffc`2ea7ee80

这似乎与 StackOverflowException(调用堆栈中的调用过多)一致:确实,内存地址 0x00007ffc'2ea7ee80 处的函数 - 出于格式化原因,我用单引号替换了反引号 - 不断调用自身。

现在的问题是:我怎么知道这是哪个函数或哪个是父线程?

至于 Windbg:当我点击最后一个条目时(ff,DMS 已启用),我看到以下内容:

0:040> dx Debugger.Sessions[0].Processes[10912].Threads[5268].Stack.Frames[255].SwitchTo();dv /t /v
Debugger.Sessions[0].Processes[10912].Threads[5268].Stack.Frames[255].SwitchTo()
Unable to enumerate locals, Win32 error 0n318
Private symbols (symbols.pri) are required for locals.
Type ".hh dbgerr005" for details

供您参考:在 Visual Studio 的Parallel Stacks 窗口中,我没有看到线程,指的是这个。

有人有想法吗?
提前致谢

【问题讨论】:

  • 在调用堆栈中看到一个裸地址意味着它的代码不在模块中。当涉及到 .NET 时,这通常意味着它是 JIT 代码。 ip2md 命令是SOS extension 的一部分,您可能会有一些运气。运行.loadby sos clr 后跟!ip2md 0x00007ffc2ea802cd 会告诉你什么吗?
  • 由于这是 .NET,这可能是 JITted 代码,请使用 SOS 扩展 (.loadby sos clr) 和 !dumpstack 命令。
  • 旁注:kb 在大多数情况下在 64 位上是无用的,因为调用约定不同。 k 应该够了。
  • @SeanCline:我已经启动了以下两个命令:!ip2md 0x00007ffc'2ea7eae2!ip2md 0x00007ffc'2ea7ee80 这些表示两次相同的结果,并且在相应的源代码中我确实看到了一个函数,调用自身,这很可能是这个问题的根本原因。请将您的评论放在答案中,以便我接受。

标签: .net visual-studio stack-overflow windbg dump


【解决方案1】:

调用堆栈中的裸地址意味着代码不在任何加载的模块中。

这可能有几个原因:

  1. 代码可能是在运行时生成的,JIT 就是这种情况。
  2. 代码可能驻留在已卸载的模块中。
  3. 调用堆栈可能已损坏。

当涉及到 .NET 时,通常是第一个原因——它是 JIT 代码。 使用SOS debugger extension 很容易检查。

首先使用.loadby sos clr加载扩展,然后使用!ip2md 0x00007ff`c2ea802cd检查相关指令指针或返回地址。

如果是 JIT 的 .NET 代码,那么您可能需要熟悉 SOS 扩展提供的 other commands 以调试问题。

正如Lieven Keersmaekers 提到的,您可以使用lm 命令检查卸载的模块(原因#2)并查找卸载的模块。

您可以使用以下方法获取有关内存地址的一些一般信息: !address 0x00007ff`c2ea802cd。 如果页面没有PAGE_EXECUTE 保护或类似的东西,我认为调用堆栈是伪造的(原因#3)。

注意:还有其他 JIT 运行时。它们在虚拟机、脚本语言甚至一些库(如正则表达式引擎)中很常见。这些运行时往往不提供调试器扩展,因此,如果您怀疑正在使用某个运行时,您可能必须为该特定运行时寻找工具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-26
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2021-12-17
    • 1970-01-01
    相关资源
    最近更新 更多