Question

Browsing some forum I came across this answer in which the answerer refers to the following as the native call stack

00000000`0014ea10 00000642`7f67d4a2 0x642`80150142
00000000`0014ea90 00000642`7f5108f5 mscorwks!CallDescrWorker+0x82 
00000000`0014eae0 00000642`7f522ff6 mscorwks!CallDescrWorkerWithHandler+0xe5
00000000`0014eb80 00000642`7f49a94b mscorwks!MethodDesc::CallDescr+0x306 
00000000`0014edb0 00000642`7f474ae4 mscorwks!ClassLoader::RunMain+0x23f
00000000`0014f010 00000642`7f5efb1a mscorwks!Assembly::ExecuteMainMethod+0xbc 
00000000`0014f300 00000642`7f467d97 mscorwks!SystemDomain::ExecuteMainMethod+0x492
00000000`0014f8d0 00000642`7f482c24 mscorwks!ExecuteEXE+0x47

What exactly is the native call stack with regards to the CLR (here we are looking at the CLR invoking the Main method I think) and how can I view and come to understand said native call stack on my local machine for educational purposes?

Was it helpful?

Solution

Yes, these are unmanaged functions written in C++. The language that was used to write the CLR.

There is no fundamental distinction in the way unmanaged code uses the stack compared to the way managed code uses it. The only difference is that you need an unmanaged debugger to actually see the unmanaged functions in the stack trace. A managed debugger just reports a [Managed to Native Transition] in the stack trace and hides the unmanaged functions.

Which is productive, you are not normally interested in unmanaged code at all and may well be missing the required PDBs to make the trace accurate. Which, for the CLR, requires enabling the Microsoft Symbol Server. Managed stack traces are always accurate, the CLR gives hard guarantees that stack walks can work well since the garbage collector and CAS need to perform stack walks to get their job done. Unmanaged stack traces are more difficult due to optimizations in the C++ code generator, the frame pointer omission optimization is quite deadly to stack walking for example.

You can certainly see both. Project + Properties, Debug tab, tick the "Enable native code debugging" option.

OTHER TIPS

"Native call stack" means a (part of) a call stack that goes trough unmanaged libraries. You always have some unmanaged entry point to a managed stack, since the operating system is not managed. But you can also have unmanaged methods on top of it, i.e. if your managed code calls into system functions. A call stack can contain any number of managed-to-native and native-to-managed transitions. To see something reasonable at all, "unmanaged debugging" should be turned on.

In your example above, you see calls originating in mscorwks.dll, which is the main dll that contains the .NET execution engine. Since symbols for that library are missing (unless you've downloaded them - see google on "Microsoft symbol server") you're only seing the entry points of the different functions. A line as mscorwks!CallDescrWorkerWithHandler+0xe5 means that the call originated from a function called "CallDescrWorkerWithHandler" in mscorwks.dll, 0xe5 bytes from the start of that function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top