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 <android-base/stringprintf.h> 26 27#include <backtrace/Backtrace.h> 28#include <backtrace/BacktraceMap.h> 29 30#include <demangle.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 57std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset, const backtrace_map_t* map) { 58 backtrace_map_t map_value; 59 if (map == nullptr) { 60 FillInMap(pc, &map_value); 61 map = &map_value; 62 } 63 // If no map is found, or this map is backed by a device, then return nothing. 64 if (map->start == 0 || (map->flags & PROT_DEVICE_MAP)) { 65 return ""; 66 } 67 return demangle(GetFunctionNameRaw(pc, offset).c_str()); 68} 69 70bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) { 71 if (ptr & (sizeof(word_t)-1)) { 72 BACK_LOGW("invalid pointer %p", reinterpret_cast<void*>(ptr)); 73 *out_value = static_cast<word_t>(-1); 74 return false; 75 } 76 return true; 77} 78 79std::string Backtrace::FormatFrameData(size_t frame_num) { 80 if (frame_num >= frames_.size()) { 81 return ""; 82 } 83 return FormatFrameData(&frames_[frame_num]); 84} 85 86std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) { 87 std::string map_name; 88 if (BacktraceMap::IsValid(frame->map)) { 89 if (!frame->map.name.empty()) { 90 map_name = frame->map.name.c_str(); 91 if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') { 92 map_name.resize(map_name.size() - 1); 93 map_name += StringPrintf(":%" PRIPTR "]", frame->map.start); 94 } 95 } else { 96 map_name = StringPrintf("<anonymous:%" PRIPTR ">", frame->map.start); 97 } 98 } else { 99 map_name = "<unknown>"; 100 } 101 102 std::string line(StringPrintf("#%02zu pc %" PRIPTR " ", frame->num, frame->rel_pc)); 103 line += map_name; 104 // Special handling for non-zero offset maps, we need to print that 105 // information. 106 if (frame->map.offset != 0) { 107 line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")"; 108 } 109 if (!frame->func_name.empty()) { 110 line += " (" + frame->func_name; 111 if (frame->func_offset) { 112 line += StringPrintf("+%" PRIuPTR, frame->func_offset); 113 } 114 line += ')'; 115 } 116 117 return line; 118} 119 120void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) { 121 if (map_ != nullptr) { 122 map_->FillIn(pc, map); 123 } 124} 125 126Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { 127 if (pid == BACKTRACE_CURRENT_PROCESS) { 128 pid = getpid(); 129 if (tid == BACKTRACE_CURRENT_THREAD) { 130 tid = gettid(); 131 } 132 } else if (tid == BACKTRACE_CURRENT_THREAD) { 133 tid = pid; 134 } 135 136 if (pid == getpid()) { 137 return new UnwindCurrent(pid, tid, map); 138 } else { 139 return new UnwindPtrace(pid, tid, map); 140 } 141} 142 143std::string Backtrace::GetErrorString(BacktraceUnwindError error) { 144 switch (error) { 145 case BACKTRACE_UNWIND_NO_ERROR: 146 return "No error"; 147 case BACKTRACE_UNWIND_ERROR_SETUP_FAILED: 148 return "Setup failed"; 149 case BACKTRACE_UNWIND_ERROR_MAP_MISSING: 150 return "No map found"; 151 case BACKTRACE_UNWIND_ERROR_INTERNAL: 152 return "Internal libbacktrace error, please submit a bugreport"; 153 case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST: 154 return "Thread doesn't exist"; 155 case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT: 156 return "Thread has not responded to signal in time"; 157 case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION: 158 return "Attempt to use an unsupported feature"; 159 case BACKTRACE_UNWIND_ERROR_NO_CONTEXT: 160 return "Attempt to do an offline unwind without a context"; 161 } 162} 163