1*a85da649SXing Xue //===--------------------- Unwind_AIXExtras.cpp -------------------------===//
2*a85da649SXing Xue //
3*a85da649SXing Xue // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a85da649SXing Xue // See https://llvm.org/LICENSE.txt for license information.
5*a85da649SXing Xue // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a85da649SXing Xue //
7*a85da649SXing Xue //
8*a85da649SXing Xue //===----------------------------------------------------------------------===//
9*a85da649SXing Xue 
10*a85da649SXing Xue // This file is only used for AIX.
11*a85da649SXing Xue #if defined(_AIX)
12*a85da649SXing Xue 
13*a85da649SXing Xue #include "config.h"
14*a85da649SXing Xue #include "libunwind_ext.h"
15*a85da649SXing Xue #include <sys/debug.h>
16*a85da649SXing Xue 
17*a85da649SXing Xue namespace libunwind {
18*a85da649SXing Xue // getFuncNameFromTBTable
19*a85da649SXing Xue // Get the function name from its traceback table.
getFuncNameFromTBTable(uintptr_t Pc,uint16_t & NameLen,unw_word_t * Offset)20*a85da649SXing Xue char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
21*a85da649SXing Xue                              unw_word_t *Offset) {
22*a85da649SXing Xue   uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
23*a85da649SXing Xue   *Offset = 0;
24*a85da649SXing Xue 
25*a85da649SXing Xue   // Keep looking forward until a word of 0 is found. The traceback
26*a85da649SXing Xue   // table starts at the following word.
27*a85da649SXing Xue   while (*p)
28*a85da649SXing Xue     p++;
29*a85da649SXing Xue   tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
30*a85da649SXing Xue 
31*a85da649SXing Xue   if (!TBTable->tb.name_present)
32*a85da649SXing Xue     return NULL;
33*a85da649SXing Xue 
34*a85da649SXing Xue   // Get to the name of the function.
35*a85da649SXing Xue   p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
36*a85da649SXing Xue 
37*a85da649SXing Xue   // Skip field parminfo if it exists.
38*a85da649SXing Xue   if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
39*a85da649SXing Xue     p++;
40*a85da649SXing Xue 
41*a85da649SXing Xue   // If the tb_offset field exisits, get the offset from the start of
42*a85da649SXing Xue   // the function to pc. Skip the field.
43*a85da649SXing Xue   if (TBTable->tb.has_tboff) {
44*a85da649SXing Xue     unw_word_t StartIp =
45*a85da649SXing Xue         reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
46*a85da649SXing Xue     *Offset = Pc - StartIp;
47*a85da649SXing Xue     p++;
48*a85da649SXing Xue   }
49*a85da649SXing Xue 
50*a85da649SXing Xue   // Skip field hand_mask if it exists.
51*a85da649SXing Xue   if (TBTable->tb.int_hndl)
52*a85da649SXing Xue     p++;
53*a85da649SXing Xue 
54*a85da649SXing Xue   // Skip fields ctl_info and ctl_info_disp if they exist.
55*a85da649SXing Xue   if (TBTable->tb.has_ctl) {
56*a85da649SXing Xue     p += 1 + *p;
57*a85da649SXing Xue   }
58*a85da649SXing Xue 
59*a85da649SXing Xue   NameLen = *(reinterpret_cast<uint16_t *>(p));
60*a85da649SXing Xue   return reinterpret_cast<char *>(p) + sizeof(uint16_t);
61*a85da649SXing Xue }
62*a85da649SXing Xue } // namespace libunwind
63*a85da649SXing Xue #endif // defined(_AIX)
64