xref: /freebsd-src/contrib/llvm-project/libunwind/src/Unwind_AIXExtras.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //===--------------------- Unwind_AIXExtras.cpp -------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //
881ad6265SDimitry Andric //===----------------------------------------------------------------------===//
981ad6265SDimitry Andric 
1081ad6265SDimitry Andric // This file is only used for AIX.
1181ad6265SDimitry Andric #if defined(_AIX)
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include "config.h"
1481ad6265SDimitry Andric #include "libunwind_ext.h"
1581ad6265SDimitry Andric #include <sys/debug.h>
1681ad6265SDimitry Andric 
1781ad6265SDimitry Andric namespace libunwind {
1881ad6265SDimitry Andric // getFuncNameFromTBTable
1981ad6265SDimitry Andric // Get the function name from its traceback table.
getFuncNameFromTBTable(uintptr_t Pc,uint16_t & NameLen,unw_word_t * Offset)2081ad6265SDimitry Andric char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
2181ad6265SDimitry Andric                              unw_word_t *Offset) {
2281ad6265SDimitry Andric   uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
2381ad6265SDimitry Andric   *Offset = 0;
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric   // Keep looking forward until a word of 0 is found. The traceback
2681ad6265SDimitry Andric   // table starts at the following word.
2781ad6265SDimitry Andric   while (*p)
2881ad6265SDimitry Andric     p++;
2981ad6265SDimitry Andric   tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
3081ad6265SDimitry Andric 
3181ad6265SDimitry Andric   if (!TBTable->tb.name_present)
3281ad6265SDimitry Andric     return NULL;
3381ad6265SDimitry Andric 
3481ad6265SDimitry Andric   // Get to the name of the function.
3581ad6265SDimitry Andric   p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
3681ad6265SDimitry Andric 
3781ad6265SDimitry Andric   // Skip field parminfo if it exists.
3881ad6265SDimitry Andric   if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
3981ad6265SDimitry Andric     p++;
4081ad6265SDimitry Andric 
41*bdd1243dSDimitry Andric   // If the tb_offset field exists, get the offset from the start of
4281ad6265SDimitry Andric   // the function to pc. Skip the field.
4381ad6265SDimitry Andric   if (TBTable->tb.has_tboff) {
4481ad6265SDimitry Andric     unw_word_t StartIp =
4581ad6265SDimitry Andric         reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
4681ad6265SDimitry Andric     *Offset = Pc - StartIp;
4781ad6265SDimitry Andric     p++;
4881ad6265SDimitry Andric   }
4981ad6265SDimitry Andric 
5081ad6265SDimitry Andric   // Skip field hand_mask if it exists.
5181ad6265SDimitry Andric   if (TBTable->tb.int_hndl)
5281ad6265SDimitry Andric     p++;
5381ad6265SDimitry Andric 
5481ad6265SDimitry Andric   // Skip fields ctl_info and ctl_info_disp if they exist.
5581ad6265SDimitry Andric   if (TBTable->tb.has_ctl) {
5681ad6265SDimitry Andric     p += 1 + *p;
5781ad6265SDimitry Andric   }
5881ad6265SDimitry Andric 
5981ad6265SDimitry Andric   NameLen = *(reinterpret_cast<uint16_t *>(p));
6081ad6265SDimitry Andric   return reinterpret_cast<char *>(p) + sizeof(uint16_t);
6181ad6265SDimitry Andric }
6281ad6265SDimitry Andric } // namespace libunwind
6381ad6265SDimitry Andric #endif // defined(_AIX)
64