Scenario:
A customer has supplied you with a crash report containing a callstack with symbol relative offsets from DLLs. The callstack also indicates which module relates to which address.
Example Data:
ntoskrnl.exe!KeSynchronizeExecution+0x2246
ntoskrnl.exe!KeWaitForMultipleObjects+0x135e
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForSingleObject+0x373
ntoskrnl.exe!KeStallWhileFrozen+0x1977
ntoskrnl.exe!_misaligned_access+0x13f9
ntoskrnl.exe!KeWaitForMultipleObjects+0x152f
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForSingleObject+0x373
ntoskrnl.exe!NtWaitForSingleObject+0xb2
ntoskrnl.exe!setjmpex+0x34a3
ntdll.dll!ZwWaitForSingleObject+0xa
KERNELBASE.dll!WaitForSingleObjectEx+0x98
svlcoveragevalidatorstub_x64.dll!sendCommandLineAndStartTimeToGUI+0x2868
svlcoveragevalidatorstub_x64.dll!setValidatorFeedbackHookingComplete+0x1fa6
svlcoveragevalidatorstub_x64.dll!svl_sendMessageRawToUserInterface+0x21837
svlcoveragevalidatorstub_x64.dll!svl_sendMessageRawToUserInterface+0x218cb
KERNEL32.DLL!BaseThreadInitThunk+0x22
ntdll.dll!RtlUserThreadStart+0x34
This is real data from a bug at Software Verify Ltd. This is one thread from many in a dump relating to a deadlock bug we were investigating.
Question:
How do you decode these symbol relative offsets?
Answer:
In the above data we can see a callstack containing entries for ntoskrnl.exe, ntdll.dll, kernelbase.dll, kernel32.dll and svlcoveragevalidatorstub_x64.dll.
All the modules are Microsoft DLLs except for one DLL, which is part of C++ Coverage Validator, one of our tools.
To decode these values, we load svlCoverageValidatorStub_x64.dll into DbgHelpBrowser.exe (64 bit), then for each symbol we take the following actions.
For our purposes here, we're going to show how to convert one symbol. We're going to use the first symbol from svlCoverageValidatorStub_x64.dll in the example data above.
svlcoveragevalidatorstub_x64.dll!sendCommandLineAndStartTimeToGUI+0x2868
Type the symbol name into the Name Filter field, then click Filter. This makes it easy to find the symbol we want.
Once we have found the symbol, right click on the symbol to display the context menu and choose Offset from this symbol....
An alternate method is to click on the symbol to select it, then from the Query menu choose Find Symbol with Symbol Relative Address....
Or, from the Query menu choose Find Symbol with Symbol Relative Address... then choose the symbol you want from the combo box.
Type the offset into the dialog (hex values must be prefixed with 0x) and click OK.
The appropriate location in the code is found and displayed.
Results:
Repeating the process for the data shown above resulted in this information.
svlcoveragevalidatorstub_x64.dll!sendCommandLineAndStartTimeToGUI+0x2868 sendWorkerEx::sendWorkerProc sendworkerex.cpp 250
svlcoveragevalidatorstub_x64.dll!setValidatorFeedbackHookingComplete+0x1fa6 stubSendComm::stubSendProc stubsendcomm.cpp 611
svlcoveragevalidatorstub_x64.dll!svl_sendMessageRawToUserInterface+0x21837 memcpy
svlcoveragevalidatorstub_x64.dll!svl_sendMessageRawToUserInterface+0x218cb wcscpy
The query options are not available for .Net and .Net executables as there is no direct translation from a crash address/offset to a .Net symbol.
Without having access to the compiled .Net method address and the compiled address to ILASM instruction offset data it is impossible to translate crash addresses/offsets to .Net functions.
The compiled address to ILASM instruction offset data is only available in the context of a running .Net application attached to a .Net debugger or a .Net profiler.