Setting up an example
Some sample code to be compiled with Visual Studio 2019:
#include <iostream>
class Test {
public:
__declspec(noinline) static int one()
{
throw std::exception("maximize debugging fun");
}
};
__declspec(noinline) int main()
{
return Test::one();
}
This will create the following call stack when being run in WinDbg:
0:000> k
# ChildEBP RetAddr
...
02 00affa6c 00661316 CallStackDecodingExample!Test::one+0x1d [C:\...\CallStackDecodingExample.cpp @ 6]
...
And we can use some calculations to get the numbers back and forth:
0:000> ? CallStackDecodingExample!Test::one+0x1d
Evaluate expression: 6689037 = 0066110d
0:000> ? CallStackDecodingExample
Evaluate expression: 6684672 = 00660000
0:000> ? CallStackDecodingExample+0x110d
Evaluate expression: 6689037 = 0066110d
0:000> ln 0066110d
[C:\...\CallStackDecodingExample.cpp @ 6]
(006610f0) CallStackDecodingExample!Test::one+0x1d |
(00661110) CallStackDecodingExample!main
Given the debugger was able to resolve the PDBs correctly, we now have the expected result. Let's try to get this without a debugging session, i.e. neither with live debugging nor with crash dump analysis, but by PDBs + text input.
Getting the address from a DLL + PDB
In WinDbg, use "Open dump file", although you don't have a crash dump file. Instead, open the DLL (wseclient.dll or CallStackDecodingExample.exe for this example).
Then use ln:
0:000> ln CallStackDecodingExample+0x110d
[C:\...\CallStackDecodingExample.cpp @ 6]
(004010f0) CallStackDecodingExample!Test::one+0x1d
| (00401110) CallStackDecodingExample!main