CaptureStackBackTrace and SymGetLineFromAddr64 can't get line info returns error code 487
I was using cl.exe in my Makefile without the /Zi compile option. When I added /Zi the line numbers and filenames appeared.
Fast capture stack trace on windows / 64-bit / mixed mode
9-1-2015 - I've located original function which gets called by process hacker, and that one was
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll
OutOfProcessFunctionTableCallback
it's source code - which was here:
https://github.com/dotnet/coreclr/blob/master/src/debug/daccess/fntableaccess.cpp
From there I have owner of most of changes in that source code - Jan Kotas (jkotas@microsoft.com) and contacted him about this problem.
From: Jan Kotas <jkotas@microsoft.com>
To: Tarmo Pikaro <tapika@yahoo.com>
Sent: Friday, January 8, 2016 3:27 PM
Subject: RE: Fast capture stack trace on windows 64 bit / mixed mode...
...
The mscordacwks.dll is called mscordaccore.dll in CoreCLR / github repro. The VS project
files are auto-generated for it during the build
(\coreclr\bin\obj\Windows_NT.x64.Debug\src\dlls\mscordac\mscordaccore.vcxproj).
You should be able to build and debug CoreCLR to understand how it works.
...
From: Jan Kotas <jkotas@microsoft.com>
To: Tarmo Pikaro <tapika@yahoo.com>
Sent: Saturday, January 9, 2016 2:02 AM
Subject: RE: Fast capture stack trace on windows 64 bit / mixed mode...
> I've tried to replace
> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll dll loading
> with C:\Prototyping\dotNet\coreclr-master\bin\obj\Windows_NT.x64.Debug\src\dlls\mscordac\Debug\mscordaccore.dll
> loading (just compiled), but if previously I could get mixed mode stack trace correctly:
> ...
mscordacwks.dll is tightly coupled with the runtime. You cannot mix and match them between runtimes.
What I meant is that you can use CoreCLR to understand how this works.
But then he recommended this solution which was working for me:
int CaptureStackBackTrace3(int FramesToSkip, int nFrames, PVOID* BackTrace, PDWORD pBackTraceHash)
{
CONTEXT ContextRecord;
RtlCaptureContext(&ContextRecord);
UINT iFrame;
for (iFrame = 0; iFrame < nFrames; iFrame++)
{
DWORD64 ImageBase;
PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry(ContextRecord.Rip, &ImageBase, NULL);
if (pFunctionEntry == NULL)
break;
PVOID HandlerData;
DWORD64 EstablisherFrame;
RtlVirtualUnwind(UNW_FLAG_NHANDLER,
ImageBase,
ContextRecord.Rip,
pFunctionEntry,
&ContextRecord,
&HandlerData,
&EstablisherFrame,
NULL);
BackTrace[iFrame] = (PVOID)ContextRecord.Rip;
}
return iFrame;
}
This code snipet still is missing backtrace hash calculation, but this is something can can be added afterwards.
It's very import also to note that when debugging this code snipet you should use native debugging, not mixed mode (C# project by default use mixed mode), because it somehow disturbs stack trace in debugger. (Something to figure out how and why such distortion happens)
There is still one missing piece of puzzle - how to make symbol resolution fully resistant to FreeLibrary / Jit code dispose, but this is something I need to figure out still.
Please note that RtlVirtualUnwind will most probably work only on 64-bit architecture, not on arm or 32-bit.
One more funny thing is that there exists function RtlCaptureStackBackTrace
which somehow resembles windows api function CaptureStackBackTrace - but they somehow differ - at least by naming. Also if you check RtlCaptureStackBackTrace - it calls eventually RtlVirtualUnwind - you can check it from Windows Research Kernel source codes
RtlCaptureStackBackTrace
>
RtlWalkFrameChain
>
RtlpWalkFrameChain
>
RtlVirtualUnwind
But what I have tested RtlCaptureStackBackTrace does not works correctly.
Unlike function RtlVirtualUnwind above.
It's a kinda magic. :-)
I'll continue this questionnaire with phase 2 question - in here:
Resolve managed and native stack trace - which API to use?
Related Topics
How to Write a Variadic Template Recursive Function
Which Header Should I Include for 'Size_T'
What Exactly Is Va_End For? Is It Always Necessary to Call It
Iterating Over a Vector in Reverse Direction
Converting a Vector<Int> to String
C++: How to Check If the Cin Buffer Is Empty
Why Can't I Static_Cast Between Char * and Unsigned Char *
Are All Temporaries Rvalues in C++
Setting Thread Priority in Linux with Boost
Compile Time Template Instantiation Check
How to Perform a Pairwise Binary Operation Between the Elements of Two Containers
How to Determine Programmatically If an Expression Is Rvalue or Lvalue in C++
Brute-Force, Single-Threaded Prime Factorization
Reading and Writing to Usb (Hid) Interrupt Endpoints on MAC
Zero Initialization and Static Initialization of Local Scope Static Variable
Print Template Typename at Compile Time
Is the Std::Set Iteration Order Always Ascending According to the C++ Specification