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