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