1*eb293b8fSAndroid Build Coastguard Worker /* 2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project 3*eb293b8fSAndroid Build Coastguard Worker * 4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*eb293b8fSAndroid Build Coastguard Worker * 8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*eb293b8fSAndroid Build Coastguard Worker * 10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License. 15*eb293b8fSAndroid Build Coastguard Worker */ 16*eb293b8fSAndroid Build Coastguard Worker 17*eb293b8fSAndroid Build Coastguard Worker #pragma once 18*eb293b8fSAndroid Build Coastguard Worker 19*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h> 20*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h> 21*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h> 22*eb293b8fSAndroid Build Coastguard Worker 23*eb293b8fSAndroid Build Coastguard Worker #include <memory> 24*eb293b8fSAndroid Build Coastguard Worker #include <mutex> 25*eb293b8fSAndroid Build Coastguard Worker #include <optional> 26*eb293b8fSAndroid Build Coastguard Worker #include <string> 27*eb293b8fSAndroid Build Coastguard Worker #include <utility> 28*eb293b8fSAndroid Build Coastguard Worker #include <vector> 29*eb293b8fSAndroid Build Coastguard Worker 30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Arch.h> 31*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DexFiles.h> 32*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Error.h> 33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/JitDebug.h> 34*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h> 35*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h> 36*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h> 37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/SharedString.h> 38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h> 39*eb293b8fSAndroid Build Coastguard Worker 40*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack { 41*eb293b8fSAndroid Build Coastguard Worker 42*eb293b8fSAndroid Build Coastguard Worker struct AndroidUnwinderData { 43*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinderData() = default; AndroidUnwinderDataAndroidUnwinderData44*eb293b8fSAndroid Build Coastguard Worker explicit AndroidUnwinderData(const size_t max_frames) : max_frames(max_frames) {} AndroidUnwinderDataAndroidUnwinderData45*eb293b8fSAndroid Build Coastguard Worker explicit AndroidUnwinderData(const bool show_all_frames) : show_all_frames(show_all_frames) {} 46*eb293b8fSAndroid Build Coastguard Worker 47*eb293b8fSAndroid Build Coastguard Worker void DemangleFunctionNames(); 48*eb293b8fSAndroid Build Coastguard Worker 49*eb293b8fSAndroid Build Coastguard Worker std::string GetErrorString(); 50*eb293b8fSAndroid Build Coastguard Worker 51*eb293b8fSAndroid Build Coastguard Worker std::vector<FrameData> frames; 52*eb293b8fSAndroid Build Coastguard Worker ErrorData error; 53*eb293b8fSAndroid Build Coastguard Worker std::optional<std::unique_ptr<Regs>> saved_initial_regs; 54*eb293b8fSAndroid Build Coastguard Worker const std::optional<size_t> max_frames; 55*eb293b8fSAndroid Build Coastguard Worker const bool show_all_frames = false; 56*eb293b8fSAndroid Build Coastguard Worker }; 57*eb293b8fSAndroid Build Coastguard Worker 58*eb293b8fSAndroid Build Coastguard Worker class AndroidUnwinder { 59*eb293b8fSAndroid Build Coastguard Worker public: AndroidUnwinder(pid_t pid)60*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder(pid_t pid) : pid_(pid) {} AndroidUnwinder(pid_t pid,std::shared_ptr<Memory> & memory)61*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder(pid_t pid, std::shared_ptr<Memory>& memory) 62*eb293b8fSAndroid Build Coastguard Worker : pid_(pid), process_memory_(memory) {} AndroidUnwinder(pid_t pid,ArchEnum arch)63*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder(pid_t pid, ArchEnum arch) : pid_(pid), arch_(arch) {} AndroidUnwinder(pid_t pid,const std::vector<std::string> initial_map_names_to_skip)64*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip) 65*eb293b8fSAndroid Build Coastguard Worker : pid_(pid), initial_map_names_to_skip_(std::move(initial_map_names_to_skip)) {} AndroidUnwinder(pid_t pid,const std::vector<std::string> initial_map_names_to_skip,const std::vector<std::string> map_suffixes_to_ignore)66*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip, 67*eb293b8fSAndroid Build Coastguard Worker const std::vector<std::string> map_suffixes_to_ignore) 68*eb293b8fSAndroid Build Coastguard Worker : pid_(pid), 69*eb293b8fSAndroid Build Coastguard Worker initial_map_names_to_skip_(std::move(initial_map_names_to_skip)), 70*eb293b8fSAndroid Build Coastguard Worker map_suffixes_to_ignore_(std::move(map_suffixes_to_ignore)) {} 71*eb293b8fSAndroid Build Coastguard Worker virtual ~AndroidUnwinder() = default; 72*eb293b8fSAndroid Build Coastguard Worker 73*eb293b8fSAndroid Build Coastguard Worker bool Initialize(ErrorData& error); 74*eb293b8fSAndroid Build Coastguard Worker GetProcessMemory()75*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; } GetMaps()76*eb293b8fSAndroid Build Coastguard Worker unwindstack::Maps* GetMaps() { return maps_.get(); } 77*eb293b8fSAndroid Build Coastguard Worker GetJitDebug()78*eb293b8fSAndroid Build Coastguard Worker const JitDebug& GetJitDebug() { return *jit_debug_.get(); } GetDexFiles()79*eb293b8fSAndroid Build Coastguard Worker const DexFiles& GetDexFiles() { return *dex_files_.get(); } 80*eb293b8fSAndroid Build Coastguard Worker 81*eb293b8fSAndroid Build Coastguard Worker std::string FormatFrame(const FrameData& frame) const; 82*eb293b8fSAndroid Build Coastguard Worker 83*eb293b8fSAndroid Build Coastguard Worker bool Unwind(AndroidUnwinderData& data); 84*eb293b8fSAndroid Build Coastguard Worker bool Unwind(std::optional<pid_t> tid, AndroidUnwinderData& data); 85*eb293b8fSAndroid Build Coastguard Worker bool Unwind(void* ucontext, AndroidUnwinderData& data); 86*eb293b8fSAndroid Build Coastguard Worker bool Unwind(Regs* initial_regs, AndroidUnwinderData& data); 87*eb293b8fSAndroid Build Coastguard Worker 88*eb293b8fSAndroid Build Coastguard Worker FrameData BuildFrameFromPcOnly(uint64_t pc); 89*eb293b8fSAndroid Build Coastguard Worker 90*eb293b8fSAndroid Build Coastguard Worker static AndroidUnwinder* Create(pid_t pid); 91*eb293b8fSAndroid Build Coastguard Worker 92*eb293b8fSAndroid Build Coastguard Worker protected: 93*eb293b8fSAndroid Build Coastguard Worker virtual bool InternalInitialize(ErrorData& error) = 0; 94*eb293b8fSAndroid Build Coastguard Worker 95*eb293b8fSAndroid Build Coastguard Worker virtual bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) = 0; 96*eb293b8fSAndroid Build Coastguard Worker 97*eb293b8fSAndroid Build Coastguard Worker pid_t pid_; 98*eb293b8fSAndroid Build Coastguard Worker 99*eb293b8fSAndroid Build Coastguard Worker size_t max_frames_ = kMaxNumFrames; 100*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> initial_map_names_to_skip_; 101*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> map_suffixes_to_ignore_; 102*eb293b8fSAndroid Build Coastguard Worker std::once_flag initialize_; 103*eb293b8fSAndroid Build Coastguard Worker bool initialize_status_ = false; 104*eb293b8fSAndroid Build Coastguard Worker 105*eb293b8fSAndroid Build Coastguard Worker ArchEnum arch_ = ARCH_UNKNOWN; 106*eb293b8fSAndroid Build Coastguard Worker 107*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Maps> maps_; 108*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> process_memory_; 109*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<JitDebug> jit_debug_; 110*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<DexFiles> dex_files_; 111*eb293b8fSAndroid Build Coastguard Worker 112*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMaxNumFrames = 512; 113*eb293b8fSAndroid Build Coastguard Worker }; 114*eb293b8fSAndroid Build Coastguard Worker 115*eb293b8fSAndroid Build Coastguard Worker class AndroidLocalUnwinder : public AndroidUnwinder { 116*eb293b8fSAndroid Build Coastguard Worker public: AndroidLocalUnwinder()117*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder() : AndroidUnwinder(getpid()) { 118*eb293b8fSAndroid Build Coastguard Worker initial_map_names_to_skip_.emplace_back(kUnwindstackLib); 119*eb293b8fSAndroid Build Coastguard Worker } AndroidLocalUnwinder(std::shared_ptr<Memory> & process_memory)120*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder(std::shared_ptr<Memory>& process_memory) 121*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(getpid(), process_memory) { 122*eb293b8fSAndroid Build Coastguard Worker initial_map_names_to_skip_.emplace_back(kUnwindstackLib); 123*eb293b8fSAndroid Build Coastguard Worker } AndroidLocalUnwinder(const std::vector<std::string> & initial_map_names_to_skip)124*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip) 125*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(getpid(), initial_map_names_to_skip) { 126*eb293b8fSAndroid Build Coastguard Worker initial_map_names_to_skip_.emplace_back(kUnwindstackLib); 127*eb293b8fSAndroid Build Coastguard Worker } AndroidLocalUnwinder(const std::vector<std::string> & initial_map_names_to_skip,const std::vector<std::string> & map_suffixes_to_ignore)128*eb293b8fSAndroid Build Coastguard Worker AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip, 129*eb293b8fSAndroid Build Coastguard Worker const std::vector<std::string>& map_suffixes_to_ignore) 130*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(getpid(), initial_map_names_to_skip, map_suffixes_to_ignore) { 131*eb293b8fSAndroid Build Coastguard Worker initial_map_names_to_skip_.emplace_back(kUnwindstackLib); 132*eb293b8fSAndroid Build Coastguard Worker } 133*eb293b8fSAndroid Build Coastguard Worker virtual ~AndroidLocalUnwinder() = default; 134*eb293b8fSAndroid Build Coastguard Worker 135*eb293b8fSAndroid Build Coastguard Worker protected: 136*eb293b8fSAndroid Build Coastguard Worker static constexpr const char* kUnwindstackLib = "libunwindstack.so"; 137*eb293b8fSAndroid Build Coastguard Worker 138*eb293b8fSAndroid Build Coastguard Worker bool InternalInitialize(ErrorData& error) override; 139*eb293b8fSAndroid Build Coastguard Worker 140*eb293b8fSAndroid Build Coastguard Worker bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override; 141*eb293b8fSAndroid Build Coastguard Worker }; 142*eb293b8fSAndroid Build Coastguard Worker 143*eb293b8fSAndroid Build Coastguard Worker class AndroidRemoteUnwinder : public AndroidUnwinder { 144*eb293b8fSAndroid Build Coastguard Worker public: AndroidRemoteUnwinder(pid_t pid)145*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder(pid_t pid) : AndroidUnwinder(pid) {} AndroidRemoteUnwinder(pid_t pid,std::shared_ptr<Memory> & process_memory)146*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder(pid_t pid, std::shared_ptr<Memory>& process_memory) 147*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(pid, process_memory) {} AndroidRemoteUnwinder(pid_t pid,ArchEnum arch)148*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder(pid_t pid, ArchEnum arch) : AndroidUnwinder(pid, arch) {} AndroidRemoteUnwinder(pid_t pid,const std::vector<std::string> initial_map_names_to_skip)149*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip) 150*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(pid, initial_map_names_to_skip) {} AndroidRemoteUnwinder(pid_t pid,const std::vector<std::string> initial_map_names_to_skip,const std::vector<std::string> map_suffixes_to_ignore)151*eb293b8fSAndroid Build Coastguard Worker AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip, 152*eb293b8fSAndroid Build Coastguard Worker const std::vector<std::string> map_suffixes_to_ignore) 153*eb293b8fSAndroid Build Coastguard Worker : AndroidUnwinder(pid, initial_map_names_to_skip, map_suffixes_to_ignore) {} 154*eb293b8fSAndroid Build Coastguard Worker virtual ~AndroidRemoteUnwinder() = default; 155*eb293b8fSAndroid Build Coastguard Worker 156*eb293b8fSAndroid Build Coastguard Worker protected: 157*eb293b8fSAndroid Build Coastguard Worker bool InternalInitialize(ErrorData& error) override; 158*eb293b8fSAndroid Build Coastguard Worker 159*eb293b8fSAndroid Build Coastguard Worker bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override; 160*eb293b8fSAndroid Build Coastguard Worker }; 161*eb293b8fSAndroid Build Coastguard Worker 162*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack 163