UnwindCurrent.cpp revision 17e91d44edf5e6476a477a200bcd89d4327358a3
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 <sys/types.h> 20 21#include <cutils/log.h> 22 23#include <backtrace/backtrace.h> 24 25#define UNW_LOCAL_ONLY 26#include <libunwind.h> 27 28#include "UnwindCurrent.h" 29 30#if defined(__arm__) 31 #if !defined(__BIONIC_HAVE_UCONTEXT_T) 32 // The Current version of the Android <signal.h> doesn't define ucontext_t. 33 #include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined. 34 35 // Machine context at the time a signal was raised. 36 typedef struct ucontext { 37 uint32_t uc_flags; 38 struct ucontext* uc_link; 39 stack_t uc_stack; 40 struct sigcontext uc_mcontext; 41 uint32_t uc_sigmask; 42 } ucontext_t; 43 #endif // !__BIONIC_HAVE_UCONTEXT_T 44#endif // defined(__arm__) 45 46//------------------------------------------------------------------------- 47// UnwindCurrent functions. 48//------------------------------------------------------------------------- 49UnwindCurrent::UnwindCurrent() { 50} 51 52UnwindCurrent::~UnwindCurrent() { 53} 54 55bool UnwindCurrent::Unwind(size_t num_ignore_frames) { 56 int ret = unw_getcontext(&context_); 57 if (ret < 0) { 58 ALOGW("UnwindCurrent::Unwind: unw_getcontext failed %d\n", ret); 59 return false; 60 } 61 return UnwindFromContext(num_ignore_frames, true); 62} 63 64std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { 65 *offset = 0; 66 char buf[512]; 67 unw_word_t value; 68 if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf), 69 &value, &context_) >= 0 && buf[0] != '\0') { 70 *offset = static_cast<uintptr_t>(value); 71 return buf; 72 } 73 return ""; 74} 75 76bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { 77 backtrace_t* backtrace = GetBacktraceData(); 78 backtrace->num_frames = 0; 79 80 // The cursor structure is pretty large, do not put it on the stack. 81 unw_cursor_t* cursor = new unw_cursor_t; 82 int ret = unw_init_local(cursor, &context_); 83 if (ret < 0) { 84 ALOGW("UnwindCurrent::UnwindWithContext: unw_init_local failed %d\n", ret); 85 return false; 86 } 87 88 do { 89 unw_word_t pc; 90 ret = unw_get_reg(cursor, UNW_REG_IP, &pc); 91 if (ret < 0) { 92 ALOGW("UnwindCurrent::UnwindWithContext: Failed to read IP %d\n", ret); 93 break; 94 } 95 unw_word_t sp; 96 ret = unw_get_reg(cursor, UNW_REG_SP, &sp); 97 if (ret < 0) { 98 ALOGW("UnwindCurrent::UnwindWithContext: Failed to read SP %d\n", ret); 99 break; 100 } 101 102 if (num_ignore_frames == 0) { 103 size_t num_frames = backtrace->num_frames; 104 backtrace_frame_data_t* frame = &backtrace->frames[num_frames]; 105 frame->pc = static_cast<uintptr_t>(pc); 106 frame->sp = static_cast<uintptr_t>(sp); 107 frame->stack_size = 0; 108 frame->map_name = NULL; 109 frame->map_offset = 0; 110 frame->func_name = NULL; 111 frame->func_offset = 0; 112 113 if (num_frames > 0) { 114 // Set the stack size for the previous frame. 115 backtrace_frame_data_t* prev = &backtrace->frames[num_frames-1]; 116 prev->stack_size = frame->sp - prev->sp; 117 } 118 119 if (resolve) { 120 std::string func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset); 121 if (!func_name.empty()) { 122 frame->func_name = strdup(func_name.c_str()); 123 } 124 125 uintptr_t map_start; 126 frame->map_name = backtrace_obj_->GetMapName(frame->pc, &map_start); 127 if (frame->map_name) { 128 frame->map_offset = frame->pc - map_start; 129 } 130 } 131 132 backtrace->num_frames++; 133 } else { 134 num_ignore_frames--; 135 } 136 ret = unw_step (cursor); 137 } while (ret > 0 && backtrace->num_frames < MAX_BACKTRACE_FRAMES); 138 139 delete cursor; 140 return true; 141} 142 143void UnwindCurrent::ExtractContext(void* sigcontext) { 144 unw_tdep_context_t* context = reinterpret_cast<unw_tdep_context_t*>(&context_); 145 146#if defined(__arm__) 147 const ucontext_t* uc = reinterpret_cast<const ucontext_t*>(sigcontext); 148 149 context->regs[0] = uc->uc_mcontext.arm_r0; 150 context->regs[1] = uc->uc_mcontext.arm_r1; 151 context->regs[2] = uc->uc_mcontext.arm_r2; 152 context->regs[3] = uc->uc_mcontext.arm_r3; 153 context->regs[4] = uc->uc_mcontext.arm_r4; 154 context->regs[5] = uc->uc_mcontext.arm_r5; 155 context->regs[6] = uc->uc_mcontext.arm_r6; 156 context->regs[7] = uc->uc_mcontext.arm_r7; 157 context->regs[8] = uc->uc_mcontext.arm_r8; 158 context->regs[9] = uc->uc_mcontext.arm_r9; 159 context->regs[10] = uc->uc_mcontext.arm_r10; 160 context->regs[11] = uc->uc_mcontext.arm_fp; 161 context->regs[12] = uc->uc_mcontext.arm_ip; 162 context->regs[13] = uc->uc_mcontext.arm_sp; 163 context->regs[14] = uc->uc_mcontext.arm_lr; 164 context->regs[15] = uc->uc_mcontext.arm_pc; 165 166#elif defined(__mips__) 167 168 typedef struct ucontext { 169 uint32_t sp; 170 uint32_t ra; 171 uint32_t pc; 172 } ucontext_t; 173 174 const ucontext_t* uc = (const ucontext_t*)sigcontext; 175 176 context->uc_mcontext.sp = uc->sp; 177 context->uc_mcontext.pc = uc->pc; 178 context->uc_mcontext.ra = uc->ra; 179#elif defined(__x86__) 180 181 #include <asm/sigcontext.h> 182 #include <asm/ucontext.h> 183 typedef struct ucontext ucontext_t; 184 185 const ucontext_t* uc = (const ucontext_t*)sigcontext; 186 187 context->uc_mcontext.gregs[REG_EBP] = uc->uc_mcontext.gregs[REG_EBP]; 188 context->uc_mcontext.gregs[REG_ESP] = uc->uc_mcontext.gregs[REG_ESP]; 189 context->uc_mcontext.gregs[REG_EIP] = uc->uc_mcontext.gregs[REG_EIP]; 190#endif 191} 192 193//------------------------------------------------------------------------- 194// UnwindThread functions. 195//------------------------------------------------------------------------- 196UnwindThread::UnwindThread() { 197} 198 199UnwindThread::~UnwindThread() { 200} 201 202bool UnwindThread::Init() { 203 return true; 204} 205 206void UnwindThread::ThreadUnwind( 207 siginfo_t* /*siginfo*/, void* sigcontext, size_t num_ignore_frames) { 208 ExtractContext(sigcontext); 209 UnwindFromContext(num_ignore_frames, false); 210} 211 212//------------------------------------------------------------------------- 213// C++ object creation function. 214//------------------------------------------------------------------------- 215Backtrace* CreateCurrentObj() { 216 return new BacktraceCurrent(new UnwindCurrent()); 217} 218 219Backtrace* CreateThreadObj(pid_t tid) { 220 UnwindThread* thread_obj = new UnwindThread(); 221 return new BacktraceThread(thread_obj, thread_obj, tid); 222} 223