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 __arm__ 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%lX)\n", 172 cursor, regNum, (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 __arm__ 205 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llx)\n", cursor, regNum, value); 206 #else 207 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", cursor, regNum, value); 208 #endif 209 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 210 if (co->validFloatReg(regNum)) { 211 co->setFloatReg(regNum, value); 212 return UNW_ESUCCESS; 213 } 214 return UNW_EBADREG; 215 } 216 217 218 /// Move cursor to next frame. 219 _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { 220 _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", cursor); 221 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 222 return co->step(); 223 } 224 225 226 /// Get unwind info at cursor position in stack frame. 227 _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, 228 unw_proc_info_t *info) { 229 _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n", 230 cursor, info); 231 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 232 co->getInfo(info); 233 if (info->end_ip == 0) 234 return UNW_ENOINFO; 235 else 236 return UNW_ESUCCESS; 237 } 238 239 240 /// Resume execution at cursor position (aka longjump). 241 _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { 242 _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", cursor); 243 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 244 co->jumpto(); 245 return UNW_EUNSPEC; 246 } 247 248 249 /// Get name of function at cursor position in stack frame. 250 _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, 251 size_t bufLen, unw_word_t *offset) { 252 _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p," 253 "bufLen=%zu)\n", cursor, buf, bufLen); 254 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 255 if (co->getFunctionName(buf, bufLen, offset)) 256 return UNW_ESUCCESS; 257 else 258 return UNW_EUNSPEC; 259 } 260 261 262 /// Checks if a register is a floating-point register. 263 _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { 264 _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", 265 cursor, regNum); 266 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 267 return co->validFloatReg(regNum); 268 } 269 270 271 /// Checks if a register is a floating-point register. 272 _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, 273 unw_regnum_t regNum) { 274 _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n", 275 cursor, regNum); 276 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 277 return co->getRegisterName(regNum); 278 } 279 280 281 /// Checks if current frame is signal trampoline. 282 _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { 283 _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", cursor); 284 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 285 return co->isSignalFrame(); 286 } 287 288 #if __arm__ 289 // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD 290 _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { 291 _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", cursor); 292 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 293 return co->saveVFPAsX(); 294 } 295 #endif 296 297 298 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 299 /// SPI: walks cached dwarf entries 300 _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( 301 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { 302 _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", func); 303 DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func); 304 } 305 306 307 /// IPI: for __register_frame() 308 void _unw_add_dynamic_fde(unw_word_t fde) { 309 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 310 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 311 const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE( 312 LocalAddressSpace::sThisAddressSpace, 313 (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo); 314 if (message == NULL) { 315 // dynamically registered FDEs don't have a mach_header group they are in. 316 // Use fde as mh_group 317 unw_word_t mh_group = fdeInfo.fdeStart; 318 DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group, 319 fdeInfo.pcStart, fdeInfo.pcEnd, 320 fdeInfo.fdeStart); 321 } else { 322 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message); 323 } 324 } 325 326 /// IPI: for __deregister_frame() 327 void _unw_remove_dynamic_fde(unw_word_t fde) { 328 // fde is own mh_group 329 DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde); 330 } 331 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND 332 333 #endif // _LIBUNWIND_BUILD_ZERO_COST_APIS 334 335 336 337 // Add logging hooks in Debug builds only 338 #ifndef NDEBUG 339 #include <stdlib.h> 340 341 _LIBUNWIND_HIDDEN 342 bool logAPIs() { 343 // do manual lock to avoid use of _cxa_guard_acquire or initializers 344 static bool checked = false; 345 static bool log = false; 346 if (!checked) { 347 log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); 348 checked = true; 349 } 350 return log; 351 } 352 353 _LIBUNWIND_HIDDEN 354 bool logUnwinding() { 355 // do manual lock to avoid use of _cxa_guard_acquire or initializers 356 static bool checked = false; 357 static bool log = false; 358 if (!checked) { 359 log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); 360 checked = true; 361 } 362 return log; 363 } 364 365 #endif // NDEBUG 366 367