In this blog post,we are going to look inside of a .NET Core process using windbg. .NET CORE process footprint is as minimal as possible so with this blog post,we are going to look at a simple .net core concole app running (simplest console app with bare minimum managed code) and check
- How many .NET Objects it needs to run a console application
- .NET dlls (managed) are loaded for a simple console application
- What are the threads running (managed and unmanaged or native)
- How does the callstack look like for .NET threads
- How to look for a particular .NET object and dump it details
First lets start a simple .NET core console application .I already have the .NET core SDK installed .Now create a simple console app and run
D:PROJECTSdotnet>dotnet new console
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on D:PROJECTSdotnetdotnet.csproj...
Restoring packages for D:PROJECTSdotnetdotnet.csproj...
Generating MSBuild file D:PROJECTSdotnetobjdotnet.csproj.nuget.g.props.
Generating MSBuild file D:PROJECTSdotnetobjdotnet.csproj.nuget.g.targets.
Restore completed in 704.29 ms for D:PROJECTSdotnetdotnet.csproj.
Restore succeeded.
After this ,We can do a build and run
D:PROJECTSdotnet>dotnet build
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 57.84 ms for D:PROJECTSdotnetdotnet.csproj.
dotnet -> D:PROJECTSdotnetbinDebugnetcoreapp2.0dotnet.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:06.06
Finally running the app
D:PROJECTSdotnet>dotnet run
Hello World!
We are going to use a windbg tool to do this,you can install debugging tools for windows to get windbg .If you are doing a fresh installation, Make sure to install As a standalone tool set
If you want to download only Debugging Tools for Windows, install the Windows SDK, and, during the installation, select the Debugging Tools for Windows box and clear all the other boxes.
Once you have installed debugging tools,run windbg(make sure to run 64 bit version ). To inspect the dotnet process,we will make a small change to the code to add a Console.ReadLine(). This is done to make sure the process does not terminate as soon as it finishes
using System;
namespace dotnet
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
}
}
}
- Run the console app using dotnet run command
- When it successfully runs,it will launch console app and will not exit because of the Console.ReadLine() we added
- Now,launch windg and attach to dotnet.exe process as shown below
make sure to launch windbg with the correct bitness(32 bit or 64 bit) .You have to match the bitness of the process you are going to debug with the windbg
Now from the windbg menu,choose Attach to a Process( press F6) and find dotnet.exe running.![]()
Once you have attached,you should see following
Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
*** wait with pending attach
Symbol search path is: srv*c:symcache*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00000001`3fdc0000 00000001`3fde7000 C:Program Filesdotnetdotnet.exe
ModLoad: 00000000`76e80000 00000000`7702a000 C:windowsSYSTEM32ntdll.dll
ModLoad: 00000000`76c60000 00000000`76d7f000 C:windowssystem32kernel32.dll
ModLoad: 000007fe`fcbf0000 000007fe`fcc5a000 C:windowssystem32KERNELBASE.dll
ModLoad: 00000000`74860000 00000000`748ee000 C:windowsSystem32SYSFER.DLL
ModLoad: 000007fe`fdb20000 000007fe`fdbfb000 C:windowssystem32ADVAPI32.dll
ModLoad: 000007fe`fea80000 000007fe`feb1f000 C:windowssystem32msvcrt.dll
ModLoad: 000007fe`fd310000 000007fe`fd32f000 C:windowsSYSTEM32sechost.dll
ModLoad: 000007fe`feff0000 000007fe`ff11d000 C:windowssystem32RPCRT4.dll
ModLoad: 000007fe`f5430000 000007fe`f5434000 C:windowssystem32api-ms-win-crt-runtime-l1-1-0.dll
ModLoad: 000007fe`dee30000 000007fe`def24000 C:windowssystem32ucrtbase.DLL
ModLoad: 000007fe`f5420000 000007fe`f5423000 C:windowssystem32api-ms-win-core-timezone-l1-1-0.dll
ModLoad: 000007fe`f4410000 000007fe`f4413000 C:windowssystem32api-ms-win-core-file-l2-1-0.dll
ModLoad: 000007fe`f4400000 000007fe`f4403000 C:windowssystem32api-ms-win-core-localization-l1-2-0.dll
ModLoad: 000007fe`fba40000 000007fe`fba43000 C:windowssystem32api-ms-win-core-synch-l1-2-0.dll
ModLoad: 000007fe`f4360000 000007fe`f4363000 C:windowssystem32api-ms-win-core-processthreads-l1-1-1.dll
ModLoad: 000007fe`f4350000 000007fe`f4353000 C:windowssystem32api-ms-win-core-file-l1-2-0.dll
ModLoad: 000007fe`ea900000 000007fe`ea905000 C:windowssystem32api-ms-win-crt-math-l1-1-0.dll
ModLoad: 000007fe`f4100000 000007fe`f4103000 C:windowssystem32api-ms-win-crt-heap-l1-1-0.dll
ModLoad: 000007fe`ee870000 000007fe`ee874000 C:windowssystem32api-ms-win-crt-convert-l1-1-0.dll
ModLoad: 000007fe`f40f0000 000007fe`f40f4000 C:windowssystem32api-ms-win-crt-stdio-l1-1-0.dll
ModLoad: 000007fe`f42f0000 000007fe`f42f4000 C:windowssystem32api-ms-win-crt-string-l1-1-0.dll
ModLoad: 000007fe`ee620000 000007fe`ee623000 C:windowssystem32api-ms-win-crt-locale-l1-1-0.dll
ModLoad: 000007fe`ea8f0000 000007fe`ea8f5000 C:windowssystem32api-ms-win-crt-multibyte-l1-1-0.dll
ModLoad: 000007fe`d6b00000 000007fe`d6b51000 C:Program Filesdotnethostfxr2.0.5hostfxr.dll
ModLoad: 000007fe`e77e0000 000007fe`e77e3000 C:windowssystem32api-ms-win-crt-filesystem-l1-1-0.dll
ModLoad: 000007fe`d6a70000 000007fe`d6af9000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5hostpolicy.dll
ModLoad: 000007fe`d1070000 000007fe`d15ba000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5coreclr.dll
ModLoad: 000007fe`fd640000 000007fe`fd83c000 C:windowssystem32ole32.dll
ModLoad: 000007fe`ff120000 000007fe`ff187000 C:windowssystem32GDI32.dll
ModLoad: 00000000`76d80000 00000000`76e7a000 C:windowssystem32USER32.dll
ModLoad: 000007fe`fd3d0000 000007fe`fd3de000 C:windowssystem32LPK.dll
ModLoad: 000007fe`fd3e0000 000007fe`fd4ab000 C:windowssystem32USP10.dll
ModLoad: 000007fe`fe990000 000007fe`fea6a000 C:windowssystem32OLEAUT32.dll
ModLoad: 000007fe`fbc20000 000007fe`fbc2c000 C:windowssystem32VERSION.dll
ModLoad: 000007fe`fd290000 000007fe`fd301000 C:windowssystem32SHLWAPI.dll
ModLoad: 000007fe`fc4b0000 000007fe`fc4d2000 C:windowssystem32bcrypt.dll
ModLoad: 000007fe`de290000 000007fe`de293000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5api-ms-win-crt-utility-l1-1-0.dll
ModLoad: 000007fe`ddb80000 000007fe`ddb83000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5api-ms-win-crt-time-l1-1-0.dll
ModLoad: 000007fe`fd260000 000007fe`fd28e000 C:windowssystem32IMM32.DLL
ModLoad: 000007fe`fd4b0000 000007fe`fd5b9000 C:windowssystem32MSCTF.dll
ModLoad: 000007fe`c5330000 000007fe`c5e84000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Private.CoreLib.dll
ModLoad: 000007fe`f3ae0000 000007fe`f3b4f000 C:windowsSYSTEM32MSCOREE.DLL
ModLoad: 00000000`00300000 00000000`00308000 D:PROJECTSdotnetbinDebugnetcoreapp2.0dotnet.dll
ModLoad: 000007fe`ddb70000 000007fe`ddb7d000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Runtime.dll
ModLoad: 000007fe`d1bb0000 000007fe`d1cbb000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5clrjit.dll
ModLoad: 000007fe`d0e60000 000007fe`d0e87000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Console.dll
ModLoad: 000007fe`dc4e0000 000007fe`dc4f3000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Threading.dll
ModLoad: 000007fe`d1cc0000 000007fe`d1d34000 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Runtime.Extensions.dll
(6018.7540): Break instruction exception - code 80000003 (first chance)
This means that windbg is successfully attached to our dotnet core process.
Now we can run some commands in windbg to get some internal details about
Getting the active threads running
For this run a simple command ~ in windbg
0:000> ~
. 0 Id: 6018.1244 Suspend: 1 Teb: 000007ff`fffde000 Unfrozen
1 Id: 6018.67e8 Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
2 Id: 6018.550 Suspend: 1 Teb: 000007ff`fffda000 Unfrozen
# 3 Id: 6018.7540 Suspend: 1 Teb: 000007ff`fffd8000 Unfrozen
tilde(~) simply lists all the threads running with the threadid.There are many variations you can do
- ~* - shows little more information like the top method currently executing .* means all the threads
- ~*k - shows all the threads along with the stack
- ~<threadnum>s - will switch to thread number threadnum you specifiy
0:001> ~*k
0 Id: 6018.1244 Suspend: 1 Teb: 000007ff`fffde000 Unfrozen
Child-SP RetAddr Call Site
00000000`001adc48 00000000`76c818e8 ntdll!NtRequestWaitReplyPort+0xa
00000000`001adc50 00000000`76cb57f1 kernel32!ConsoleClientCallServer+0x54
00000000`001adc80 00000000`76cca9f2 kernel32!ReadConsoleInternal+0x1f1
00000000`001addd0 00000000`76c97e64 kernel32!ReadConsoleA+0xb2
00000000`001adeb0 000007fe`716d147f kernel32!TlsGetValue+0x81fe
00000000`001adef0 000007fe`d0e78f65 0x7fe`716d147f
00000000`001adfb0 000007fe`d0e78db3 System_Console+0x18f65
00000000`001ae010 000007fe`d1d0dc6d System_Console+0x18db3
00000000`001ae080 000007fe`d1d0e04a System_Runtime_Extensions+0x4dc6d
00000000`001ae0d0 000007fe`d0e7d517 System_Runtime_Extensions+0x4e04a
00000000`001ae120 000007fe`d0e752fa System_Console+0x1d517
00000000`001ae170 000007fe`716d04b6 System_Console+0x152fa
00000000`001ae1a0 000007fe`d11a35d3 0x7fe`716d04b6
00000000`001ae1e0 000007fe`d10cd9bf coreclr!CallDescrWorkerInternal+0x83 [E:A_work1791ssrcvmamd64CallDescrWorkerAMD64.asm @ 101]
00000000`001ae220 000007fe`d1193ef7 coreclr!MethodDescCallSite::CallTargetWorker+0x17b [e:a_work1791ssrcvmcallhelpers.cpp @ 653]
00000000`001ae370 000007fe`d108b195 coreclr!RunMain+0x17f [e:a_work1791ssrcvmassembly.cpp @ 1849]
00000000`001ae5d0 000007fe`d112ba29 coreclr!Assembly::ExecuteMainMethod+0xb5 [e:a_work1791ssrcvmassembly.cpp @ 1944]
00000000`001ae890 000007fe`d112d9ce coreclr!CorHost2::ExecuteAssembly+0x149 [e:a_work1791ssrcvmcorhost.cpp @ 502]
00000000`001ae960 000007fe`d6a8e8b9 coreclr!coreclr_execute_assembly+0xde [e:a_work1791ssrcdllsmscoreeunixinterface.cpp @ 407]
00000000`001ae9f0 000007fe`d6a8ee44 hostpolicy!run+0xdb9
00000000`001af0c0 000007fe`d6b19b05 hostpolicy!corehost_main+0x164
00000000`001af240 000007fe`d6b1f42b hostfxr!execute_app+0x1f5
00000000`001af310 000007fe`d6b1e819 hostfxr!fx_muxer_t::read_config_and_execute+0x94b
00000000`001af9b0 000007fe`d6b1cc8d hostfxr!fx_muxer_t::parse_args_and_execute+0x409
00000000`001afb40 00000001`3fdc9abc hostfxr!fx_muxer_t::execute+0x22d
00000000`001afcd0 00000001`3fdce099 dotnet!wmain+0x46c
00000000`001afde0 00000000`76c759cd dotnet!__scrt_common_main_seh+0x11d [f:ddvctoolscrtvcstartupsrcstartupexe_common.inl @ 253]
00000000`001afe20 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`001afe50 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
1 Id: 6018.67e8 Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
Child-SP RetAddr Call Site
00000000`0232f648 000007fe`fcbf1430 ntdll!ZwWaitForMultipleObjects+0xa
00000000`0232f650 00000000`76c816e3 KERNELBASE!WaitForMultipleObjectsEx+0xe8
00000000`0232f750 000007fe`d118b36a kernel32!WaitForMultipleObjectsExImplementation+0xb3
00000000`0232f7e0 000007fe`d118b44e coreclr!DebuggerRCThread::MainLoop+0xce [e:a_work1791ssrcdebugeercthread.cpp @ 1241]
00000000`0232f8a0 000007fe`d118ae8a coreclr!DebuggerRCThread::ThreadProc+0xd2 [e:a_work1791ssrcdebugeercthread.cpp @ 1042]
00000000`0232f8f0 00000000`76c759cd coreclr!DebuggerRCThread::ThreadProcStatic+0x1a [e:a_work1791ssrcdebugeercthread.cpp @ 1642]
00000000`0232f920 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`0232f950 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
2 Id: 6018.550 Suspend: 1 Teb: 000007ff`fffda000 Unfrozen
Child-SP RetAddr Call Site
00000000`1a94f5f8 000007fe`fcbf1430 ntdll!ZwWaitForMultipleObjects+0xa
00000000`1a94f600 00000000`76c816e3 KERNELBASE!WaitForMultipleObjectsEx+0xe8
00000000`1a94f700 000007fe`d1176361 kernel32!WaitForMultipleObjectsExImplementation+0xb3
00000000`1a94f790 000007fe`d1175de2 coreclr!FinalizerThread::WaitForFinalizerEvent+0x85 [e:a_work1791ssrcvmfinalizerthread.cpp @ 469]
00000000`1a94f7d0 000007fe`d10cd66b coreclr!FinalizerThread::FinalizerThreadWorker+0x62 [e:a_work1791ssrcvmfinalizerthread.cpp @ 587]
00000000`1a94f830 000007fe`d10cd586 coreclr!ManagedThreadBase_DispatchInner+0x43 [e:a_work1791ssrcvmthreads.cpp @ 9204]
00000000`1a94f870 000007fe`d10cd498 coreclr!ManagedThreadBase_DispatchMiddle+0x82 [e:a_work1791ssrcvmthreads.cpp @ 9253]
00000000`1a94f9d0 000007fe`d117587c coreclr!ManagedThreadBase_DispatchOuter+0xb4 [e:a_work1791ssrcvmthreads.cpp @ 9492]
00000000`1a94fa80 000007fe`d11773fb coreclr!FinalizerThread::FinalizerThreadStart+0x9c [e:a_work1791ssrcvmfinalizerthread.cpp @ 774]
00000000`1a94fb20 00000000`76c759cd coreclr!Thread::intermediateThreadProc+0x8b [e:a_work1791ssrcvmthreads.cpp @ 2594]
00000000`1a94fbe0 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`1a94fc10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
# 3 Id: 6018.7540 Suspend: 1 Teb: 000007ff`fffd8000 Unfrozen
Child-SP RetAddr Call Site
00000000`1ac7fc28 00000000`76f72e08 ntdll!DbgBreakPoint
00000000`1ac7fc30 00000000`76c759cd ntdll!DbgUiRemoteBreakin+0x38
00000000`1ac7fc60 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`1ac7fc90 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
We see 4 threads running in idle state and callstacks of the threads.But these windbg commands only shows native stacks and does not show managed threads or stacks.To make windbg understand about CLR and managed threads, we have to windbg debugging extension dlls .In this case we are going to use a dll called SOS
We have SOS.dll for every version and bitness of .NET framework (.NET 1.1,2.0,4.0 etc) .So for .NET core process debugging we need to use .NET Core's sos.dll . And the good part is that sos.dll is shipped with the dotnet and you will find it on
64bit: C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5sos.dll
32bit: C:Program Files (x86)dotnetsharedMicrosoft.NETCore.App2.0.5sos.dll
Now to load any extension to windbg,we have to use .load command
.load C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5sos
You can also use alternate command .loadby
0:001> .loadby sos coreclr
What this does is it will automatically find the sos path and load from the already existing dll coreclr which is loaded into the dotnet.exe process. Once it is loaded,you can get all the commands using help
0:001> !help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function.
Object Inspection Examining code and stacks
----------------------------- -----------------------------
DumpObj (do) Threads
DumpArray (da) ThreadState
DumpStackObjects (dso) IP2MD
DumpHeap U
DumpVC DumpStack
GCRoot EEStack
ObjSize CLRStack
FinalizeQueue GCInfo
PrintException (pe) EHInfo
TraverseHeap BPMD
COMState
Examining CLR data structures Diagnostic Utilities
----------------------------- -----------------------------
DumpDomain VerifyHeap
EEHeap VerifyObj
Name2EE FindRoots
SyncBlk HeapStat
DumpMT GCWhere
DumpClass ListNearObj (lno)
DumpMD GCHandles
Token2EE GCHandleLeaks
EEVersion FinalizeQueue (fq)
DumpModule FindAppDomain
ThreadPool SaveModule
DumpAssembly ProcInfo
DumpSigElem StopOnException (soe)
DumpRuntimeTypes DumpLog
DumpSig VMMap
RCWCleanupList VMStat
DumpIL MinidumpMode
DumpRCW AnalyzeOOM (ao)
DumpCCW
Examining the GC history Other
----------------------------- -----------------------------
HistInit FAQ
HistRoot
HistObj
HistObjFind
HistClear
don't worry about all these commands ,we are going to use a handful of them .mainly !threads !CLRStack and !dumpheap .
Please note that all extension commands will start with ! .So all commands inside sos.dll we have to use !threads ,!clrstack etc.
Getting managed threads and stacks
0:001> !threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 1244 00000000005cb900 20020 Preemptive 0000000002355278:00000000023561C0 0000000000433400 1 Ukn
2 2 550 00000000005f1fb0 21220 Preemptive 0000000000000000:0000000000000000 0000000000433400 0 Ukn (Finalizer)
Once you see manageed thread,you can switch to that thread by ~<threadnumber>s
to switch to first thread ~ss
0:001> ~0s
ntdll!NtRequestWaitReplyPort+0xa:
00000000`76ecbf5a c3 ret
0:000> !clrstack
OS Thread Id: 0x1244 (0)
Child SP IP Call Site
00000000001adf20 0000000076ecbf5a [InlinedCallFrame: 00000000001adf20] Interop+Kernel32.ReadFile(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000000001adf20 000007fe716d147f [InlinedCallFrame: 00000000001adf20] Interop+Kernel32.ReadFile(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000000001adef0 000007fe716d147f DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000000001adfb0 000007fed0e78f65 System.ConsolePal+WindowsConsoleStream.ReadFileNative(IntPtr, Byte[], Int32, Int32, Boolean, Int32 ByRef, Boolean) [E:A_work1439scorefxsrcSystem.ConsolesrcSystemConsolePal.Windows.cs @ 1170]
00000000001ae010 000007fed0e78db3 System.ConsolePal+WindowsConsoleStream.Read(Byte[], Int32, Int32) [E:A_work1439scorefxsrcSystem.ConsolesrcSystemConsolePal.Windows.cs @ 1121]
00000000001ae080 000007fed1d0dc6d System.IO.StreamReader.ReadBuffer() [E:A_work1439scorefxsrcSystem.Runtime.ExtensionssrcSystemIOStreamReader.cs @ 627]
00000000001ae0d0 000007fed1d0e04a System.IO.StreamReader.ReadLine() [E:A_work1439scorefxsrcSystem.Runtime.ExtensionssrcSystemIOStreamReader.cs @ 802]
00000000001ae120 000007fed0e7d517 System.IO.SyncTextReader.ReadLine() [E:A_work1439scorefxsrcSystem.ConsolesrcSystemIOSyncTextReader.cs @ 78]
00000000001ae170 000007fed0e752fa System.Console.ReadLine() [E:A_work1439scorefxsrcSystem.ConsolesrcSystemConsole.cs @ 474]
00000000001ae1a0 000007fe716d04b6 dotnet.Program.Main(System.String[]) [D:PROJECTSdotnetProgram.cs @ 10]
00000000001ae418 000007fed11a35d3 [GCFrame: 00000000001ae418]
00000000001ae8f8 000007fed11a35d3 [GCFrame: 00000000001ae8f8]
Now We can check how the native stack will look like by running k
0:000> k
Child-SP RetAddr Call Site
00000000`001adc48 00000000`76c818e8 ntdll!NtRequestWaitReplyPort+0xa
00000000`001adc50 00000000`76cb57f1 kernel32!ConsoleClientCallServer+0x54
00000000`001adc80 00000000`76cca9f2 kernel32!ReadConsoleInternal+0x1f1
00000000`001addd0 00000000`76c97e64 kernel32!ReadConsoleA+0xb2
00000000`001adeb0 000007fe`716d147f kernel32!TlsGetValue+0x81fe
00000000`001adef0 000007fe`d0e78f65 0x7fe`716d147f
00000000`001adfb0 000007fe`d0e78db3 System_Console+0x18f65
00000000`001ae010 000007fe`d1d0dc6d System_Console+0x18db3
00000000`001ae080 000007fe`d1d0e04a System_Runtime_Extensions+0x4dc6d
00000000`001ae0d0 000007fe`d0e7d517 System_Runtime_Extensions+0x4e04a
00000000`001ae120 000007fe`d0e752fa System_Console+0x1d517
00000000`001ae170 000007fe`716d04b6 System_Console+0x152fa
00000000`001ae1a0 000007fe`d11a35d3 0x7fe`716d04b6
00000000`001ae1e0 000007fe`d10cd9bf coreclr!CallDescrWorkerInternal+0x83 [E:A_work1791ssrcvmamd64CallDescrWorkerAMD64.asm @ 101]
00000000`001ae220 000007fe`d1193ef7 coreclr!MethodDescCallSite::CallTargetWorker+0x17b [e:a_work1791ssrcvmcallhelpers.cpp @ 653]
00000000`001ae370 000007fe`d108b195 coreclr!RunMain+0x17f [e:a_work1791ssrcvmassembly.cpp @ 1849]
00000000`001ae5d0 000007fe`d112ba29 coreclr!Assembly::ExecuteMainMethod+0xb5 [e:a_work1791ssrcvmassembly.cpp @ 1944]
00000000`001ae890 000007fe`d112d9ce coreclr!CorHost2::ExecuteAssembly+0x149 [e:a_work1791ssrcvmcorhost.cpp @ 502]
00000000`001ae960 000007fe`d6a8e8b9 coreclr!coreclr_execute_assembly+0xde [e:a_work1791ssrcdllsmscoreeunixinterface.cpp @ 407]
00000000`001ae9f0 000007fe`d6a8ee44 hostpolicy!run+0xdb9
00000000`001af0c0 000007fe`d6b19b05 hostpolicy!corehost_main+0x164
00000000`001af240 000007fe`d6b1f42b hostfxr!execute_app+0x1f5
00000000`001af310 000007fe`d6b1e819 hostfxr!fx_muxer_t::read_config_and_execute+0x94b
00000000`001af9b0 000007fe`d6b1cc8d hostfxr!fx_muxer_t::parse_args_and_execute+0x409
00000000`001afb40 00000001`3fdc9abc hostfxr!fx_muxer_t::execute+0x22d
00000000`001afcd0 00000001`3fdce099 dotnet!wmain+0x46c
00000000`001afde0 00000000`76c759cd dotnet!__scrt_common_main_seh+0x11d [f:ddvctoolscrtvcstartupsrcstartupexe_common.inl @ 253]
00000000`001afe20 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`001afe50 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
As you see the managed stack and native stack look different this is because CLR abstracts away many details from the actual machine level execution.
hostfxr!execute_app method executes your .NET code. Once it loads coreclr ,everything happens is on .NET terms . coreclr loads the .NET dlls and all the reference dlls and execute your code
As you see there are two managed threads running (from the output of !threads command),lets see what the other thread is doing
0:000> ~2s
ntdll!ZwWaitForMultipleObjects+0xa:
00000000`76ecc2ea c3 ret
0:002> !clrstack
OS Thread Id: 0x550 (2)
Child SP IP Call Site
000000001a94fa00 0000000076ecc2ea [DebuggerU2MCatchHandlerFrame: 000000001a94fa00]
We really do not see any manage callstack although it is managed thread.So let's see what it actually is by looking at the native callstack
0:002> k
Child-SP RetAddr Call Site
00000000`1a94f5f8 000007fe`fcbf1430 ntdll!ZwWaitForMultipleObjects+0xa
00000000`1a94f600 00000000`76c816e3 KERNELBASE!WaitForMultipleObjectsEx+0xe8
00000000`1a94f700 000007fe`d1176361 kernel32!WaitForMultipleObjectsExImplementation+0xb3
00000000`1a94f790 000007fe`d1175de2 coreclr!FinalizerThread::WaitForFinalizerEvent+0x85 [e:a_work1791ssrcvmfinalizerthread.cpp @ 469]
00000000`1a94f7d0 000007fe`d10cd66b coreclr!FinalizerThread::FinalizerThreadWorker+0x62 [e:a_work1791ssrcvmfinalizerthread.cpp @ 587]
00000000`1a94f830 000007fe`d10cd586 coreclr!ManagedThreadBase_DispatchInner+0x43 [e:a_work1791ssrcvmthreads.cpp @ 9204]
00000000`1a94f870 000007fe`d10cd498 coreclr!ManagedThreadBase_DispatchMiddle+0x82 [e:a_work1791ssrcvmthreads.cpp @ 9253]
00000000`1a94f9d0 000007fe`d117587c coreclr!ManagedThreadBase_DispatchOuter+0xb4 [e:a_work1791ssrcvmthreads.cpp @ 9492]
00000000`1a94fa80 000007fe`d11773fb coreclr!FinalizerThread::FinalizerThreadStart+0x9c [e:a_work1791ssrcvmfinalizerthread.cpp @ 774]
00000000`1a94fb20 00000000`76c759cd coreclr!Thread::intermediateThreadProc+0x8b [e:a_work1791ssrcvmthreads.cpp @ 2594]
00000000`1a94fbe0 00000000`76eaa561 kernel32!BaseThreadInitThunk+0xd
00000000`1a94fc10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
As you see from the stack,it is finalizer thread
Now let's move on to .NET obejcts in the heap.For this ,we will use !dumpheap .
0:002> !dumpheap
Statistics:
MT Count TotalSize Class Name
000007fec5cd6c68 1 24 System.Collections.Generic.GenericEqualityComparer`1[[System.Char, System.Private.CoreLib]]
000007fec5ccb060 1 24 System.Environment+<>c
000007fec5cc5130 1 24 System.Collections.Generic.GenericEqualityComparer`1[[System.String, System.Private.CoreLib]]
000007fec5cbe1e0 1 24 System.Reflection.Missing
000007fec5cb8c58 1 24 System.Security.Policy.ApplicationTrust
000007fec5cb6e98 1 24 System.Diagnostics.Tracing.EtwEventProvider
000007fec5cb4168 1 24 System.OrdinalIgnoreCaseComparer
000007fec5cb4068 1 24 System.OrdinalCaseSensitiveComparer
000007fec5cb1bd8 1 24 System.SharedStatics
000007fec5ca00f8 1 24 System.WeakReference
000007fec5c91228 1 24 System.Collections.Generic.NonRandomizedStringEqualityComparer
000007fec5c88388 1 24 System.Boolean
000007fec5c53388 1 24 System.Attribute[]
000007fec537f038 1 24 System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]]
000007fe7157cdb8 1 24 System.IO.SyncTextReader
000007fe715790d8 1 24 System.Console+<>c
000007fe71566fe0 1 24 System.Collections.Generic.ObjectEqualityComparer`1[[System.RuntimeType, System.Private.CoreLib]]
000007fec5c62708 1 26 System.Globalization.CalendarId[]
000007fec5c53260 1 31 System.Boolean[]
000007fec5ce2358 1 32 System.Buffers.TlsOverPerCoreLockedStacksArrayPool`1[[System.Char, System.Private.CoreLib]]
000007fec5ccc430 1 32 System.IO.Stream+NullStream
000007fec5c9d0a8 1 32 System.Diagnostics.Tracing.ActivityTracker
000007fec5c8da20 1 32 System.Guid
000007fec5c59028 1 32 System.Reflection.RuntimePropertyInfo[]
000007fec5c98ef0 1 40 System.Collections.Generic.List`1+Enumerator[[System.String, System.Private.CoreLib]]
000007fec5c54658 1 40 System.WeakReference[]
000007fec5378e28 1 40 System.Collections.Generic.List`1[[System.WeakReference, System.Private.CoreLib]]
000007fec5377168 1 40 System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]]
000007fe7157bc50 1 40 System.IO.TextWriter+NullTextWriter
000007fe715799e0 1 40 Interop+InputRecord
000007fe71567680 1 40 System.Reflection.CerHashtable`2+Table[[System.String, System.Private.CoreLib],[System.Reflection.RuntimePropertyInfo[], System.Private.CoreLib]]
000007fe715668c0 1 40 System.Collections.Generic.Dictionary`2+KeyCollection+Enumerator[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]]
000007fec5cce310 1 48 System.Text.Encoding+DefaultDecoder
000007fec5c59768 2 48 System.Reflection.ParameterInfo[]
000007fe7157c0f8 1 48 System.IO.SyncTextWriter
000007fe7157be68 1 48 System.Text.OSEncoder
000007fec5c92158 1 56 System.RuntimeType+RuntimeTypeCache+MemberInfoCache`1[[System.Reflection.RuntimePropertyInfo, System.Private.CoreLib]]
000007fec5c91d58 1 56 System.RuntimeType+RuntimeTypeCache+MemberInfoCache`1[[System.Reflection.RuntimeMethodInfo, System.Private.CoreLib]]
000007fec5c8f3e8 1 56 System.Reflection.RuntimeAssembly
000007fec5c88d10 1 56 System.Globalization.CompareInfo
000007fec5cb3f58 2 64 System.CultureAwareComparer
000007fec5ca0e78 2 64 System.LazyHelper
000007fec5c963c8 1 64 System.Reflection.RuntimeModule
000007fec5c49988 1 64 Microsoft.Win32.UnsafeNativeMethods+ManifestEtw+EtwEnableCallback
000007fe7157c6e0 1 64 System.Func`1[[System.IO.TextReader, System.Runtime.Extensions]]
000007fe71579188 1 64 System.Func`1[[System.IO.TextWriter, System.Runtime.Extensions]]
000007fe71567188 2 64 System.Diagnostics.Tracing.EventSourceAttribute[]
000007fec5ca64e0 3 72 System.IntPtr
000007fec5cb7070 2 80 System.Diagnostics.Tracing.EventSourceAttribute
000007fec5c9d478 2 80 System.Lazy`1[[System.Boolean, System.Private.CoreLib]]
000007fec537a308 1 80 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.Globalization.CultureData, System.Private.CoreLib]]
000007fec53799f0 1 80 System.Collections.Generic.Dictionary`2[[System.RuntimeType, System.Private.CoreLib],[System.RuntimeType, System.Private.CoreLib]]
000007fe715677c8 1 80 System.Reflection.RuntimePropertyInfo[][]
000007fec5cce920 2 96 System.Text.UTF8Encoding+UTF8EncodingSealed
000007fec5ccb5e8 1 96 System.Diagnostics.Tracing.EventSource+OverideEventProvider
000007fec5c587e0 2 96 System.Reflection.CustomAttributeRecord[]
000007fec5c54280 3 96 System.IntPtr[]
000007fe7157cbc0 1 96 System.IO.StreamReader
000007fe715662b8 1 96 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[System.Globalization.CultureData, System.Private.CoreLib]][]
000007fec5c92b58 1 104 System.Reflection.RuntimePropertyInfo
000007fe7157b9d0 1 104 System.IO.StreamWriter
000007fec5cc38f0 2 112 System.Text.UnicodeEncoding
000007fe7157b4b8 2 112 System.Text.ConsoleEncoding
000007fe71579e10 2 112 System.ConsolePal+WindowsConsoleStream
000007fec5c590b8 3 120 System.Reflection.RuntimeMethodInfo[]
000007fec5c9ba08 4 128 System.Text.DecoderReplacementFallback
000007fec5c9b9a8 4 128 System.Text.EncoderReplacementFallback
000007fec5c8b930 2 128 System.Globalization.TextInfo
000007fec5c44c10 2 128 System.Func`1[[System.Boolean, System.Private.CoreLib]]
000007fe7157b0a0 2 128 System.Text.OSEncoding
000007fe71567c28 2 128 System.Func`1[[System.Text.Encoding, System.Private.CoreLib]]
000007fec5cb81b0 1 152 System.Buffers.ArrayPoolEventSource
000007fec5cb3db8 1 152 System.StackOverflowException
000007fec5cb2f68 1 152 System.ExecutionEngineException
000007fec5ca5ba0 1 152 System.OutOfMemoryException
000007fec5c8a718 1 152 System.Exception
000007fec5c88340 1 152 System.AppDomain
000007fec5cc2cb8 4 160 System.Text.InternalEncoderBestFitFallback
000007fec5c90d98 1 160 System.Globalization.CalendarData
000007fec5c6d230 1 160 System.Char[][]
000007fec5c55b50 1 160 System.Buffers.TlsOverPerCoreLockedStacksArrayPool`1+PerCoreLockedStacks[[System.Char, System.Private.CoreLib]][]
000007fec5c8af30 7 168 System.Object
000007fec5cb19e8 2 176 System.RuntimeMethodInfoStub
0000000000483380 7 186 Free
000007fec5cc2770 4 192 System.Text.InternalDecoderBestFitFallback
000007fec5c8b5a0 4 192 System.Text.StringBuilder
000007fec5c2fba8 3 192 System.Reflection.MemberFilter
000007fec5c923c0 2 208 System.Reflection.RuntimeMethodInfo
000007fec5c61260 1 208 System.Globalization.CalendarData[]
000007fec5c54ec8 7 216 System.Type[]
000007fec5c96bd8 3 240 System.Signature
000007fe71566b68 1 288 System.Collections.Generic.Dictionary`2+Entry[[System.RuntimeType, System.Private.CoreLib],[System.RuntimeType, System.Private.CoreLib]][]
000007fec5cb9c80 2 304 System.Threading.ThreadAbortException
000007fec5c91cb8 2 304 System.RuntimeType+RuntimeTypeCache
000007fec5c9c190 3 312 System.AppDomainSetup
000007fec5379db0 4 320 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]]
000007fec5c88be8 3 336 System.Globalization.CultureInfo
000007fec5c546f8 1 364 System.UInt32[]
000007fec5c53e28 10 384 System.RuntimeType[]
000007fec5c54158 13 940 System.Int32[]
000007fec5c8b498 2 944 System.Globalization.CultureData
000007fe71566648 6 1008 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]][]
000007fec5c8dd70 36 1440 System.RuntimeType
000007fec5c528e8 24 1728 System.String[]
000007fec5c53050 7 4148 System.Byte[]
000007fec5c52ca8 10 17776 System.Object[]
000007fec5c567e0 14 31538 System.Char[]
000007fec5c87be8 320 94632 System.String
We see that there are around 600 objects. We can get more details about !dumpheap by getting the help with help command
0:002> !help dumpheap0:002> !help dumpheap-------------------------------------------------------------------------------!DumpHeap [-stat] [-strings] [-short] [-min <size>] [-max <size>] [-live] [-dead] [-thinlock] [-startAtLowerBound] [-mt <MethodTable address>] [-type <partial type name>] [start [end]]
!DumpHeap is a powerful command that traverses the garbage collected heap, collection statistics about objects. With it's various options, it can look forparticular types, restrict to a range, or look for ThinLocks (see !SyncBlk documentation). Finally, it will provide a warning if it detects excessive fragmentation in the GC heap.
When called without options, the output is first a list of objects in the heap,followed by a report listing all the types found, their size and number:
0:000> !dumpheap Address MT Size 00a71000 0015cde8 12 Free 00a7100c 0015cde8 12 Free 00a71018 0015cde8 12 Free 00a71024 5ba58328 68 00a71068 5ba58380 68 00a710ac 5ba58430 68 00a710f0 5ba5dba4 68 ... total 619 objects Statistics: MT Count TotalSize Class Name 5ba7607c 1 12 System.Security.Permissions.HostProtectionResource 5ba75d54 1 12 System.Security.Permissions.SecurityPermissionFlag 5ba61f18 1 12 System.Collections.CaseInsensitiveComparer ... 0015cde8 6 10260 Free 5ba57bf8 318 18136 System.String ...
"Free" objects are simply regions of space the garbage collector can use later.If 30% or more of the heap contains "Free" objects, the process may suffer fromheap fragmentation. This is usually caused by pinning objects for a long time combined with a high rate of allocation. Here is example output where !DumpHeapprovides a warning about fragmentation:
<After the Statistics section> Fragmented blocks larger than 1MB: Addr Size Followed by 00a780c0 1.5MB 00bec800 System.Byte[] 00da4e38 1.2MB 00ed2c00 System.Byte[] 00f16df0 1.2MB 01044338 System.Byte[]
The arguments in detail:
-stat Restrict the output to the statistical type summary-strings Restrict the output to a statistical string value summary-short Limits output to just the address of each object. This allows you to easily pipe output from the command to another debugger command for automation.-min Ignore objects less than the size given in bytes-max Ignore objects larger than the size given in bytes-live Only print live objects-dead Only print dead objects (objects which will be collected in the next full GC)-thinlock Report on any ThinLocks (an efficient locking scheme, see !SyncBlk documentation for more info)-startAtLowerBound Force heap walk to begin at lower bound of a supplied address range. (During plan phase, the heap is often not walkable because objects are being moved. In this case, DumpHeap may report spurious errors, in particular bad objects. It may be possible to traverse more of the heap after the reported bad object. Even if you specify an address range, !DumpHeap will start its walk from the beginning of the heap by default. If it finds a bad object before the specified range, it will stop before displaying the part of the heap in which you are interested. This switch will force !DumpHeap to begin its walk at the specified lower bound. You must supply the address of a good object as the lower bound for this to work. Display memory at the address of the bad object to manually find the next method table (use !dumpmt to verify). If the GC is currently in a call to memcopy, You may also be able to find the next object's address by adding the size to the start address given as parameters.) -mt List only those objects with the MethodTable given-type List only those objects whose type name is a substring match of the string provided. start Begin listing from this addressend Stop listing at this address
A special note about -type: Often, you'd like to find not only Strings, butSystem.Object arrays that are constrained to contain Strings. ("new String[100]" actually creates a System.Object array, but it can only holdSystem.String object pointers). You can use -type in a special way to findthese arrays. Just pass "-type System.String[]" and those Object arrays willbe returned. More generally, "-type <Substring of interesting type>[]".
The start/end parameters can be obtained from the output of !EEHeap -gc. For example, if you only want to list objects in the large heap segment:
0:000> !eeheap -gc Number of GC Heaps: 1 generation 0 starts at 0x00c32754 generation 1 starts at 0x00c32748 generation 2 starts at 0x00a71000 segment begin allocated size 00a70000 00a71000 010443a8 005d33a8(6108072) Large object heap starts at 0x01a71000 segment begin allocated size 01a70000 01a71000 01a75000 0x00004000(16384) Total Size 0x5d73a8(6124456) ------------------------------ GC Heap Size 0x5d73a8(6124456)
0:000> !dumpheap 1a71000 1a75000 Address MT Size 01a71000 5ba88bd8 2064 01a71810 0019fe48 2032 Free 01a72000 5ba88bd8 4096 01a73000 0019fe48 4096 Free 01a74000 5ba88bd8 4096 total 5 objects Statistics: MT Count TotalSize Class Name 0019fe48 2 6128 Free 5ba88bd8 3 10256 System.Object[] Total 5 objects
Finally, if GC heap corruption is present, you may see an error like this:
0:000> !dumpheap -stat object 00a73d24: does not have valid MT curr_object : 00a73d24 Last good object: 00a73d14 ----------------
That indicates a serious problem. See the help for !VerifyHeap for more information on diagnosing the cause.
We can use DumpHeap command to look for memory leak issues in our application.
following are the different usecase of dumpheap command
- To get all the strings loaded into our application
0:002> !dumpheap -strings
00000000023313f0 000007fec5c87be8 26
00000000023314c0 000007fec5c87be8 42
0000000002331600 000007fec5c87be8 94
0000000002331680 000007fec5c87be8 46
00000000023316b0 000007fec5c87be8 74
0000000002331700 000007fec5c87be8 40
00000000023317e8 000007fec5c87be8 80
0000000002331838 000007fec5c87be8 27448
0000000002338370 000007fec5c87be8 84
00000000023383c8 000007fec5c87be8 146
0000000002338460 000007fec5c87be8 72
00000000023384a8 000007fec5c87be8 68
00000000023384f0 000007fec5c87be8 98
0000000002338558 000007fec5c87be8 78
00000000023385a8 000007fec5c87be8 112
0000000002338618 000007fec5c87be8 70
===============trimmed=====================
42 1 HH:mm:ss
42 1 November
42 1 Saturday
42 1 Thursday
42 1 encoding
42 1 hh:mm tt
42 1 December
42 1 February
42 1 Infinity
42 1 Internet
42 1 JIT_PATH
44 1 September
44 1 FullTrust
44 1 yyyy MMMM
44 1 -Infinity
44 1 APP_PATHS
44 1 Wednesday
46 1 MM/dd/yyyy
46 1 yyyy-MM-dd
48 1 MultiDomain
50 1 NotSpecified
50 1 FX_DEPS_FILE
50 1 APP_NI_PATHS
50 1 SingleDomain
50 1 Hello World!
56 1 MultiDomainHost
60 1 Invariant Country
62 1 Gregorian Calendar
62 1 Invariant Language
62 1 dddd, dd MMMM yyyy
64 1 PROBING_DIRECTORIES
64 1 LOADER_OPTIMIZATION
66 1 ArrayPoolEventSource
68 1 !x-sys-default-locale
68 2 Name
68 1 APP_LOCAL_WINMETADATA
68 1 RFLCT_InvalidPropFail
70 1 RFLCT_InvalidFieldFail
70 1 APP_CONTEXT_DEPS_FILES
72 2 en-us
72 2 bytes
72 2 chars
78 1 APP_CONTEXT_BASE_DIRECTORY
80 1 International Monetary Fund
86 1 System.Globalization.Invariant
88 2 charCount
88 2 byteCount
88 2 charIndex
90 1 UseRandomizedStringHashAlgorithm
92 2 dotnet.exe
96 1 SYSTEM.BUFFERS.ARRAYPOOLEVENTSOURCE
98 1 UseLatestBehaviorWhenTFMNotSpecified
102 1 Invariant Language (Invariant Country)
108 3 en-US
112 1 D:PROJECTSdotnetbinDebugnetcoreapp2.0
122 1 System.Diagnostics.Eventing.FrameworkEventSource
130 1 ERROR: Exception during construction of EventSource
136 2 AppDomainCompatSwitch
144 2 PLATFORM_RESOURCE_ROOTS
146 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5;
148 2 C:Program Filesdotnet
160 2 TRUSTED_PLATFORM_ASSEMBLIES
164 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5clrj
168 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5msco
168 2 NATIVE_DLL_SEARCH_DIRECTORIES
174 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5Wind
174 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5SOS.
174 1 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5nets
188 2 C:Program Filesdotnetdotnet.exe
192 2 System.Buffers.ArrayPoolEventSource
264 2 D:PROJECTSdotnetbinDebugnetcoreapp2.0dotnet.dll
298 1 C:Program Filesdotnetstorex64netcoreapp2.0;C:Usersrkolak
326 1 D:PROJECTSdotnetbinDebugnetcoreapp2.0dotnet.deps.json;C:
988 5 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5Micr
29538 146 C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5Syst
54894 2 D:PROJECTSdotnetbinDebugnetcoreapp2.0dotnet.dll;C:Progra
You can get all the strings from the process e.g. your password stored as plaintext and stored in config if you are loading that into memory,you will be able to see it here.
- To check the objects in LOH Large Object Heap
any objects which are more than 85000 bytes will be stored in Large Object Heap(LOH) and lot of objects in LOH can cause memory issues in your application.
0:002> !dumpheap -min 85000
Address MT Size
Statistics:
MT Count TotalSize Class Name
Total 0 objects
We did not get any large objects
- How many objects are locked using lock statements
0:002> !dumpheap -thinlock
Address MT Size
0000000002355260 000007fe7157cdb8 24 ThinLock owner 1 (00000000005cb900) Recursive 0
Found 1 objects.
0:002> !do 0000000002355260
Name: System.IO.SyncTextReader
MethodTable: 000007fe7157cdb8
EEClass: 000007fe716cbc98
Size: 24(0x18) bytes
File: C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Console.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fe7157c520 40001a5 d0 System.IO.TextReader 0 static 0000000000000000 Null
000007fe7157c520 400011c 8 System.IO.TextReader 0 instance 00000000023548a0 _in
ThinLock owner 1 (00000000005cb900), Recursive 0
- Dump all the objects of a particular type
0:002> !dumpheap -type Console
Address MT Size
00000000023530e0 000007fe715790d8 24
0000000002353178 000007fe71579e10 56
0000000002353330 000007fe7157b4b8 56
0000000002354700 000007fe71579e10 56
0000000002354810 000007fe7157b4b8 56
Statistics:
MT Count TotalSize Class Name
000007fe715790d8 1 24 System.Console+<>c
000007fe7157b4b8 2 112 System.Text.ConsoleEncoding
000007fe71579e10 2 112 System.ConsolePal+WindowsConsoleStream
Total 5 objects
Dumping an object from process and looking at all properties
To get the details of any object,we will be using !DumpObject command.To this command,you have to pass the Object Address.Normally we use DumpObject command along with another command(dumpheap). We will first use dumpheap to find the address of a particular tpe of object and then use DumpObject(!do is alias) to further drill down
0:002> !dumpheap -type Console
Address MT Size
00000000023530e0 000007fe715790d8 24
0000000002353178 000007fe71579e10 56
0000000002353330 000007fe7157b4b8 56
0000000002354700 000007fe71579e10 56
0000000002354810 000007fe7157b4b8 56
Statistics:
MT Count TotalSize Class Name
000007fe715790d8 1 24 System.Console+<>c
000007fe7157b4b8 2 112 System.Text.ConsoleEncoding
000007fe71579e10 2 112 System.ConsolePal+WindowsConsoleStream
Total 5 objects
0:002> !do 00000000023530e0
Name: System.Console+<>c
MethodTable: 000007fe715790d8
EEClass: 000007fe716cadc0
Size: 24(0x18) bytes
File: C:Program FilesdotnetsharedMicrosoft.NETCore.App2.0.5System.Console.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fe715790d8 4000044 60 System.Console+<>c 0 static 00000000023530e0 <>9
000007fe7157c6e0 4000045 68 ...time.Extensions]] 0 static 00000000023546c0 <>9__13_0
000007fe71567c28 4000046 70 ...Private.CoreLib]] 0 static 0000000002354738 <>9__15_0
000007fe71567c28 4000047 78 ...Private.CoreLib]] 0 static 00000000023531b0 <>9__18_0
000007fe71579188 4000048 80 ...time.Extensions]] 0 static 00000000023530f8 <>9__25_0
000007fe71579188 4000049 88 ...time.Extensions]] 0 static 0000000000000000 <>9__27_0
0000000000000000 400004a 90 0 static 0000000000000000 <>9__33_0
0000000000000000 400004b 98 0 static 0000000000000000 <>9__35_0
0000000000000000 400004c a0 0 static 0000000000000000 <>9__37_0
000007fec5c701d8 400004d a8 ...Private.CoreLib]] 0 static 0000000000000000 <>9__151_0
In our next post we will explore looking inside a ASP.NET CORE process.We will also explore more detail commands which can help you find memory leak inside a asp.net core process.