[libunwind][AIX] implementation of the unwinder for AIX

Summary:
This patch contains the implementation of the unwinder for IBM AIX.

AIX does not support the eh_frame section. Instead, the traceback table located at the end of each function provides the information for stack unwinding and EH. In this patch macro _LIBUNWIND_SUPPORT_TBTAB_UNWIND is used to guard code for AIX traceback table based unwinding. Function getInfoFromTBTable() and stepWithTBTable() are added to get the EH information from the traceback table and to step up the stack respectively.

There are two kinds of LSDA information for EH on AIX, the state table and the range table. The state table is used by the previous version of the IBM XL compiler, i.e., xlC and xlclang++. The DWARF based range table is used by AIX clang++. The traceback table has flags to differentiate these cases. For the range table, relative addresses are calculated using a base of DW_EH_PE_datarel, which is the TOC base of the module where the function of the current frame belongs.

Two personality routines are employed to handle these two different LSDAs, __xlcxx_personality_v0() for the state table and __xlcxx_personality_v1() for the range table. Since the traceback table does not have the information of the personality for the state table approach, its personality __xlcxx_personality_v0() is dynamically resolved as the handler for the state table. For the range table, the locations of the LSDA and its associated personality routine are found in the traceback table.

Assembly code for 32- and 64-bit PowerPC in UnwindRegistersRestore.S and UnwindRegistersSave.S are modified so that it can be consumed by the GNU flavor assembler and the AIX assembler. The restoration of vector registers does not check VRSAVE on AIX because VRSAVE is not used in the AIX ABI.

Reviewed by: MaskRay, compnerd, cebowleratibm, sfertile, libunwind

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

NOKEYCHECK=True
GitOrigin-RevId: a85da649b9ac67afffec6bff9487e6405e1f9cba
diff --git a/src/Unwind_AIXExtras.cpp b/src/Unwind_AIXExtras.cpp
new file mode 100644
index 0000000..7e47f70
--- /dev/null
+++ b/src/Unwind_AIXExtras.cpp
@@ -0,0 +1,63 @@
+//===--------------------- Unwind_AIXExtras.cpp -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//
+//===----------------------------------------------------------------------===//
+
+// This file is only used for AIX.
+#if defined(_AIX)
+
+#include "config.h"
+#include "libunwind_ext.h"
+#include <sys/debug.h>
+
+namespace libunwind {
+// getFuncNameFromTBTable
+// Get the function name from its traceback table.
+char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
+                             unw_word_t *Offset) {
+  uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
+  *Offset = 0;
+
+  // Keep looking forward until a word of 0 is found. The traceback
+  // table starts at the following word.
+  while (*p)
+    p++;
+  tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
+
+  if (!TBTable->tb.name_present)
+    return NULL;
+
+  // Get to the name of the function.
+  p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
+
+  // Skip field parminfo if it exists.
+  if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+    p++;
+
+  // If the tb_offset field exisits, get the offset from the start of
+  // the function to pc. Skip the field.
+  if (TBTable->tb.has_tboff) {
+    unw_word_t StartIp =
+        reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
+    *Offset = Pc - StartIp;
+    p++;
+  }
+
+  // Skip field hand_mask if it exists.
+  if (TBTable->tb.int_hndl)
+    p++;
+
+  // Skip fields ctl_info and ctl_info_disp if they exist.
+  if (TBTable->tb.has_ctl) {
+    p += 1 + *p;
+  }
+
+  NameLen = *(reinterpret_cast<uint16_t *>(p));
+  return reinterpret_cast<char *>(p) + sizeof(uint16_t);
+}
+} // namespace libunwind
+#endif // defined(_AIX)