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