我有一个简单的测试程序导致无限期等待锁定.
public class SyncBlock
{
}
class Program
{
public static SyncBlock sync = new SyncBlock();
private static void ThreadProc()
{
try
{
Monitor.Enter(sync);
}
catch (Exception)
{
//Monitor.Exit(sync);
Console.WriteLine("3rd party code threw an exception");
}
}
static void Main(string[] args)
{
Thread newThread = new Thread(ThreadProc);
newThread.Start();
Console.WriteLine("Acquiring lock");
Monitor.Enter(sync);
Console.WriteLine("Releasing lock");
Monitor.Exit(sync);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,主线程在尝试执行Monitor.Enter(sync)时基本上被锁定.如果我看着!clrStack在主线程上,其输出基本上表现出来,其意义,但是当我尝试看看栈的本机端,我期待看到通话的单/多对象类型的一些等待,但我没有看到它.任何人都可以解释它.谢谢
0:000> !CLRStack
Run Code Online (Sandbox Code Playgroud)
为的Mscorwks.dll PDB符号未加载
OS线程ID:0x1e8(0)
ESP EIP
0012f0a8 77455e74 [GCFrame:0012f0a8]
0012f178 77455e74 [HelperMethodFrame_1OBJ:0012f178] System.Threading.Monitor.Enter(System.Object的)0012f1d0 00a40177 ConsoleApplication1.Program.主(System.String [])
0012f400 70fc1b4c [GCFrame:0012f400]
0:000> kb的
ChildEBP …
如果我有进程转储文件,是否知道转储是在 x64 机器还是 x86 机器上生成的?
在我看到这个问题和答案之前:使用WinDbg将托管字节[]的内容写入文件,但我有一个问题,提到答案是将所有字节写入文件(方法表指针,数组长度和数组内容) ,我想只是写一个数组内容到该文件.
例如,我创建了一个长度为8192的字节数组.
var bytes=new Byte[8192]
Run Code Online (Sandbox Code Playgroud)
并使用windbg并崩溃.
0:034> !do 0x0143fd1c
Name: System.Byte[]
MethodTable: 5ce54944
EEClass: 5cb8af1c
Size: 8204(0x200c) bytes
Array: Rank 1, Number of elements 8192, Type Byte
Element Type:System.Byte
Content: .0.................:.i......$...,x"!.a_.h#......66..vx.4...P.R?...M
Fields:
None
0:034> dd 0x0143fd1c
0143fd1c 5ce54944 00002000 0a0d300a 16460a0d
0143fd2c 957bd993 1f92335c 79a2d058 72455ef6
0143fd3c cc16c7b1 05b18e14 5b1df595 0fb5dbd8
0143fd4c 629a16c6 0edb5c9a 6ede4110 5d5da54e
0143fd5c 4638143a efcad6db 060935f1 a9a48285
0143fd6c e414cff0 8aeaae92 f169b93a f80bd6de
0143fd7c 9a9824d1 22782ccd 5f610c21 0f2368b4
0143fd8c ae09d410 083636c3 0b787616 101ab234
0:034> …
Run Code Online (Sandbox Code Playgroud) 我已将 ADPlus / cdb 设置为计算机上的默认即时调试器。当任何进程出现未处理的异常或因任何其他原因崩溃时,我希望 ADPlus 为我生成故障转储。我使用 ADPlus 配置文件来设置输出目录并运行用于将 dmp 文件推送到云的预命令。
为了进行测试以确保其有效,我编写了一个非常简单的程序,该程序会引发未处理的异常并崩溃。ADPlus 总是像预期的那样附加自身,但它只成功生成我想要的转储,大约为 15 次之一。在不更改系统上的任何内容的情况下,我连续运行崩溃的程序并得到不同的结果。
大多数时候,我从 cdb 收到以下错误:
0:000> g
^ No runnable debuggees error in 'g'
0:000>
*[EOF]*
Run Code Online (Sandbox Code Playgroud)
当它正常工作时,日志中的同一位置如下所示:
0:004> g
FirstChance_epr_Process_Shut_Down
*[More stuff after here]*
Run Code Online (Sandbox Code Playgroud)
知道为什么我会出现这种行为吗?如果有帮助的话,我可以发布我的配置文件和完整日志。何时工作日志和何时不工作日志之间的唯一区别是,所有行均以“何时0:004>
工作”和“0:000>
何时不工作”开头。
在过去的几周里,我一直在玩非托管的.NET调试API.
虽然MSDN记录了接口本身,但为了找到如何以任何有意义的方式实际使用它们,我使用了各种博客(主要是Mike Stall)和CLR Managed Debugger示例中的托管包装器以及ILSpy源代码.最后,我能够将我的测试程序附加到正在运行的进程,设置断点并点击它们.
我接下来要做的就是点击这样一个断点,读取相关对象实例的一个字段.通过禁用加载NGEN的程序集(环境设置'COMPLUS_ZAPDISABLE = 1')并禁用JIT优化(又称'.ini文件技巧' ),当调试目标方法尚未进行NGEN或JIT时,这可以正常工作).
但是,当我尝试使用我理想的目标 - 零售优化(NGEN/JIT'ed)代码时 - 它不起作用.例如:我可以在命中入口断点时仍然检索方法参数的数量,但我无法获得第一个参数本身(调试API抛出异常).
现在,我想这是因为调试API应该是独立于平台的,在这种情况下,程序集不再存在.但是如果我接受这个平台依赖于英特尔的那个怎么办:据我所知CLR使用fastcall调用约定,在这种情况下,ECX寄存器包含第一个方法参数(成员函数的隐式'this'引用) .
我测试了这个,实际上在击中断点时,ECX包含NGEN的组件中的OBJECTREF(对象实例的地址).
现在,读取实例字段的最后一步是检索相对于此指针的字段偏移量,这就是我被卡住的地方,因为我似乎无法找到CLR如何在本机代码生成期间打包实例字段.
我意识到这可能是CLR版本/实现依赖,但显然有方法,因为带有SOS扩展的WinDbg能够找到这种布局.如果没有通过调试API,我能以某种方式利用SOS.dll吗?
我正在关注本教程:链接.在第8步,当我.load sos
在立即窗口中说,它只是呕吐expected expression
.
系统:Win 7 x64,Visual Studio 2012 Premium.我已经安装了适用于Windows的调试工具(x64)11/14/2012,现在我安装了X64调试器和工具.我有适用于Windows 7的Windows SDK(7.1).WinDbg.exe位于c:\ Program Files\Debugging Tools for Windows(x64)\中,我可以从开始菜单启动它.但是我找不到sos.dll,它应该随Windows调试工具(x64)一起提供.
我怎样才能做到这一点?
奖金问题:{,,kernel32}_LoadLibraryExW@12
在第4步不起作用,我使用{,,kernel32}LoadLibraryExW
,但后来我无法弄清楚加载的dll名称在哪里.我正在寻找寄存器.
我有一个转储,它加载了两个.NET版本:
0:000> lm m clr
start end module name
65490000 65aff000 clr (deferred)
0:000> lm m mscorwks
start end module name
6a980000 6af2c000 mscorwks (deferred)
Run Code Online (Sandbox Code Playgroud)
现在我不确定要使用哪个版本的SOS.两者都会毫无问题地加载.
0:000> .loadby sos mscorwks
0:000> .loadby sos clr
Run Code Online (Sandbox Code Playgroud)
我如何找出最适合我的分析的版本?或者我会一直需要两者吗?
在这种情况下,.cordll -ve -u -l是否可靠?
.symfix c:\symbols
.cordll -ve -u -l
CLRDLL: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll:4.0.30319.18047 f:8
doesn't match desired version 4.0.30319.296 f:8
CLRDLL: Loaded DLL c:\symbols\mscordacwks_x86_x86_4.0.30319.296.dll\50484AA966f000\mscordacwks_x86_x86_4.0.30319.296.dll
CLR DLL status: Loaded DLL c:\symbols\mscordacwks_x86_x86_4.0.30319.296.dll\50484AA966f000\mscordacwks_x86_x86_4.0.30319.296.dll
Run Code Online (Sandbox Code Playgroud)
线程0显示mscorwks.使用的命令:
~0s
k
Run Code Online (Sandbox Code Playgroud)
===更新===
.cordll
原则上还可以.默认情况下,它将使用.NET 4框架.可以通过更改此行为.cordll -I
.
我已经获得了两个版本的SOS,它们与目标计算机的版本匹配,并由路径加载
.load C:\SOS\4.0.30319.296\SOS.dll
Run Code Online (Sandbox Code Playgroud)
我已经从WinDbg 6.2升级到最新的6.3.仍然不是更好.
我还问过SOSEX的作者史蒂夫约翰逊, …
我有一个托管进程的一些非常大的内存转储,我试图从中获取大量统计信息,并且能够呈现堆上相当深的对象图的交互式视图。想想!do <address>
与prefer_dml 1
在WinDbg中设置与SOS,在那里你可以不断地点击属性,并查看它们的值,只有在比较多的对象更友好的用户界面。
我发现Microsoft.Diagnostics.Runtime (ClrMD) 特别适合这项任务,但我很难处理数组字段,而且我对对象字段有点困惑,我已经做了一些工作更好的。
数组:如果我直接从堆中定位一个带有地址的数组并使用,ClrType.GetArrayLength
并且ClrType.GetArrayElementValue
一切正常,但是一旦我在另一个对象上挖掘字段,我不确定我从ClrInstanceField.GetValue
什么时候得到的值ClrInstanceField.ElementType
是ClrElementType.SZArray
(我还没有Array
在我的对象图中遇到过挖掘,但我也想处理它)。
编辑:我只是决定使用ClrType
forSystem.UInt64
取消引用数组字段(parent address + offset of the array field
用于计算存储数组指针的地址),然后我可以像从 EnumerateObjects 获取它一样使用它。我现在在某些不支持该ArrayComponentType
属性的数组上遇到了一些困难。我还没有用结构数组进行测试,所以我也想知道这是否是内联结构的 C 风格分配,就像它一样,int[]
或者它是否是指向堆上结构的指针数组。Guid[]
是我在ArrayComponentType
从中获取问题的类型之一。
对象:固定(逻辑错误)
随着ClrInstanceField
具有Type
的ClrElementType.Object
我得到更好的结果,但仍需要更多一点。首先,在调用后GetFieldValue
我得到一个ulong
地址(?),我可以ClrInstanceField.Type.Fields
很好地使用它,所以我可以看到嵌套对象的字段名称和值。也就是说,我必须考虑多态性,所以我尝试ClrHeap.GetObjectType
在同一个地址上使用,它要么返回 NULL,要么返回完全不正确的东西。地址在我的第一个用例中有效,但在第二个用例中无效,这似乎很奇怪。
字符串:已修复(已找到解决方法)
因为我的真实项目已经使用带 SOS 的 DbgEng,我有一种不同的方法可以通过地址轻松获取字符串的值,但是尝试使用ClrInstanceField.GetFieldValue
成功返回字符串似乎很奇怪,但是使用完全不准确的结果(一堆奇怪的字符)。也许我做错了? …
我刚刚开始使用windbg/sos,我创建了一个简单的控制台应用程序进行测试(抛出未处理的异常).似乎在我加载sos后,我将在下次调用时获得异常.
例如:
ntsd consoleapplication1.exe
.symfix
.reload
g
.loadby sos clr
Run Code Online (Sandbox Code Playgroud)
如果我打电话:
!threads
"c0000005 Exception in C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.threads
PC: 592b7713 VA: 00000000 R/W: 0 Parameter: 00000000"
Run Code Online (Sandbox Code Playgroud)
如果我打电话:
!ClrStack
c0000005 Exception in C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.ClrStack
PC: 592b7713 VA: 00000000 R/W: 0 Parameter: 00000000
Run Code Online (Sandbox Code Playgroud)
第一次通话后的每次通话都会有效(这只是加载SOS后第一次通话失败).
我尝试了这个建议并重新编译了我的代码,启用了本机代码调试,但它没有什么区别.
windbg的版本:6.3.9600.16384 X86
我在托管堆中存在数百个MyClass实例。其中一些位于大对象堆中。下面是各种堆结构的样子
0:000> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000000002df9de8
generation 1 starts at 0x0000000002dc6710
generation 2 starts at 0x0000000002a01000
ephemeral segment allocation context: none
segment begin allocated size
0000000002a00000 0000000002a01000 0000000002e3c2c0 0x43b2c0(4436672)
Large object heap starts at 0x0000000012a01000
segment begin allocated size
0000000012a00000 0000000012a01000 000000001a5ed558 0x7bec558(129942872)
000000002a980000 000000002a981000 00000000328110b8 0x7e900b8(132710584)
0000000033e00000 0000000033e01000 000000003bd80d78 0x7f7fd78(133692792)
000000001daf0000 000000001daf1000 0000000025996188 0x7ea5188(132796808)
00000000542b0000 00000000542b1000 000000005a4bf100 0x620e100(102818048)
000000005c2b0000 000000005c2b1000 000000006344df88 0x719cf88(119132040)
000000007fff0000 000000007fff1000 00000000878bfbc0 0x78cebc0(126675904)
Total Size: Size: …
Run Code Online (Sandbox Code Playgroud)