[llvm-dev] Supporting libunwind on Windows 10 (32bit; 64bit) for MSVC and Clang
Ivan Serdyuk via llvm-dev
llvm-dev at lists.llvm.org
Sun Aug 16 16:30:20 PDT 2020
This is what Ken Johnson replied:
On Sun, Aug 16, 2020 at 4:09 PM Skywing <Skywing at valhallalegends.com> wrote:
> I just briefly skimmed the discussion, so hopefully I didn't misunderstand
> what you are trying to do ... but if your objective is to capture a stack
> trace under NT, the OS exports several services for this purpose, depending
> on what you need out of such a stack trace :
> 1) There is a "pre-cooked" stack trace facility that will perform the
> entire stack trace for you (optionally skipping some frames at the top),
> returning an array of program counter values for each return address on the
> (CaptureStackBackTrace) and its kernel/NTDLL equivalent
> 2) Alternatively, if more customization for the operation than what
> CaptureStackBackTrace/RtlCaptureStackBackTrace affords is required, then
> you could walk the stack manually by successively invoking
> (RtlVirtualUnwind) for each frame, starting with a live register context
> (e.g. as captured by
> (RtlCaptureContext)). This would give you the opportunity to examine, for
> instance, the nonvolatile register context for each frame, albeit at the
> cost of having to write platform dependent code for each build target (e.g.
> AMD64, 32-bit ARMNT, ARM64, etc.). RtlCaptureStackBackTrace is essentially
> implemented in this way for non-32-bit-x86 targets (x86 doesn't have what
> most architectures would consider an "unwinder" in the sense of restoring
> registers; there is simply a linked list of frames that participate in SEH
> and that desire to be called for a dynamic unwind operation, so
> RtlCaptureStackBackTrace assumes that EBP-based frames are in use and walks
> an EBP-based frame chain on x86 - not all x86 code is written with
> EBP-based frames so while even though we generally build the OS that way,
> you might always run the risk of encountering external code that uses EBP
> as a general purpose register for which such an unwind attempt for a stack
> trace would fail). On non-x86 architectures, the various NT platform ABIs
> typically strive to provide for precise unwinding at all frames and at
> every instruction boundary where interrupts are enabled (at least assuming
> that all code in the process is well-formed and follows the ABI properly
> etc. - interrupts are always enabled in user mode code). For C/C++ code,
> VC, ICC, and (I believe) LLVM/clang should support the platform
> exception/unwind ABIs; GCC may or may not these days.
> The OS's exception and unwind dispatcher, for non-x86 build targets, uses
> the virtual unwind facility to accomplish unwinding for purposes of
> exception handling related exception dispatching & unwinding.
> On the non-x86 targets, debuggers and related tools would typically use
> the platform ABI's exception and unwind handling structures for their
> unwinding as well. Debuggers on x86 might either assume EBP-based frames,
> or use compiler-specific debug information from debug symbols (typically
> not embedded in the compiled binary for most NT-targeted code but rather
> kept in a standalone .pdb/.dbg file etc.).
> Note that the platform exception and unwind APIs and associated structures
> embedded in executable images don't, on their own, provide a way to map a
> PC value to a meaningful symbolic function name, line number, etc.. If you
> want to resolve PC values to function names, then you'll typically need
> debug symbols for each module present on the call stack. For that,
> provided that you have debug symbols available for all such frames (OS
> binaries have these published on the Microsoft public symbol server; some
> major third parties like web browsers publish their symbols on their own
> symbol servers as well but many other third party binaries may not make
> such affordances available). There are a set of APIs (
> https://docs.microsoft.com/en-us/windows/win32/debug/symbol-handling) to
> load debug symbols for a module, and resolve a module + RVA (i.e. module +
> offset into the module) to a symbol name and offset into the symbol. When
> debug symbols aren't available, these facilities will typically pick the
> nearest exported symbol (if any), which may or may not be at all meaningful
> (most symbols aren't exported in most executables targeting NT). Note that
> loading and processing debug symbols is typically a considerably more
> "heavyweight" operation than invoking the platform unwind APIs.
> - S
how close are these capabilities to what you planned for libbacktrace?
please explain which scenarios did you assume, for libbacktrace, while
integrating Ian's project with https://go.googlesource.com/gollvm/.
Please check Ken's considerations and tell which of those would be the
native way to support unwinding capabilities.
I think there is some undocumented context, for that, related to gollvm.
Consider this related to github issues, targeting support of Windows 10
(x86_64; i386). And btw - specifically ARM64 oriented Windows 10 haven't
been suggested yet, by ARM's engineers, which contributed into brief
support of ARM64 oriented Linux.
On Sun, Aug 16, 2020 at 11:17 PM Ivan Serdyuk <local.tourist.kiev at gmail.com>
> good to hear from you.
> Thanks for the effort - I will test on 32bit and 64bit Windows 10.
> I will report ASAP.
> On Sun, Aug 16, 2020 at 8:42 PM Martin Storsjö <martin at martin.st> wrote:
>> On Sat, 15 Aug 2020, Ivan Serdyuk wrote:
>> > On Sat, Aug 15, 2020 at 8:39 PM Martin Storsjö <martin at martin.st>
>> > Hi,
>> > On Sat, 15 Aug 2020, Ivan Serdyuk wrote:
>> > > Just as Shoaib said, libunwind only is useful in
>> > environments
>> > > that use
>> > > the Itanium C++ ABI - there's really no use for it in an
>> > MSVC
>> > > context
>> > > (either using MSVC or clang-cl to compile it).
>> > >
>> > > The particular linker error comes from the fact that
>> > there's
>> > > functions
>> > > implemented in assembly, that expect the function name
>> > to be
>> > > mangled the
>> > > itanium way, while the object files built by the
>> > compiler expect
>> > > the
>> > > symbols to use the MSVC C++ name mangling, so there's an
>> > > undefined
>> > > reference.
>> > >
>> > >
>> > > I see, thanks.
>> > >
>> > > Which options exist for MSVC, in sense an alternative to
>> > libunwind and
>> > > libbacktrace ?
>> > Well for libunwind, there's really no use for it in an MSVC
>> > setting. All
>> > the unwinding functionality is already built into the operating
>> > system,
>> > available via the Rtl*Unwind* functions.
>> > Martin,
>> > you mean these functions
>> > 2
>> > ex
>> > lunwind
>> > ?
>> Yes, those are the functions used for unwinding on windows.
>> > For libbacktrace, I guess the _Unwind_Backtrace function in
>> > libunwind
>> > might work and be useful, even if the rest of libunwind doesn't
>> > make sense
>> > in such a context.
>> Just FWIW, I made a RFC patch that fixes building libunwind in MSVC mode
>> (still requiring clang-cl though), at https://reviews.llvm.org/D86041 -
>> mostly just to show what it takes - not convinced that it necessarily is
>> something that should be done.
>> It does seem like _Unwind_Backtrace in libunwind doesn't work properly on
>> x86_64 windows at the moment though, but on aarch64 it seems to do what
>> one would expect.
>> // Martin
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the llvm-dev