Tar*_*aro 8 windows mixed-mode memory-leaks stack-trace
像大多数人一样,你可能知道存在很多不同的机制来从堆栈跟踪开始,从windows api开始,并继续深入神奇的汇编世界 - 让我列举一些我已经研究过的链接.
总之,让我提一下,我想要有混合模式(托管和非托管)/ 64位+ AnyCPU应用程序的内存泄漏分析机制,并且从所有windows api的CaptureStackBackTrace最适合我的需求,但正如我所分析的 - 它不支持托管代码堆栈行走.但是该函数API最接近我所需要的(因为它还计算回跟踪散列 - 特定调用堆栈的唯一标识符).
我已经排除了查找内存泄漏的不同方法 - 我尝试过的大多数软件要么崩溃要么不能正常工作,要么产生不好的结果.
此外,我不想重新编译现有的软件并覆盖malloc/new其他机制 - 因为它是一项繁重的任务(我们拥有大量代码库和大量的dll).此外,我怀疑这不是我需要执行的一次性工作 - 问题以1 - 2年周期回归,具体取决于谁和编码,所以我更希望在应用程序本身内置内存泄漏检测(内存) api挂钩)而不是一遍又一遍地解决这个问题.
http://www.codeproject.com/Articles/11132/Walking-the-callstack
使用StackWalk64 Windows API函数,但不能与托管代码一起使用.此外64位支持还不完全清楚 - 我已经看到64位问题的一些解决方法 - 我怀疑当在同一线程内完成堆栈遍历时,此代码不能完全正常工作.
然后存在进程黑客:http: //processhacker.sourceforge.net/
其中也使用StackWalk64,但扩展了它的回调函数(第7和第8个参数)以支持混合模式堆栈行走.在使用7/8回调函数进行了大量复杂操作之后,我还成功地获得了支持混合模式支持的StackWalk64(将堆栈跟踪作为向量捕获 - 其中每个指针指向调用过去的汇编/ dll位置).但正如您可能猜到的那样 - StackWalk64的性能不足以满足我的需求 - 即使使用C#端的简单消息框,应用程序只需"挂起"一段时间直到它正确启动.
我没有看到CaptureStackBackTrace函数调用的这么大的延迟,所以我认为StackWalk64的性能不足以满足我的需求.
还存在基于COM的堆栈跟踪确定方法 - 如下所示:http: //www.codeproject.com/Articles/371137/A-Mixed-Mode-Stackwalk-with-the-IDebugClient-Inter
http://blog.steveniemitz.com/building-a-mixed-mode-stack-walker-part-1/
但是我害怕 - 它需要COM,并且线程需要进行初始化,并且由于内存api挂钩我不应该触摸任何线程中的com状态,因为它可能导致更严重的问题(例如,不正确的公寓初始化,其他毛刺)
现在我已经达到了Windows API不能满足我自己需求的程度,我需要手动遍历调用堆栈.例如,可以找到这样的例子:
http://www.codeproject.com/Articles/11221/Easy-Detection-of-Memory-Leaks 请参阅函数FillStackInfo/32位,不支持托管代码.
有几个关于反转堆栈跟踪的提及 - 例如在以下链接上:
特别是1,3,4个链接提供了一些有趣的夜间阅读.:-)
但即便如此,它们也是相当有趣的机制,其中任何一个都没有完全可用的演示示例.
我想其中一个例子是Wine的dbghelp实现(用于linux的Windows"模拟器"),它也显示了StackWalk64最终的工作原理,但我怀疑它与DWARF2文件格式的可执行文件有很大关系,因此它与当前的Windows PE不完全相同可执行文件格式.
有人可以指点我很好地实现堆栈行走,在64位架构上工作,支持混合模式(可以跟踪本机和托管内存分配),这完全是在寄存器/调用堆栈/代码分析中绑定的.(1,3,4的组合实施)
有人与Microsoft开发团队有任何良好的联系,他们可能会回答这个问题吗?
9-1-2015 - 我找到了被进程黑客调用的原始函数,那个函数是
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll OutOfProcessFunctionTableCallback
它的源代码 - 在这里: https: //github.com/dotnet/coreclr/blob/master/src/debug/daccess/fntableaccess.cpp
从那里,我拥有了该源代码中大部分更改的所有者 - Jan Kotas (jkotas@microsoft.com),并就这个问题与他联系。
From: Jan Kotas <jkotas@microsoft.com>
To: Tarmo Pikaro <tapika@yahoo.com>
Sent: Friday, January 8, 2016 3:27 PM
Subject: RE: Fast capture stack trace on windows 64 bit / mixed mode...
...
The mscordacwks.dll is called mscordaccore.dll in CoreCLR / github repro. The VS project
files are auto-generated for it during the build
(\coreclr\bin\obj\Windows_NT.x64.Debug\src\dlls\mscordac\mscordaccore.vcxproj).
You should be able to build and debug CoreCLR to understand how it works.
...
From: Jan Kotas <jkotas@microsoft.com>
To: Tarmo Pikaro <tapika@yahoo.com>
Sent: Saturday, January 9, 2016 2:02 AM
Subject: RE: Fast capture stack trace on windows 64 bit / mixed mode...
> I've tried to replace
> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll dll loading
> with C:\Prototyping\dotNet\coreclr-master\bin\obj\Windows_NT.x64.Debug\src\dlls\mscordac\Debug\mscordaccore.dll
> loading (just compiled), but if previously I could get mixed mode stack trace correctly:
> ...
mscordacwks.dll is tightly coupled with the runtime. You cannot mix and match them between runtimes.
What I meant is that you can use CoreCLR to understand how this works.
Run Code Online (Sandbox Code Playgroud)
但后来他推荐了这个对我有用的解决方案:
int CaptureStackBackTrace3(int FramesToSkip, int nFrames, PVOID* BackTrace, PDWORD pBackTraceHash)
{
CONTEXT ContextRecord;
RtlCaptureContext(&ContextRecord);
UINT iFrame;
for (iFrame = 0; iFrame < nFrames; iFrame++)
{
DWORD64 ImageBase;
PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry(ContextRecord.Rip, &ImageBase, NULL);
if (pFunctionEntry == NULL)
break;
PVOID HandlerData;
DWORD64 EstablisherFrame;
RtlVirtualUnwind(UNW_FLAG_NHANDLER,
ImageBase,
ContextRecord.Rip,
pFunctionEntry,
&ContextRecord,
&HandlerData,
&EstablisherFrame,
NULL);
BackTrace[iFrame] = (PVOID)ContextRecord.Rip;
}
return iFrame;
}
Run Code Online (Sandbox Code Playgroud)
此代码片段仍然缺少回溯哈希计算,但这是可以在之后添加的内容。
还需要注意的是,在调试此代码片段时,您应该使用本机调试,而不是混合模式(C# 项目默认使用混合模式),因为它会以某种方式干扰调试器中的堆栈跟踪。(弄清楚这种扭曲是如何以及为何发生的)
仍然缺少一个难题 - 如何使符号解析完全抵抗 FreeLibrary / Jit 代码处理,但这仍然是我需要弄清楚的事情。
请注意,RtlVirtualUnwind 很可能仅适用于 64 位架构,不适用于 ARM 或 32 位架构。
更有趣的是,存在函数 RtlCaptureStackBackTrace ,它在某种程度上类似于 Windows api 函数 CaptureStackBackTrace - 但它们在某种程度上有所不同 - 至少在命名上。另外,如果您检查 RtlCaptureStackBackTrace - 它最终调用 RtlVirtualUnwind - 您可以从 Windows Research Kernel 源代码中检查它
RtlCaptureStackBackTrace
>
RtlWalkFrameChain
>
RtlpWalkFrameChain
>
RtlVirtualUnwind
Run Code Online (Sandbox Code Playgroud)
但我测试过的 RtlCaptureStackBackTrace 无法正常工作。与上面的 RtlVirtualUnwind 函数不同。
这有点神奇。:-)
我将继续此调查问卷的第二阶段问题 - 在这里:
归档时间: |
|
查看次数: |
2206 次 |
最近记录: |