1288149Semaste//===--------------------------- libuwind.cpp -----------------------------===// 2288149Semaste// 3288149Semaste// The LLVM Compiler Infrastructure 4288149Semaste// 5288149Semaste// This file is dual licensed under the MIT and the University of Illinois Open 6288149Semaste// Source Licenses. See LICENSE.TXT for details. 7288149Semaste// 8288149Semaste// 9288149Semaste// Implements unw_* functions from <libunwind.h> 10288149Semaste// 11288149Semaste//===----------------------------------------------------------------------===// 12288149Semaste 13288149Semaste#include <libunwind.h> 14288149Semaste 15288149Semaste#ifndef NDEBUG 16288149Semaste#include <cstdlib> // getenv 17288149Semaste#endif 18288149Semaste#include <new> 19288149Semaste#include <algorithm> 20288149Semaste 21288149Semaste#include "libunwind_ext.h" 22288149Semaste#include "config.h" 23288149Semaste 24288149Semaste#include <stdlib.h> 25288149Semaste 26288149Semaste 27288149Semaste#include "UnwindCursor.hpp" 28288149Semaste 29288149Semasteusing namespace libunwind; 30288149Semaste 31288149Semaste/// internal object to represent this processes address space 32288149SemasteLocalAddressSpace LocalAddressSpace::sThisAddressSpace; 33288149Semaste 34288149Semaste_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = 35288149Semaste (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; 36288149Semaste 37288149Semaste/// record the registers and stack position of the caller 38288149Semasteextern int unw_getcontext(unw_context_t *); 39288149Semaste// note: unw_getcontext() implemented in assembly 40288149Semaste 41288149Semaste/// Create a cursor of a thread in this process given 'context' recorded by 42288149Semaste/// unw_getcontext(). 43288149Semaste_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, 44288149Semaste unw_context_t *context) { 45288149Semaste _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n", 46288149Semaste static_cast<void *>(cursor), 47288149Semaste static_cast<void *>(context)); 48288149Semaste#if defined(__i386__) 49303196Semaste# define REGISTER_KIND Registers_x86 50288149Semaste#elif defined(__x86_64__) 51303196Semaste# define REGISTER_KIND Registers_x86_64 52288149Semaste#elif defined(__ppc__) 53303196Semaste# define REGISTER_KIND Registers_ppc 54303196Semaste#elif defined(__aarch64__) 55303196Semaste# define REGISTER_KIND Registers_arm64 56288149Semaste#elif _LIBUNWIND_ARM_EHABI 57303196Semaste# define REGISTER_KIND Registers_arm 58288149Semaste#elif defined(__or1k__) 59303196Semaste# define REGISTER_KIND Registers_or1k 60303196Semaste#elif defined(__riscv__) 61303196Semaste# define REGISTER_KIND Registers_riscv 62293183Semaste#elif defined(__mips__) 63303196Semaste# warning The MIPS architecture is not supported. 64288149Semaste#else 65303196Semaste# error Architecture not supported 66288149Semaste#endif 67303196Semaste // Use "placement new" to allocate UnwindCursor in the cursor buffer. 68303196Semaste new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>( 69303196Semaste context, LocalAddressSpace::sThisAddressSpace); 70303196Semaste#undef REGISTER_KIND 71288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 72288149Semaste co->setInfoBasedOnIPRegister(); 73288149Semaste 74288149Semaste return UNW_ESUCCESS; 75288149Semaste} 76288149Semaste 77288149Semaste#ifdef UNW_REMOTE 78288149Semaste/// Create a cursor into a thread in another process. 79288149Semaste_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, 80288149Semaste unw_addr_space_t as, 81288149Semaste void *arg) { 82288149Semaste // special case: unw_init_remote(xx, unw_local_addr_space, xx) 83288149Semaste if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace) 84288149Semaste return unw_init_local(cursor, NULL); //FIXME 85288149Semaste 86288149Semaste // use "placement new" to allocate UnwindCursor in the cursor buffer 87288149Semaste switch (as->cpuType) { 88288149Semaste case CPU_TYPE_I386: 89288149Semaste new ((void *)cursor) 90288149Semaste UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >, 91288149Semaste Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg); 92288149Semaste break; 93288149Semaste case CPU_TYPE_X86_64: 94288149Semaste new ((void *)cursor) UnwindCursor< 95288149Semaste OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>( 96288149Semaste ((unw_addr_space_x86_64 *)as)->oas, arg); 97288149Semaste break; 98288149Semaste case CPU_TYPE_POWERPC: 99288149Semaste new ((void *)cursor) 100288149Semaste UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>( 101288149Semaste ((unw_addr_space_ppc *)as)->oas, arg); 102288149Semaste break; 103288149Semaste default: 104288149Semaste return UNW_EUNSPEC; 105288149Semaste } 106288149Semaste return UNW_ESUCCESS; 107288149Semaste} 108288149Semaste 109288149Semaste 110288149Semastestatic bool is64bit(task_t task) { 111288149Semaste return false; // FIXME 112288149Semaste} 113288149Semaste 114288149Semaste/// Create an address_space object for use in examining another task. 115288149Semaste_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) { 116288149Semaste#if __i386__ 117288149Semaste if (is64bit(task)) { 118288149Semaste unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task); 119288149Semaste as->taskPort = task; 120288149Semaste as->cpuType = CPU_TYPE_X86_64; 121288149Semaste //as->oas 122288149Semaste } else { 123288149Semaste unw_addr_space_i386 *as = new unw_addr_space_i386(task); 124288149Semaste as->taskPort = task; 125288149Semaste as->cpuType = CPU_TYPE_I386; 126288149Semaste //as->oas 127288149Semaste } 128288149Semaste#else 129288149Semaste// FIXME 130288149Semaste#endif 131288149Semaste} 132288149Semaste 133288149Semaste 134288149Semaste/// Delete an address_space object. 135288149Semaste_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { 136288149Semaste switch (asp->cpuType) { 137288149Semaste#if __i386__ || __x86_64__ 138288149Semaste case CPU_TYPE_I386: { 139288149Semaste unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp; 140288149Semaste delete as; 141288149Semaste } 142288149Semaste break; 143288149Semaste case CPU_TYPE_X86_64: { 144288149Semaste unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp; 145288149Semaste delete as; 146288149Semaste } 147288149Semaste break; 148288149Semaste#endif 149288149Semaste case CPU_TYPE_POWERPC: { 150288149Semaste unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp; 151288149Semaste delete as; 152288149Semaste } 153288149Semaste break; 154288149Semaste } 155288149Semaste} 156288149Semaste#endif // UNW_REMOTE 157288149Semaste 158288149Semaste 159288149Semaste/// Get value of specified register at cursor position in stack frame. 160288149Semaste_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, 161288149Semaste unw_word_t *value) { 162288149Semaste _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", 163288149Semaste static_cast<void *>(cursor), regNum, 164288149Semaste static_cast<void *>(value)); 165288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 166288149Semaste if (co->validReg(regNum)) { 167288149Semaste *value = co->getReg(regNum); 168288149Semaste return UNW_ESUCCESS; 169288149Semaste } 170288149Semaste return UNW_EBADREG; 171288149Semaste} 172288149Semaste 173288149Semaste 174288149Semaste/// Set value of specified register at cursor position in stack frame. 175288149Semaste_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, 176288149Semaste unw_word_t value) { 177288149Semaste _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", 178288149Semaste static_cast<void *>(cursor), regNum, (long long)value); 179288149Semaste typedef LocalAddressSpace::pint_t pint_t; 180288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 181288149Semaste if (co->validReg(regNum)) { 182288149Semaste co->setReg(regNum, (pint_t)value); 183288149Semaste // specical case altering IP to re-find info (being called by personality 184288149Semaste // function) 185288149Semaste if (regNum == UNW_REG_IP) 186288149Semaste co->setInfoBasedOnIPRegister(false); 187288149Semaste return UNW_ESUCCESS; 188288149Semaste } 189288149Semaste return UNW_EBADREG; 190288149Semaste} 191288149Semaste 192288149Semaste 193288149Semaste/// Get value of specified float register at cursor position in stack frame. 194288149Semaste_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, 195288149Semaste unw_fpreg_t *value) { 196288149Semaste _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", 197288149Semaste static_cast<void *>(cursor), regNum, 198288149Semaste static_cast<void *>(value)); 199288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 200288149Semaste if (co->validFloatReg(regNum)) { 201288149Semaste *value = co->getFloatReg(regNum); 202288149Semaste return UNW_ESUCCESS; 203288149Semaste } 204288149Semaste return UNW_EBADREG; 205288149Semaste} 206288149Semaste 207288149Semaste 208288149Semaste/// Set value of specified float register at cursor position in stack frame. 209288149Semaste_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, 210288149Semaste unw_fpreg_t value) { 211288149Semaste#if _LIBUNWIND_ARM_EHABI 212288149Semaste _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n", 213288149Semaste static_cast<void *>(cursor), regNum, value); 214288149Semaste#else 215288149Semaste _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", 216288149Semaste static_cast<void *>(cursor), regNum, value); 217288149Semaste#endif 218288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 219288149Semaste if (co->validFloatReg(regNum)) { 220288149Semaste co->setFloatReg(regNum, value); 221288149Semaste return UNW_ESUCCESS; 222288149Semaste } 223288149Semaste return UNW_EBADREG; 224288149Semaste} 225288149Semaste 226288149Semaste 227288149Semaste/// Move cursor to next frame. 228288149Semaste_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { 229288149Semaste _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor)); 230288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 231288149Semaste return co->step(); 232288149Semaste} 233288149Semaste 234288149Semaste 235288149Semaste/// Get unwind info at cursor position in stack frame. 236288149Semaste_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, 237288149Semaste unw_proc_info_t *info) { 238288149Semaste _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n", 239288149Semaste static_cast<void *>(cursor), static_cast<void *>(info)); 240288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 241288149Semaste co->getInfo(info); 242288149Semaste if (info->end_ip == 0) 243288149Semaste return UNW_ENOINFO; 244288149Semaste else 245288149Semaste return UNW_ESUCCESS; 246288149Semaste} 247288149Semaste 248288149Semaste 249288149Semaste/// Resume execution at cursor position (aka longjump). 250288149Semaste_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { 251288149Semaste _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor)); 252288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 253288149Semaste co->jumpto(); 254288149Semaste return UNW_EUNSPEC; 255288149Semaste} 256288149Semaste 257288149Semaste 258288149Semaste/// Get name of function at cursor position in stack frame. 259288149Semaste_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, 260288149Semaste size_t bufLen, unw_word_t *offset) { 261288149Semaste _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n", 262288149Semaste static_cast<void *>(cursor), static_cast<void *>(buf), 263288149Semaste static_cast<unsigned long>(bufLen)); 264288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 265288149Semaste if (co->getFunctionName(buf, bufLen, offset)) 266288149Semaste return UNW_ESUCCESS; 267288149Semaste else 268288149Semaste return UNW_EUNSPEC; 269288149Semaste} 270288149Semaste 271288149Semaste 272288149Semaste/// Checks if a register is a floating-point register. 273288149Semaste_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { 274288149Semaste _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", 275288149Semaste static_cast<void *>(cursor), regNum); 276288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 277288149Semaste return co->validFloatReg(regNum); 278288149Semaste} 279288149Semaste 280288149Semaste 281288149Semaste/// Checks if a register is a floating-point register. 282288149Semaste_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, 283288149Semaste unw_regnum_t regNum) { 284288149Semaste _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n", 285288149Semaste static_cast<void *>(cursor), regNum); 286288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 287288149Semaste return co->getRegisterName(regNum); 288288149Semaste} 289288149Semaste 290288149Semaste 291288149Semaste/// Checks if current frame is signal trampoline. 292288149Semaste_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { 293288149Semaste _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", 294288149Semaste static_cast<void *>(cursor)); 295288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 296288149Semaste return co->isSignalFrame(); 297288149Semaste} 298288149Semaste 299288149Semaste#ifdef __arm__ 300288149Semaste// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD 301288149Semaste_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { 302288149Semaste _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", 303288149Semaste static_cast<void *>(cursor)); 304288149Semaste AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; 305288149Semaste return co->saveVFPAsX(); 306288149Semaste} 307288149Semaste#endif 308288149Semaste 309288149Semaste 310288149Semaste#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 311288149Semaste/// SPI: walks cached dwarf entries 312288149Semaste_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( 313288149Semaste unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { 314288149Semaste _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", 315288149Semaste reinterpret_cast<void *>(func)); 316288149Semaste DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func); 317288149Semaste} 318288149Semaste 319288149Semaste 320288149Semaste/// IPI: for __register_frame() 321288149Semastevoid _unw_add_dynamic_fde(unw_word_t fde) { 322288149Semaste CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 323288149Semaste CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 324288149Semaste const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE( 325288149Semaste LocalAddressSpace::sThisAddressSpace, 326288149Semaste (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo); 327288149Semaste if (message == NULL) { 328288149Semaste // dynamically registered FDEs don't have a mach_header group they are in. 329288149Semaste // Use fde as mh_group 330288149Semaste unw_word_t mh_group = fdeInfo.fdeStart; 331288149Semaste DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group, 332288149Semaste fdeInfo.pcStart, fdeInfo.pcEnd, 333288149Semaste fdeInfo.fdeStart); 334288149Semaste } else { 335288149Semaste _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message); 336288149Semaste } 337288149Semaste} 338288149Semaste 339288149Semaste/// IPI: for __deregister_frame() 340288149Semastevoid _unw_remove_dynamic_fde(unw_word_t fde) { 341288149Semaste // fde is own mh_group 342288149Semaste DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde); 343288149Semaste} 344288149Semaste#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND 345288149Semaste 346288149Semaste 347288149Semaste 348288149Semaste// Add logging hooks in Debug builds only 349288149Semaste#ifndef NDEBUG 350288149Semaste#include <stdlib.h> 351288149Semaste 352288149Semaste_LIBUNWIND_HIDDEN 353288149Semastebool logAPIs() { 354288149Semaste // do manual lock to avoid use of _cxa_guard_acquire or initializers 355288149Semaste static bool checked = false; 356288149Semaste static bool log = false; 357288149Semaste if (!checked) { 358288149Semaste log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); 359288149Semaste checked = true; 360288149Semaste } 361288149Semaste return log; 362288149Semaste} 363288149Semaste 364288149Semaste_LIBUNWIND_HIDDEN 365288149Semastebool logUnwinding() { 366288149Semaste // do manual lock to avoid use of _cxa_guard_acquire or initializers 367288149Semaste static bool checked = false; 368288149Semaste static bool log = false; 369288149Semaste if (!checked) { 370288149Semaste log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); 371288149Semaste checked = true; 372288149Semaste } 373288149Semaste return log; 374288149Semaste} 375288149Semaste 376288149Semaste#endif // NDEBUG 377288149Semaste 378