bool UnwindPtrace::Init() { if (upt_info_) { return true; } if (addr_space_) { // If somehow the addr_space_ gets initialized but upt_info_ doesn't, // then that indicates there is some kind of failure. return false; } addr_space_ = unw_create_addr_space(&_UPT_accessors, 0); if (!addr_space_) { BACK_LOGW("unw_create_addr_space failed."); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } UnwindMap* map = static_cast<UnwindMap*>(GetMap()); unw_map_set(addr_space_, map->GetMapCursor()); upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid())); if (!upt_info_) { BACK_LOGW("Failed to create upt info."); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } return true; }
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { if (ucontext) { BACK_LOGW("Unwinding from a specified context not supported yet."); return false; } addr_space_ = unw_create_addr_space(&_UPT_accessors, 0); if (!addr_space_) { BACK_LOGW("unw_create_addr_space failed."); return false; } UnwindMap* map = static_cast<UnwindMap*>(GetMap()); if (NULL == map) { BACK_LOGW("GetMap before unwinding failed."); return false; } unw_map_set(addr_space_, map->GetMapCursor()); upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid())); if (!upt_info_) { BACK_LOGW("Failed to create upt info."); return false; } unw_cursor_t cursor; if(num_ignore_frames==0xdeaddead) { cursor.opaque[0]=0xdeaddead; //add for tell libunwind to unwind for kernel unwind userspace backtrace,lhd BACK_LOGW(" K2U_bt call into UnwindPtrace::Unwind."); num_ignore_frames=0; } int ret = unw_init_remote(&cursor, addr_space_, upt_info_); if (ret < 0) { BACK_LOGW("unw_init_remote failed %d", ret); return false; } std::vector<backtrace_frame_data_t>* frames = GetFrames(); frames->reserve(MAX_BACKTRACE_FRAMES); size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(&cursor, UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(&cursor, UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } if (num_ignore_frames == 0) { frames->resize(num_frames+1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; if (num_frames > 0) { backtrace_frame_data_t* prev = &frames->at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); frame->map = FindMap(frame->pc); num_frames++; } else { num_ignore_frames--; } ret = unw_step (&cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); return true; }
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { if (GetMap() == nullptr) { // Without a map object, we can't do anything. return false; } if (ucontext) { BACK_LOGW("Unwinding from a specified context not supported yet."); return false; } addr_space_ = unw_create_addr_space(&_UPT_accessors, 0); if (!addr_space_) { BACK_LOGW("unw_create_addr_space failed."); return false; } UnwindMap* map = static_cast<UnwindMap*>(GetMap()); unw_map_set(addr_space_, map->GetMapCursor()); upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid())); if (!upt_info_) { BACK_LOGW("Failed to create upt info."); return false; } unw_cursor_t cursor; int ret = unw_init_remote(&cursor, addr_space_, upt_info_); if (ret < 0) { BACK_LOGW("unw_init_remote failed %d", ret); return false; } size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(&cursor, UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(&cursor, UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } if (num_ignore_frames == 0) { frames_.resize(num_frames+1); backtrace_frame_data_t* frame = &frames_.at(num_frames); frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; if (num_frames > 0) { backtrace_frame_data_t* prev = &frames_.at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); FillInMap(frame->pc, &frame->map); num_frames++; } else { num_ignore_frames--; } ret = unw_step (&cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); return true; }