This is an archive of the discontinued LLVM Phabricator instance.

[libunwind] Add 64-bit SPARC support
AbandonedPublic

Authored by MaskRay on Apr 24 2017, 12:42 PM.

Details

Summary

This adds unwinder support for 64-bit SPARC (aka SPARCv9). The implementation was done on OpenBSD/sparc64, so it takes StackGhost into account:

https://www.usenix.org/legacy/publications/library/proceedings/sec01/full_papers/frantzen/frantzen_html/index.html

Since StackGhost xor's return addresses with a random cookie before storing them on the stack, the unwinder has to do some extra work to recover those. This is done by introducing a new kRegisterInCFADecrypt "location" type that is used
to implement the DW_CFA_GNU_window_save opcode. That implementation is SPARC-specific, but should work for 32-bit SPARC as well. DW_CFA_GNU_window_save is only ever generated on SPARC as far as I know.

Diff Detail

Event Timeline

kettenis created this revision.Apr 24 2017, 12:42 PM
compnerd requested changes to this revision.Apr 24 2017, 5:52 PM
compnerd added inline comments.
libunwind/src/DwarfInstructions.hpp
89

Please prefer static_cast rather than the C-style cast as this is C++ code.

libunwind/src/DwarfParser.hpp
659

Is the DW_CFA_GNU_window_save operand limited to SPARC? I think that we should handle this generically, not specific to SPARC. We can add a special case for SPARC if the generic way to handle windows registers doesn't work.

This revision now requires changes to proceed.Apr 24 2017, 5:52 PM
joerg added inline comments.Apr 24 2017, 5:58 PM
libunwind/src/DwarfParser.hpp
659

Yes. It only makes sense on architectures with register windows and that essentially means SPARC. See the NetBSD version which goes as far as excluding the code for !sparc.

jyknight added inline comments.Apr 24 2017, 6:05 PM
libunwind/src/DwarfParser.hpp
659

Yes, window-save is sparc specific. However, it looks the value was reused for a totally different purpose on aarch64 (https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2.c#L1189). So this code should really be in a sparc conditional.

While that loop indeed describes part of the effect of a SAVE instruction, this is potentially dangerous as it may cause the unwinder to believe that a certain register is still "live" when in reality it has been clobbered already. This is because the unwinder doesn't recursively apply its location logic, but instead returns the raw register contents for a kRegisterInRegister location. The GCC unwinder doesn't have this loop. What happens instead is that it explicitly issues DWARF instructions that say that the return address now lives in i7 instead of o7. Other compilers, including clang, do this too.

kettenis added inline comments.Apr 25 2017, 12:07 AM
libunwind/src/DwarfInstructions.hpp
89

The code surrounding this uses C-style casts. I can change those too, but that's probably best done as a separate change.

joerg added a comment.Apr 25 2017, 1:52 PM

Liveness of registers is pretty much ephemeral at this point. The unwind register locations are not recursive either. They are applied in order.

Ping, is there anything else that needs to be done here?

brad added a subscriber: brad.Apr 20 2021, 2:50 PM

Ping. I've rebased this patch to build with recent versions, should I upload it here, or do I need to make a new review ticket?

MaskRay commandeered this revision.Feb 5 2022, 2:43 PM
MaskRay added a reviewer: kettenis.
MaskRay abandoned this revision.Feb 5 2022, 2:43 PM

Abandoned by D116857