[libunwind] [sparc] Add SPARCv9 support

Adds libunwind support for SPARCv9 (aka sparc64). This is a rebase of @kettenis' patch D32450, which I created (with his permission) because the original review has become inactive.
The changes are of a cosmetic nature to make it fit better with the new code style, and to reuse the existing SPARCv8 code, whenever possible.

Please let me know if I posted this on the wrong place. Also, the summary of the original review is reproduced below:

> 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.

Co-authored-by: Mark Kettenis
Reviewed By: #libunwind, thesamesam, MaskRay, Arfrever

Differential Revision: https://reviews.llvm.org/D116857

NOKEYCHECK=True
GitOrigin-RevId: 2b9554b8850192bdd86c02eb671de1d866df8d87
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index 1c50941..c1a241c 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -74,6 +74,13 @@
   }
 };
 
+template <typename R>
+auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {
+  return r.getWCookie();
+}
+template <typename R> uint64_t getSparcWCookie(const R &, long) {
+  return 0;
+}
 
 template <typename A, typename R>
 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
@@ -83,6 +90,10 @@
   case CFI_Parser<A>::kRegisterInCFA:
     return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
 
+  case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific
+    return addressSpace.getP(cfa + (pint_t)savedReg.value) ^
+           getSparcWCookie(registers, 0);
+
   case CFI_Parser<A>::kRegisterAtExpression:
     return (pint_t)addressSpace.getRegister(evaluateExpression(
         (pint_t)savedReg.value, addressSpace, registers, cfa));
@@ -124,6 +135,7 @@
   case CFI_Parser<A>::kRegisterIsExpression:
   case CFI_Parser<A>::kRegisterUnused:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
+  case CFI_Parser<A>::kRegisterInCFADecrypt:
     // FIX ME
     break;
   }
@@ -148,6 +160,7 @@
   case CFI_Parser<A>::kRegisterUndefined:
   case CFI_Parser<A>::kRegisterOffsetFromCFA:
   case CFI_Parser<A>::kRegisterInRegister:
+  case CFI_Parser<A>::kRegisterInCFADecrypt:
     // FIX ME
     break;
   }
@@ -266,6 +279,12 @@
       }
 #endif
 
+#if defined(_LIBUNWIND_TARGET_SPARC64)
+      // Skip call site instruction and delay slot.
+      if (R::getArch() == REGISTERS_SPARC64)
+        returnAddress += 8;
+#endif
+
 #if defined(_LIBUNWIND_TARGET_PPC64)
 #define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
 #define PPC64_ELFV1_R2_OFFSET 40