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