UnwindPtrace.cpp revision 20303f856f1f1cdb5af58af0b116b8c598f0ea5c
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "libbacktrace" 18 19#include <backtrace/backtrace.h> 20 21#include <sys/types.h> 22#include <string.h> 23 24#include <cutils/log.h> 25 26#include <libunwind.h> 27#include <libunwind-ptrace.h> 28 29#include "UnwindPtrace.h" 30 31UnwindPtrace::UnwindPtrace() : addr_space_(NULL), upt_info_(NULL) { 32} 33 34UnwindPtrace::~UnwindPtrace() { 35 if (upt_info_) { 36 _UPT_destroy(upt_info_); 37 upt_info_ = NULL; 38 } 39 if (addr_space_) { 40 unw_destroy_addr_space(addr_space_); 41 addr_space_ = NULL; 42 } 43} 44 45bool UnwindPtrace::Unwind(size_t num_ignore_frames) { 46 addr_space_ = unw_create_addr_space(&_UPT_accessors, 0); 47 if (!addr_space_) { 48 BACK_LOGW("unw_create_addr_space failed."); 49 return false; 50 } 51 52 upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(backtrace_obj_->Tid())); 53 if (!upt_info_) { 54 BACK_LOGW("Failed to create upt info."); 55 return false; 56 } 57 58 backtrace_t* backtrace = GetBacktraceData(); 59 backtrace->num_frames = 0; 60 61 unw_cursor_t cursor; 62 int ret = unw_init_remote(&cursor, addr_space_, upt_info_); 63 if (ret < 0) { 64 BACK_LOGW("unw_init_remote failed %d", ret); 65 return false; 66 } 67 68 do { 69 unw_word_t pc; 70 ret = unw_get_reg(&cursor, UNW_REG_IP, &pc); 71 if (ret < 0) { 72 BACK_LOGW("Failed to read IP %d", ret); 73 break; 74 } 75 unw_word_t sp; 76 ret = unw_get_reg(&cursor, UNW_REG_SP, &sp); 77 if (ret < 0) { 78 BACK_LOGW("Failed to read SP %d", ret); 79 break; 80 } 81 82 if (num_ignore_frames == 0) { 83 size_t num_frames = backtrace->num_frames; 84 backtrace_frame_data_t* frame = &backtrace->frames[num_frames]; 85 frame->num = num_frames; 86 frame->pc = static_cast<uintptr_t>(pc); 87 frame->sp = static_cast<uintptr_t>(sp); 88 frame->stack_size = 0; 89 frame->map_name = NULL; 90 frame->map_offset = 0; 91 frame->func_name = NULL; 92 frame->func_offset = 0; 93 94 if (num_frames > 0) { 95 backtrace_frame_data_t* prev = &backtrace->frames[num_frames-1]; 96 prev->stack_size = frame->sp - prev->sp; 97 } 98 99 std::string func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset); 100 if (!func_name.empty()) { 101 frame->func_name = strdup(func_name.c_str()); 102 } 103 104 uintptr_t map_start; 105 frame->map_name = backtrace_obj_->GetMapName(frame->pc, &map_start); 106 if (frame->map_name) { 107 frame->map_offset = frame->pc - map_start; 108 } 109 110 backtrace->num_frames++; 111 } else { 112 num_ignore_frames--; 113 } 114 ret = unw_step (&cursor); 115 } while (ret > 0 && backtrace->num_frames < MAX_BACKTRACE_FRAMES); 116 117 return true; 118} 119 120std::string UnwindPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { 121 *offset = 0; 122 char buf[512]; 123 unw_word_t value; 124 if (unw_get_proc_name_by_ip(addr_space_, pc, buf, sizeof(buf), &value, 125 upt_info_) >= 0 && buf[0] != '\0') { 126 *offset = static_cast<uintptr_t>(value); 127 return buf; 128 } 129 return ""; 130} 131 132//------------------------------------------------------------------------- 133// C++ object creation function. 134//------------------------------------------------------------------------- 135Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) { 136 return new BacktracePtrace(new UnwindPtrace(), pid, tid, map_info); 137} 138