1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2013 The Android Open Source Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 5bf215546Sopenharmony_ci * you may not use this file except in compliance with the License. 6bf215546Sopenharmony_ci * You may obtain a copy of the License at 7bf215546Sopenharmony_ci * 8bf215546Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 9bf215546Sopenharmony_ci * 10bf215546Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 11bf215546Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 12bf215546Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bf215546Sopenharmony_ci * See the License for the specific language governing permissions and 14bf215546Sopenharmony_ci * limitations under the License. 15bf215546Sopenharmony_ci */ 16bf215546Sopenharmony_ci 17bf215546Sopenharmony_ci#ifndef _BACKTRACE_BACKTRACE_H 18bf215546Sopenharmony_ci#define _BACKTRACE_BACKTRACE_H 19bf215546Sopenharmony_ci 20bf215546Sopenharmony_ci#include <inttypes.h> 21bf215546Sopenharmony_ci#include <stdint.h> 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include <string> 24bf215546Sopenharmony_ci#include <vector> 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include <backtrace/backtrace_constants.h> 27bf215546Sopenharmony_ci#include <backtrace/BacktraceMap.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#if defined(__LP64__) 30bf215546Sopenharmony_ci#define PRIPTR "016" PRIx64 31bf215546Sopenharmony_citypedef uint64_t word_t; 32bf215546Sopenharmony_ci#else 33bf215546Sopenharmony_ci#define PRIPTR "08" PRIx64 34bf215546Sopenharmony_citypedef uint32_t word_t; 35bf215546Sopenharmony_ci#endif 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cienum BacktraceUnwindErrorCode : uint32_t { 38bf215546Sopenharmony_ci BACKTRACE_UNWIND_NO_ERROR, 39bf215546Sopenharmony_ci // Something failed while trying to perform the setup to begin the unwind. 40bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_SETUP_FAILED, 41bf215546Sopenharmony_ci // There is no map information to use with the unwind. 42bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_MAP_MISSING, 43bf215546Sopenharmony_ci // An error occurred that indicates a programming error. 44bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_INTERNAL, 45bf215546Sopenharmony_ci // The thread to unwind has disappeared before the unwind can begin. 46bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, 47bf215546Sopenharmony_ci // The thread to unwind has not responded to a signal in a timely manner. 48bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT, 49bf215546Sopenharmony_ci // Attempt to do an unsupported operation. 50bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION, 51bf215546Sopenharmony_ci // Attempt to do an offline unwind without a context. 52bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_NO_CONTEXT, 53bf215546Sopenharmony_ci // The count of frames exceed MAX_BACKTRACE_FRAMES. 54bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, 55bf215546Sopenharmony_ci // Failed to read memory. 56bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED, 57bf215546Sopenharmony_ci // Failed to read registers. 58bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED, 59bf215546Sopenharmony_ci // Failed to find a function in debug sections. 60bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED, 61bf215546Sopenharmony_ci // Failed to execute dwarf instructions in debug sections. 62bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED, 63bf215546Sopenharmony_ci // Unwind information is incorrect. 64bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_UNWIND_INFO, 65bf215546Sopenharmony_ci // Unwind information stopped due to sp/pc repeating. 66bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_REPEATED_FRAME, 67bf215546Sopenharmony_ci // Unwind information stopped due to invalid elf. 68bf215546Sopenharmony_ci BACKTRACE_UNWIND_ERROR_INVALID_ELF, 69bf215546Sopenharmony_ci}; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistruct BacktraceUnwindError { 72bf215546Sopenharmony_ci enum BacktraceUnwindErrorCode error_code; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci union { 75bf215546Sopenharmony_ci // for BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED 76bf215546Sopenharmony_ci uint64_t addr; 77bf215546Sopenharmony_ci // for BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED 78bf215546Sopenharmony_ci uint64_t regno; 79bf215546Sopenharmony_ci } error_info; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci BacktraceUnwindError() : error_code(BACKTRACE_UNWIND_NO_ERROR) {} 82bf215546Sopenharmony_ci}; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_cistruct backtrace_frame_data_t { 85bf215546Sopenharmony_ci size_t num; // The current fame number. 86bf215546Sopenharmony_ci uint64_t pc; // The absolute pc. 87bf215546Sopenharmony_ci uint64_t rel_pc; // The relative pc. 88bf215546Sopenharmony_ci uint64_t sp; // The top of the stack. 89bf215546Sopenharmony_ci size_t stack_size; // The size of the stack, zero indicate an unknown stack size. 90bf215546Sopenharmony_ci backtrace_map_t map; // The map associated with the given pc. 91bf215546Sopenharmony_ci std::string func_name; // The function name associated with this pc, NULL if not found. 92bf215546Sopenharmony_ci uint64_t func_offset; // pc relative to the start of the function, only valid if func_name is not 93bf215546Sopenharmony_ci // NULL. 94bf215546Sopenharmony_ci}; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_cistruct backtrace_stackinfo_t { 97bf215546Sopenharmony_ci uint64_t start; 98bf215546Sopenharmony_ci uint64_t end; 99bf215546Sopenharmony_ci const uint8_t* data; 100bf215546Sopenharmony_ci}; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cinamespace unwindstack { 103bf215546Sopenharmony_ciclass Regs; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ciclass Backtrace { 107bf215546Sopenharmony_ci public: 108bf215546Sopenharmony_ci enum ArchEnum : uint8_t { 109bf215546Sopenharmony_ci ARCH_ARM, 110bf215546Sopenharmony_ci ARCH_ARM64, 111bf215546Sopenharmony_ci ARCH_X86, 112bf215546Sopenharmony_ci ARCH_X86_64, 113bf215546Sopenharmony_ci }; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci static void SetGlobalElfCache(bool enable); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci // Create the correct Backtrace object based on what is to be unwound. 118bf215546Sopenharmony_ci // If pid < 0 or equals the current pid, then the Backtrace object 119bf215546Sopenharmony_ci // corresponds to the current process. 120bf215546Sopenharmony_ci // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace 121bf215546Sopenharmony_ci // object corresponds to a thread in the current process. 122bf215546Sopenharmony_ci // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a 123bf215546Sopenharmony_ci // different process. 124bf215546Sopenharmony_ci // Tracing a thread in a different process is not supported. 125bf215546Sopenharmony_ci // If map is NULL, then create the map and manage it internally. 126bf215546Sopenharmony_ci // If map is not NULL, the map is still owned by the caller. 127bf215546Sopenharmony_ci static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = nullptr); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci virtual ~Backtrace(); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci // Get the current stack trace and store in the backtrace_ structure. 132bf215546Sopenharmony_ci virtual bool Unwind(size_t num_ignore_frames, void* context = nullptr) = 0; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, 135bf215546Sopenharmony_ci std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, 136bf215546Sopenharmony_ci std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci // Get the function name and offset into the function given the pc. 139bf215546Sopenharmony_ci // If the string is empty, then no valid function name was found, 140bf215546Sopenharmony_ci // or the pc is not in any valid map. 141bf215546Sopenharmony_ci virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset, 142bf215546Sopenharmony_ci const backtrace_map_t* map = nullptr); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci // Fill in the map data associated with the given pc. 145bf215546Sopenharmony_ci virtual void FillInMap(uint64_t pc, backtrace_map_t* map); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci // Read the data at a specific address. 148bf215546Sopenharmony_ci virtual bool ReadWord(uint64_t ptr, word_t* out_value) = 0; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci // Read arbitrary data from a specific address. If a read request would 151bf215546Sopenharmony_ci // span from one map to another, this call only reads up until the end 152bf215546Sopenharmony_ci // of the current map. 153bf215546Sopenharmony_ci // Returns the total number of bytes actually read. 154bf215546Sopenharmony_ci virtual size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) = 0; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci // Create a string representing the formatted line of backtrace information 157bf215546Sopenharmony_ci // for a single frame. 158bf215546Sopenharmony_ci virtual std::string FormatFrameData(size_t frame_num); 159bf215546Sopenharmony_ci static std::string FormatFrameData(const backtrace_frame_data_t* frame); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci pid_t Pid() const { return pid_; } 162bf215546Sopenharmony_ci pid_t Tid() const { return tid_; } 163bf215546Sopenharmony_ci size_t NumFrames() const { return frames_.size(); } 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci const backtrace_frame_data_t* GetFrame(size_t frame_num) { 166bf215546Sopenharmony_ci if (frame_num >= frames_.size()) { 167bf215546Sopenharmony_ci return nullptr; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci return &frames_[frame_num]; 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci typedef std::vector<backtrace_frame_data_t>::iterator iterator; 173bf215546Sopenharmony_ci iterator begin() { return frames_.begin(); } 174bf215546Sopenharmony_ci iterator end() { return frames_.end(); } 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci typedef std::vector<backtrace_frame_data_t>::const_iterator const_iterator; 177bf215546Sopenharmony_ci const_iterator begin() const { return frames_.begin(); } 178bf215546Sopenharmony_ci const_iterator end() const { return frames_.end(); } 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci BacktraceMap* GetMap() { return map_; } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci BacktraceUnwindError GetError() { return error_; } 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci std::string GetErrorString(BacktraceUnwindError error); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci // Set whether to skip frames in libbacktrace/libunwindstack when doing a local unwind. 187bf215546Sopenharmony_ci void SetSkipFrames(bool skip_frames) { skip_frames_ = skip_frames; } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci protected: 190bf215546Sopenharmony_ci Backtrace(pid_t pid, pid_t tid, BacktraceMap* map); 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci // The name returned is not demangled, GetFunctionName() takes care of 193bf215546Sopenharmony_ci // demangling the name. 194bf215546Sopenharmony_ci virtual std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) = 0; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci virtual bool VerifyReadWordArgs(uint64_t ptr, word_t* out_value); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci bool BuildMap(); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci pid_t pid_; 201bf215546Sopenharmony_ci pid_t tid_; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci BacktraceMap* map_; 204bf215546Sopenharmony_ci bool map_shared_; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci std::vector<backtrace_frame_data_t> frames_; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci // Skip frames in libbacktrace/libunwindstack when doing a local unwind. 209bf215546Sopenharmony_ci bool skip_frames_ = true; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci BacktraceUnwindError error_; 212bf215546Sopenharmony_ci}; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci#endif // _BACKTRACE_BACKTRACE_H 215