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