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