1*eb293b8fSAndroid Build Coastguard Worker /* 2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2021 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 <sys/types.h> 20*eb293b8fSAndroid Build Coastguard Worker 21*eb293b8fSAndroid Build Coastguard Worker #include <set> 22*eb293b8fSAndroid Build Coastguard Worker #include <string> 23*eb293b8fSAndroid Build Coastguard Worker 24*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack { 25*eb293b8fSAndroid Build Coastguard Worker 26*eb293b8fSAndroid Build Coastguard Worker // ProcessTracer objects abstract operations for tracing a process and its threads with ptrace(2). 27*eb293b8fSAndroid Build Coastguard Worker class ProcessTracer final { 28*eb293b8fSAndroid Build Coastguard Worker public: 29*eb293b8fSAndroid Build Coastguard Worker ProcessTracer(pid_t pid, bool is_tracing_threads); 30*eb293b8fSAndroid Build Coastguard Worker 31*eb293b8fSAndroid Build Coastguard Worker ~ProcessTracer(); 32*eb293b8fSAndroid Build Coastguard Worker 33*eb293b8fSAndroid Build Coastguard Worker // ProcessTracer instances are moveable but not copyable because they manage the 34*eb293b8fSAndroid Build Coastguard Worker // state of a process. 35*eb293b8fSAndroid Build Coastguard Worker ProcessTracer(const ProcessTracer&) = delete; 36*eb293b8fSAndroid Build Coastguard Worker ProcessTracer& operator=(const ProcessTracer&) = delete; 37*eb293b8fSAndroid Build Coastguard Worker ProcessTracer(ProcessTracer&&) = default; 38*eb293b8fSAndroid Build Coastguard Worker ProcessTracer& operator=(ProcessTracer&&) = delete; 39*eb293b8fSAndroid Build Coastguard Worker pid()40*eb293b8fSAndroid Build Coastguard Worker pid_t pid() const { return pid_; } 41*eb293b8fSAndroid Build Coastguard Worker tids()42*eb293b8fSAndroid Build Coastguard Worker const std::set<pid_t>& tids() const { return tids_; } 43*eb293b8fSAndroid Build Coastguard Worker IsTracingThreads()44*eb293b8fSAndroid Build Coastguard Worker bool IsTracingThreads() const { return is_tracing_threads_; } 45*eb293b8fSAndroid Build Coastguard Worker 46*eb293b8fSAndroid Build Coastguard Worker bool Stop(); 47*eb293b8fSAndroid Build Coastguard Worker 48*eb293b8fSAndroid Build Coastguard Worker bool Resume(); 49*eb293b8fSAndroid Build Coastguard Worker 50*eb293b8fSAndroid Build Coastguard Worker // Like ptrace, it is required to call ProcessTracer::Detach before calling ProcessTracer::Attach 51*eb293b8fSAndroid Build Coastguard Worker // on a different thread of the same process. 52*eb293b8fSAndroid Build Coastguard Worker bool Detach(pid_t tid); 53*eb293b8fSAndroid Build Coastguard Worker 54*eb293b8fSAndroid Build Coastguard Worker bool Attach(pid_t tid); 55*eb293b8fSAndroid Build Coastguard Worker 56*eb293b8fSAndroid Build Coastguard Worker // This method for determining whether a thread is currently executing instructions from a 57*eb293b8fSAndroid Build Coastguard Worker // desired ELF is not the most time efficient solution. In the interest of simplicity and 58*eb293b8fSAndroid Build Coastguard Worker // limiting memory usage, the UnwinderFromPid, Regs, and Maps instances constructed for 59*eb293b8fSAndroid Build Coastguard Worker // in each check (loop iteration) are thrown away. 60*eb293b8fSAndroid Build Coastguard Worker // 61*eb293b8fSAndroid Build Coastguard Worker // A SIGINT signal handler is set up to allow the user to gracefully exit with CTRL-C if they 62*eb293b8fSAndroid Build Coastguard Worker // decide that they no longer want to wait for the process to enter the desired ELF. 63*eb293b8fSAndroid Build Coastguard Worker bool StopInDesiredElf(const std::string& elf_name); 64*eb293b8fSAndroid Build Coastguard Worker 65*eb293b8fSAndroid Build Coastguard Worker // `desired_elf_name` should match the filename of the path (the component following the final 66*eb293b8fSAndroid Build Coastguard Worker // '/') corresponding to the shared library as indicated in /proc/pid/maps. 67*eb293b8fSAndroid Build Coastguard Worker static bool UsesSharedLibrary(pid_t pid, const std::string& desired_elf_name); 68*eb293b8fSAndroid Build Coastguard Worker 69*eb293b8fSAndroid Build Coastguard Worker private: 70*eb293b8fSAndroid Build Coastguard Worker static bool ProcIsInDesiredElf(pid_t tid, const std::string& desired_elf_name); 71*eb293b8fSAndroid Build Coastguard Worker 72*eb293b8fSAndroid Build Coastguard Worker // Initialize tids_ such that the main thread is the first element and 73*eb293b8fSAndroid Build Coastguard Worker // the remaining tids are in order from least to greatest. 74*eb293b8fSAndroid Build Coastguard Worker bool InitProcessTids(); 75*eb293b8fSAndroid Build Coastguard Worker 76*eb293b8fSAndroid Build Coastguard Worker static constexpr pid_t kNoThreadAttached = -2; 77*eb293b8fSAndroid Build Coastguard Worker static constexpr pid_t kKillFailed = -1; 78*eb293b8fSAndroid Build Coastguard Worker static constexpr pid_t kPtraceFailed = -1; 79*eb293b8fSAndroid Build Coastguard Worker static constexpr pid_t kWaitpidFailed = -1; 80*eb293b8fSAndroid Build Coastguard Worker static inline std::atomic_bool keepWaitingForPcInElf = true; 81*eb293b8fSAndroid Build Coastguard Worker 82*eb293b8fSAndroid Build Coastguard Worker const pid_t pid_; 83*eb293b8fSAndroid Build Coastguard Worker bool is_tracing_threads_ = false; 84*eb293b8fSAndroid Build Coastguard Worker std::set<pid_t> tids_; 85*eb293b8fSAndroid Build Coastguard Worker bool is_running_ = true; 86*eb293b8fSAndroid Build Coastguard Worker pid_t cur_attached_tid_ = kNoThreadAttached; 87*eb293b8fSAndroid Build Coastguard Worker }; 88*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack 89