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#include <inttypes.h> 18#include <stdint.h> 19#include <stdlib.h> 20#include <sys/types.h> 21#include <ucontext.h> 22 23#include <string> 24 25#include <base/stringprintf.h> 26 27#include <backtrace/Backtrace.h> 28#include <backtrace/BacktraceMap.h> 29 30#include <cutils/threads.h> 31 32#include "BacktraceLog.h" 33#include "thread_utils.h" 34#include "UnwindCurrent.h" 35#include "UnwindPtrace.h" 36 37using android::base::StringPrintf; 38 39//------------------------------------------------------------------------- 40// Backtrace functions. 41//------------------------------------------------------------------------- 42Backtrace::Backtrace(pid_t pid, pid_t tid, BacktraceMap* map) 43 : pid_(pid), tid_(tid), map_(map), map_shared_(true) { 44 if (map_ == nullptr) { 45 map_ = BacktraceMap::Create(pid); 46 map_shared_ = false; 47 } 48} 49 50Backtrace::~Backtrace() { 51 if (map_ && !map_shared_) { 52 delete map_; 53 map_ = nullptr; 54 } 55} 56 57extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len, 58 int* status); 59 60std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { 61 std::string func_name = GetFunctionNameRaw(pc, offset); 62 if (!func_name.empty()) { 63#if defined(__APPLE__) 64 // Mac OS' __cxa_demangle demangles "f" as "float"; last tested on 10.7. 65 if (func_name[0] != '_') { 66 return func_name; 67 } 68#endif 69 char* name = __cxa_demangle(func_name.c_str(), 0, 0, 0); 70 if (name) { 71 func_name = name; 72 free(name); 73 } 74 } 75 return func_name; 76} 77 78bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) { 79 if (ptr & (sizeof(word_t)-1)) { 80 BACK_LOGW("invalid pointer %p", reinterpret_cast<void*>(ptr)); 81 *out_value = static_cast<word_t>(-1); 82 return false; 83 } 84 return true; 85} 86 87std::string Backtrace::FormatFrameData(size_t frame_num) { 88 if (frame_num >= frames_.size()) { 89 return ""; 90 } 91 return FormatFrameData(&frames_[frame_num]); 92} 93 94std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) { 95 const char* map_name; 96 if (BacktraceMap::IsValid(frame->map) && !frame->map.name.empty()) { 97 map_name = frame->map.name.c_str(); 98 } else { 99 map_name = "<unknown>"; 100 } 101 102 uintptr_t relative_pc = BacktraceMap::GetRelativePc(frame->map, frame->pc); 103 104 std::string line(StringPrintf("#%02zu pc %" PRIPTR " %s", frame->num, relative_pc, map_name)); 105 // Special handling for non-zero offset maps, we need to print that 106 // information. 107 if (frame->map.offset != 0) { 108 line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")"; 109 } 110 if (!frame->func_name.empty()) { 111 line += " (" + frame->func_name; 112 if (frame->func_offset) { 113 line += StringPrintf("+%" PRIuPTR, frame->func_offset); 114 } 115 line += ')'; 116 } 117 118 return line; 119} 120 121void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) { 122 if (map_ != nullptr) { 123 map_->FillIn(pc, map); 124 } 125} 126 127Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { 128 if (pid == BACKTRACE_CURRENT_PROCESS) { 129 pid = getpid(); 130 if (tid == BACKTRACE_CURRENT_THREAD) { 131 tid = gettid(); 132 } 133 } else if (tid == BACKTRACE_CURRENT_THREAD) { 134 tid = pid; 135 } 136 137 if (pid == getpid()) { 138 return new UnwindCurrent(pid, tid, map); 139 } else { 140 return new UnwindPtrace(pid, tid, map); 141 } 142} 143