Skip to content

Commit

Permalink
[libunwind][AIX] implementation of the unwinder for AIX
Browse files Browse the repository at this point in the history
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
  • Loading branch information
xingxue-ibm committed Apr 13, 2022
1 parent 0424b51 commit a85da64
Show file tree
Hide file tree
Showing 15 changed files with 848 additions and 81 deletions.
3 changes: 3 additions & 0 deletions libunwind/include/libunwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
#endif

#ifdef _AIX
extern uintptr_t unw_get_data_rel_base(unw_cursor_t *) LIBUNWIND_AVAIL;
#endif

extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
Expand Down
2 changes: 1 addition & 1 deletion libunwind/include/unwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
extern void *_Unwind_FindEnclosingFunction(void *pc);

// Mac OS X does not support text-rel and data-rel addressing so these functions
// are unimplemented
// are unimplemented.
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
LIBUNWIND_UNAVAIL;
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
Expand Down
30 changes: 24 additions & 6 deletions libunwind/src/AddressSpace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
#include "Registers.hpp"

#ifndef _LIBUNWIND_USE_DLADDR
#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
#define _LIBUNWIND_USE_DLADDR 1
#else
#define _LIBUNWIND_USE_DLADDR 0
#endif
#if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX))
#define _LIBUNWIND_USE_DLADDR 1
#else
#define _LIBUNWIND_USE_DLADDR 0
#endif
#endif

#if _LIBUNWIND_USE_DLADDR
Expand All @@ -45,6 +45,13 @@ struct EHABIIndexEntry {
};
#endif

#if defined(_AIX)
namespace libunwind {
char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen,
unw_word_t *offset);
}
#endif

#ifdef __APPLE__

struct dyld_unwind_sections
Expand Down Expand Up @@ -580,6 +587,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
(void)targetAddr;
(void)info;
return true;
#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
// The traceback table is used for unwinding.
(void)targetAddr;
(void)info;
return true;
#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
int length = 0;
info.arm_section =
Expand All @@ -596,7 +608,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
return false;
}


inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
// TO DO: if OS has way to dynamically register FDEs, check that.
(void)targetAddr;
Expand All @@ -616,6 +627,13 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
return true;
}
}
#elif defined(_AIX)
uint16_t nameLen;
char *funcName = getFuncNameFromTBTable(addr, nameLen, offset);
if (funcName != NULL) {
snprintf(buf, bufLen, "%.*s", nameLen, funcName);
return true;
}
#else
(void)addr;
(void)buf;
Expand Down
12 changes: 11 additions & 1 deletion libunwind/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ if(APPLE)
)
endif()

if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
list(APPEND LIBUNWIND_CXX_SOURCES
Unwind_AIXExtras.cpp
)
endif()

set(LIBUNWIND_C_SOURCES
UnwindLevel1.c
UnwindLevel1-gcc-ext.c
Expand All @@ -26,7 +32,11 @@ set(LIBUNWIND_ASM_SOURCES
)

# See add_asm_sources() in compiler-rt for explanation of this workaround.
if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR (MINGW AND CMAKE_VERSION VERSION_LESS 3.17))
# CMake doesn't work correctly with assembly on AIX. Workaround by compiling
# as C files as well.
if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR
(MINGW AND CMAKE_VERSION VERSION_LESS 3.17) OR
(${CMAKE_SYSTEM_NAME} MATCHES "AIX"))
set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C)
endif()

Expand Down
4 changes: 4 additions & 0 deletions libunwind/src/Registers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc {
void setSP(uint32_t value) { _registers.__r1 = value; }
uint64_t getIP() const { return _registers.__srr0; }
void setIP(uint32_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; }
void setCR(uint32_t value) { _registers.__cr = value; }

private:
struct ppc_thread_state_t {
Expand Down Expand Up @@ -1175,6 +1177,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 {
void setSP(uint64_t value) { _registers.__r1 = value; }
uint64_t getIP() const { return _registers.__srr0; }
void setIP(uint64_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; }
void setCR(uint64_t value) { _registers.__cr = value; }

private:
struct ppc64_thread_state_t {
Expand Down
Loading

0 comments on commit a85da64

Please sign in to comment.