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 <algorithm> 20 21 #include "libunwind_ext.h" 22 #include "config.h" 23 24 #include <stdlib.h> 25 26 27 #include "UnwindCursor.hpp" 28 29 using namespace libunwind; 30 31 /// internal object to represent this processes address space 32 LocalAddressSpace LocalAddressSpace::sThisAddressSpace; 33 34 _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = 35 (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; 36 37 /// record the registers and stack position of the caller 38 extern int unw_getcontext(unw_context_t *); 39 // note: unw_getcontext() implemented in assembly 40 41 /// Create a cursor of a thread in this process given 'context' recorded by 42 /// unw_getcontext(). 43 _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, 44 unw_context_t *context) { 45 _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n", 46 static_cast<void *>(cursor), 47 static_cast<void *>(context)); 48 // Use "placement new" to allocate UnwindCursor in the cursor buffer. 49 #if defined(__i386__) 50 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>( 51 context, LocalAddressSpace::sThisAddressSpace); 52 #elif defined(__x86_64__) 53 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>( 54 context, LocalAddressSpace::sThisAddressSpace); 55 #elif defined(__ppc__) 56 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>( 57 context, LocalAddressSpace::sThisAddressSpace); 58 #elif defined(__arm64__) || defined(__aarch64__) 59 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>( 60 context, LocalAddressSpace::sThisAddressSpace); 61 #elif _LIBUNWIND_ARM_EHABI 62 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>( 63 context, LocalAddressSpace::sThisAddressSpace); 64 #elif defined(__or1k__) 65 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_or1k>( 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