Home | History | Annotate | Download | only in Unwind
      1 //===--------------------------- libuwind.cpp -----------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //
      9 //  Implements unw_* functions from <libunwind.h>
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include <libunwind.h>
     14 
     15 #ifndef NDEBUG
     16 #include <cstdlib> // getenv
     17 #endif
     18 #include <new>
     19 #include <tuple>
     20 #include <memory>
     21 #include <vector>
     22 
     23 #include "libunwind_ext.h"
     24 #include "config.h"
     25 
     26 #include <stdlib.h>
     27 
     28 
     29 #if _LIBUNWIND_BUILD_ZERO_COST_APIS
     30 
     31 #include "UnwindCursor.hpp"
     32 
     33 using namespace libunwind;
     34 
     35 /// internal object to represent this processes address space
     36 LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
     37 
     38 _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
     39     (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
     40 
     41 /// record the registers and stack position of the caller
     42 extern int unw_getcontext(unw_context_t *);
     43 // note: unw_getcontext() implemented in assembly
     44 
     45 /// Create a cursor of a thread in this process given 'context' recorded by
     46 /// unw_getcontext().
     47 _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
     48                                      unw_context_t *context) {
     49   _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n",
     50                        static_cast<void *>(cursor),
     51                        static_cast<void *>(context));
     52   // Use "placement new" to allocate UnwindCursor in the cursor buffer.
     53 #if defined(__i386__)
     54   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>(
     55                                  context, LocalAddressSpace::sThisAddressSpace);
     56 #elif defined(__x86_64__)
     57   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
     58                                  context, LocalAddressSpace::sThisAddressSpace);
     59 #elif defined(__ppc__)
     60   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>(
     61                                  context, LocalAddressSpace::sThisAddressSpace);
     62 #elif defined(__arm64__)
     63   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
     64                                  context, LocalAddressSpace::sThisAddressSpace);
     65 #elif LIBCXXABI_ARM_EHABI
     66   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
     67                                  context, LocalAddressSpace::sThisAddressSpace);
     68 #endif
     69   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
     70   co->setInfoBasedOnIPRegister();
     71 
     72   return UNW_ESUCCESS;
     73 }
     74 
     75 #ifdef UNW_REMOTE
     76 /// Create a cursor into a thread in another process.
     77 _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
     78                                              unw_addr_space_t as,
     79                                              void *arg) {
     80   // special case: unw_init_remote(xx, unw_local_addr_space, xx)
     81   if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
     82     return unw_init_local(cursor, NULL); //FIXME
     83 
     84   // use "placement new" to allocate UnwindCursor in the cursor buffer
     85   switch (as->cpuType) {
     86   case CPU_TYPE_I386:
     87     new ((void *)cursor)
     88         UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >,
     89                      Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
     90     break;
     91   case CPU_TYPE_X86_64:
     92     new ((void *)cursor) UnwindCursor<
     93         OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(
     94         ((unw_addr_space_x86_64 *)as)->oas, arg);
     95     break;
     96   case CPU_TYPE_POWERPC:
     97     new ((void *)cursor)
     98         UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>(
     99             ((unw_addr_space_ppc *)as)->oas, arg);
    100     break;
    101   default:
    102     return UNW_EUNSPEC;
    103   }
    104   return UNW_ESUCCESS;
    105 }
    106 
    107 
    108 static bool is64bit(task_t task) {
    109   return false; // FIXME
    110 }
    111 
    112 /// Create an address_space object for use in examining another task.
    113 _LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
    114 #if __i386__
    115   if (is64bit(task)) {
    116     unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
    117     as->taskPort = task;
    118     as->cpuType = CPU_TYPE_X86_64;
    119     //as->oas
    120   } else {
    121     unw_addr_space_i386 *as = new unw_addr_space_i386(task);
    122     as->taskPort = task;
    123     as->cpuType = CPU_TYPE_I386;
    124     //as->oas
    125   }
    126 #else
    127 // FIXME
    128 #endif
    129 }
    130 
    131 
    132 /// Delete an address_space object.
    133 _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
    134   switch (asp->cpuType) {
    135 #if __i386__ || __x86_64__
    136   case CPU_TYPE_I386: {
    137     unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
    138     delete as;
    139   }
    140   break;
    141   case CPU_TYPE_X86_64: {
    142     unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
    143     delete as;
    144   }
    145   break;
    146 #endif
    147   case CPU_TYPE_POWERPC: {
    148     unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
    149     delete as;
    150   }
    151   break;
    152   }
    153 }
    154 #endif // UNW_REMOTE
    155 
    156 
    157 /// Get value of specified register at cursor position in stack frame.
    158 _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
    159                                   unw_word_t *value) {
    160   _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n",
    161                        static_cast<void *>(cursor), regNum,
    162                        static_cast<void *>(value));
    163   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    164   if (co->validReg(regNum)) {
    165     *value = co->getReg(regNum);
    166     return UNW_ESUCCESS;
    167   }
    168   return UNW_EBADREG;
    169 }
    170 
    171 
    172 /// Set value of specified register at cursor position in stack frame.
    173 _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
    174                                   unw_word_t value) {
    175   _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n",
    176                        static_cast<void *>(cursor), regNum, (long long)value);
    177   typedef LocalAddressSpace::pint_t pint_t;
    178   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    179   if (co->validReg(regNum)) {
    180     co->setReg(regNum, (pint_t)value);
    181     // specical case altering IP to re-find info (being called by personality
    182     // function)
    183     if (regNum == UNW_REG_IP)
    184       co->setInfoBasedOnIPRegister(false);
    185     return UNW_ESUCCESS;
    186   }
    187   return UNW_EBADREG;
    188 }
    189 
    190 
    191 /// Get value of specified float register at cursor position in stack frame.
    192 _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
    193                                     unw_fpreg_t *value) {
    194   _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n",
    195                        static_cast<void *>(cursor), regNum,
    196                        static_cast<void *>(value));
    197   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    198   if (co->validFloatReg(regNum)) {
    199     *value = co->getFloatReg(regNum);
    200     return UNW_ESUCCESS;
    201   }
    202   return UNW_EBADREG;
    203 }
    204 
    205 
    206 /// Set value of specified float register at cursor position in stack frame.
    207 _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
    208                                     unw_fpreg_t value) {
    209 #if LIBCXXABI_ARM_EHABI
    210   _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n",
    211                        static_cast<void *>(cursor), regNum, value);
    212 #else
    213   _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n",
    214                        static_cast<void *>(cursor), regNum, value);
    215 #endif
    216   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    217   if (co->validFloatReg(regNum)) {
    218     co->setFloatReg(regNum, value);
    219     return UNW_ESUCCESS;
    220   }
    221   return UNW_EBADREG;
    222 }
    223 
    224 
    225 /// Move cursor to next frame.
    226 _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
    227   _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor));
    228   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    229   return co->step();
    230 }
    231 
    232 
    233 /// Get unwind info at cursor position in stack frame.
    234 _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
    235                                         unw_proc_info_t *info) {
    236   _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n",
    237                        static_cast<void *>(cursor), static_cast<void *>(info));
    238   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    239   co->getInfo(info);
    240   if (info->end_ip == 0)
    241     return UNW_ENOINFO;
    242   else
    243     return UNW_ESUCCESS;
    244 }
    245 
    246 
    247 /// Resume execution at cursor position (aka longjump).
    248 _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
    249   _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor));
    250   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    251   co->jumpto();
    252   return UNW_EUNSPEC;
    253 }
    254 
    255 
    256 /// Get name of function at cursor position in stack frame.
    257 _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
    258                                         size_t bufLen, unw_word_t *offset) {
    259   _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n",
    260                        static_cast<void *>(cursor), static_cast<void *>(buf),
    261                        static_cast<unsigned long>(bufLen));
    262   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    263   if (co->getFunctionName(buf, bufLen, offset))
    264     return UNW_ESUCCESS;
    265   else
    266     return UNW_EUNSPEC;
    267 }
    268 
    269 
    270 /// Checks if a register is a floating-point register.
    271 _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
    272   _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n",
    273                        static_cast<void *>(cursor), regNum);
    274   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    275   return co->validFloatReg(regNum);
    276 }
    277 
    278 
    279 /// Checks if a register is a floating-point register.
    280 _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
    281                                           unw_regnum_t regNum) {
    282   _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n",
    283                        static_cast<void *>(cursor), regNum);
    284   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    285   return co->getRegisterName(regNum);
    286 }
    287 
    288 
    289 /// Checks if current frame is signal trampoline.
    290 _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
    291   _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n",
    292                        static_cast<void *>(cursor));
    293   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    294   return co->isSignalFrame();
    295 }
    296 
    297 #ifdef __arm__
    298 // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
    299 _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
    300   _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n",
    301                        static_cast<void *>(cursor));
    302   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
    303   return co->saveVFPAsX();
    304 }
    305 #endif
    306 
    307 
    308 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
    309 /// SPI: walks cached dwarf entries
    310 _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
    311     unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
    312   _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n",
    313                        reinterpret_cast<void *>(func));
    314   DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
    315 }
    316 
    317 
    318 /// IPI: for __register_frame()
    319 void _unw_add_dynamic_fde(unw_word_t fde) {
    320   CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
    321   CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
    322   const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
    323                            LocalAddressSpace::sThisAddressSpace,
    324                           (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
    325   if (message == NULL) {
    326     // dynamically registered FDEs don't have a mach_header group they are in.
    327     // Use fde as mh_group
    328     unw_word_t mh_group = fdeInfo.fdeStart;
    329     DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
    330                                           fdeInfo.pcStart, fdeInfo.pcEnd,
    331                                           fdeInfo.fdeStart);
    332   } else {
    333     _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
    334   }
    335 }
    336 
    337 /// IPI: for __deregister_frame()
    338 void _unw_remove_dynamic_fde(unw_word_t fde) {
    339   // fde is own mh_group
    340   DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
    341 }
    342 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
    343 
    344 #endif // _LIBUNWIND_BUILD_ZERO_COST_APIS
    345 
    346 
    347 
    348 // Add logging hooks in Debug builds only
    349 #ifndef NDEBUG
    350 #include <stdlib.h>
    351 
    352 _LIBUNWIND_HIDDEN
    353 bool logAPIs() {
    354   // do manual lock to avoid use of _cxa_guard_acquire or initializers
    355   static bool checked = false;
    356   static bool log = false;
    357   if (!checked) {
    358     log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
    359     checked = true;
    360   }
    361   return log;
    362 }
    363 
    364 _LIBUNWIND_HIDDEN
    365 bool logUnwinding() {
    366   // do manual lock to avoid use of _cxa_guard_acquire or initializers
    367   static bool checked = false;
    368   static bool log = false;
    369   if (!checked) {
    370     log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
    371     checked = true;
    372   }
    373   return log;
    374 }
    375 
    376 #endif // NDEBUG
    377 
    378