diff --git a/libunwind/src/UnwindLevel1-gcc-ext.c b/libunwind/src/UnwindLevel1-gcc-ext.c --- a/libunwind/src/UnwindLevel1-gcc-ext.c +++ b/libunwind/src/UnwindLevel1-gcc-ext.c @@ -22,6 +22,10 @@ #include "Unwind-EHABI.h" #include "unwind.h" +#if defined(_AIX) +#include +#endif + #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) @@ -82,6 +86,32 @@ /// specified code address "pc". _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); +#if defined(_AIX) + if (pc == NULL) + return NULL; + + // Get the start address of the enclosing function from the function's + // traceback table. + uint32_t *p = (uint32_t *)pc; + + // Keep looking forward until a word of 0 is found. The traceback + // table starts at the following word. + while (*p) + ++p; + struct tbtable *TBTable = (struct tbtable *)(p + 1); + + // Get the address of the traceback table extension. + p = (uint32_t *)&TBTable->tb_ext; + + // Skip field parminfo if it exists. + if (TBTable->tb.fixedparms || TBTable->tb.floatparms) + ++p; + + if (TBTable->tb.has_tboff) + // *p contains the offset from the function start to traceback table. + return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t)); + return NULL; +#else // This is slow, but works. // We create an unwind cursor then alter the IP to be pc unw_cursor_t cursor; @@ -94,6 +124,7 @@ return (void *)(intptr_t) info.start_ip; else return NULL; +#endif } /// Walk every frame and call trace function at each one. If trace function diff --git a/libunwind/src/Unwind_AIXExtras.cpp b/libunwind/src/Unwind_AIXExtras.cpp --- a/libunwind/src/Unwind_AIXExtras.cpp +++ b/libunwind/src/Unwind_AIXExtras.cpp @@ -38,7 +38,7 @@ if (TBTable->tb.fixedparms || TBTable->tb.floatparms) p++; - // If the tb_offset field exisits, get the offset from the start of + // If the tb_offset field exists, get the offset from the start of // the function to pc. Skip the field. if (TBTable->tb.has_tboff) { unw_word_t StartIp =