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 #include <errno.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <fcntl.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <sys/ptrace.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <sys/wait.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
23*eb293b8fSAndroid Build Coastguard Worker
24*eb293b8fSAndroid Build Coastguard Worker #include <algorithm>
25*eb293b8fSAndroid Build Coastguard Worker #include <array>
26*eb293b8fSAndroid Build Coastguard Worker #include <atomic>
27*eb293b8fSAndroid Build Coastguard Worker #include <csignal>
28*eb293b8fSAndroid Build Coastguard Worker #include <cstddef>
29*eb293b8fSAndroid Build Coastguard Worker #include <cstdio>
30*eb293b8fSAndroid Build Coastguard Worker #include <cstring>
31*eb293b8fSAndroid Build Coastguard Worker #include <memory>
32*eb293b8fSAndroid Build Coastguard Worker #include <regex>
33*eb293b8fSAndroid Build Coastguard Worker #include <string>
34*eb293b8fSAndroid Build Coastguard Worker #include <unordered_set>
35*eb293b8fSAndroid Build Coastguard Worker #include <vector>
36*eb293b8fSAndroid Build Coastguard Worker
37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
39*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
40*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
41*eb293b8fSAndroid Build Coastguard Worker
42*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
43*eb293b8fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
44*eb293b8fSAndroid Build Coastguard Worker #include <procinfo/process.h>
45*eb293b8fSAndroid Build Coastguard Worker
46*eb293b8fSAndroid Build Coastguard Worker #include "ProcessTracer.h"
47*eb293b8fSAndroid Build Coastguard Worker
48*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
49*eb293b8fSAndroid Build Coastguard Worker
ProcessTracer(pid_t pid,bool is_tracing_threads)50*eb293b8fSAndroid Build Coastguard Worker ProcessTracer::ProcessTracer(pid_t pid, bool is_tracing_threads)
51*eb293b8fSAndroid Build Coastguard Worker : pid_(pid), is_tracing_threads_(is_tracing_threads) {
52*eb293b8fSAndroid Build Coastguard Worker if (is_tracing_threads_) is_tracing_threads_ = InitProcessTids();
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker
InitProcessTids()55*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::InitProcessTids() {
56*eb293b8fSAndroid Build Coastguard Worker std::string error_msg;
57*eb293b8fSAndroid Build Coastguard Worker if (!android::procinfo::GetProcessTids(pid_, &tids_, &error_msg)) {
58*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr,
59*eb293b8fSAndroid Build Coastguard Worker "Failed to get process tids: %s. Reverting to tracing the "
60*eb293b8fSAndroid Build Coastguard Worker "main thread only.\n",
61*eb293b8fSAndroid Build Coastguard Worker error_msg.c_str());
62*eb293b8fSAndroid Build Coastguard Worker return false;
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker if (tids_.erase(pid_) != 1) {
65*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr,
66*eb293b8fSAndroid Build Coastguard Worker "Failed to erase the main thread from the thread id set. "
67*eb293b8fSAndroid Build Coastguard Worker "Reverting to tracing the main thread only.\n");
68*eb293b8fSAndroid Build Coastguard Worker return false;
69*eb293b8fSAndroid Build Coastguard Worker }
70*eb293b8fSAndroid Build Coastguard Worker return true;
71*eb293b8fSAndroid Build Coastguard Worker }
72*eb293b8fSAndroid Build Coastguard Worker
~ProcessTracer()73*eb293b8fSAndroid Build Coastguard Worker ProcessTracer::~ProcessTracer() {
74*eb293b8fSAndroid Build Coastguard Worker if (cur_attached_tid_ != kNoThreadAttached) Detach(cur_attached_tid_);
75*eb293b8fSAndroid Build Coastguard Worker if (!is_running_) Resume();
76*eb293b8fSAndroid Build Coastguard Worker }
77*eb293b8fSAndroid Build Coastguard Worker
Stop()78*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::Stop() {
79*eb293b8fSAndroid Build Coastguard Worker if (kill(pid_, SIGSTOP) == kKillFailed) {
80*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to send stop signal to pid %d: %s\n", pid_, strerror(errno));
81*eb293b8fSAndroid Build Coastguard Worker return false;
82*eb293b8fSAndroid Build Coastguard Worker }
83*eb293b8fSAndroid Build Coastguard Worker usleep(1000); // 1 ms. Without this sleep, any attempt to resume right away may fail.
84*eb293b8fSAndroid Build Coastguard Worker
85*eb293b8fSAndroid Build Coastguard Worker is_running_ = false;
86*eb293b8fSAndroid Build Coastguard Worker return true;
87*eb293b8fSAndroid Build Coastguard Worker }
88*eb293b8fSAndroid Build Coastguard Worker
Resume()89*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::Resume() {
90*eb293b8fSAndroid Build Coastguard Worker if (kill(pid_, SIGCONT) == kKillFailed) {
91*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to send continue signal to pid %d: %s\n", pid_, strerror(errno));
92*eb293b8fSAndroid Build Coastguard Worker return false;
93*eb293b8fSAndroid Build Coastguard Worker }
94*eb293b8fSAndroid Build Coastguard Worker usleep(1000); // 1 ms. Without this sleep, any attempt to stop right away may fail.
95*eb293b8fSAndroid Build Coastguard Worker
96*eb293b8fSAndroid Build Coastguard Worker is_running_ = true;
97*eb293b8fSAndroid Build Coastguard Worker return true;
98*eb293b8fSAndroid Build Coastguard Worker }
99*eb293b8fSAndroid Build Coastguard Worker
Detach(pid_t tid)100*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::Detach(pid_t tid) {
101*eb293b8fSAndroid Build Coastguard Worker if (tid != pid_ && !tids_.contains(tid)) {
102*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Tid %d does not belong to proc %d.\n", tid, pid_);
103*eb293b8fSAndroid Build Coastguard Worker return false;
104*eb293b8fSAndroid Build Coastguard Worker }
105*eb293b8fSAndroid Build Coastguard Worker
106*eb293b8fSAndroid Build Coastguard Worker if (cur_attached_tid_ == kNoThreadAttached) {
107*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Cannot detach because no thread is currently attached.\n");
108*eb293b8fSAndroid Build Coastguard Worker return false;
109*eb293b8fSAndroid Build Coastguard Worker }
110*eb293b8fSAndroid Build Coastguard Worker if (is_running_ && !Stop()) return false;
111*eb293b8fSAndroid Build Coastguard Worker
112*eb293b8fSAndroid Build Coastguard Worker if (ptrace(PTRACE_DETACH, tid, nullptr, nullptr) == kPtraceFailed) {
113*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to detach from tid %d: %s\n", tid, strerror(errno));
114*eb293b8fSAndroid Build Coastguard Worker return false;
115*eb293b8fSAndroid Build Coastguard Worker }
116*eb293b8fSAndroid Build Coastguard Worker
117*eb293b8fSAndroid Build Coastguard Worker cur_attached_tid_ = kNoThreadAttached;
118*eb293b8fSAndroid Build Coastguard Worker return true;
119*eb293b8fSAndroid Build Coastguard Worker }
120*eb293b8fSAndroid Build Coastguard Worker
Attach(pid_t tid)121*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::Attach(pid_t tid) {
122*eb293b8fSAndroid Build Coastguard Worker if (tid != pid_ && !tids_.contains(tid)) {
123*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Tid %d does not belong to proc %d.\n", tid, pid_);
124*eb293b8fSAndroid Build Coastguard Worker return false;
125*eb293b8fSAndroid Build Coastguard Worker }
126*eb293b8fSAndroid Build Coastguard Worker
127*eb293b8fSAndroid Build Coastguard Worker if (is_running_) Stop();
128*eb293b8fSAndroid Build Coastguard Worker if (cur_attached_tid_ != kNoThreadAttached) {
129*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Cannot attatch to tid %d. Already attached to tid %d.\n", tid,
130*eb293b8fSAndroid Build Coastguard Worker cur_attached_tid_);
131*eb293b8fSAndroid Build Coastguard Worker return false;
132*eb293b8fSAndroid Build Coastguard Worker }
133*eb293b8fSAndroid Build Coastguard Worker
134*eb293b8fSAndroid Build Coastguard Worker if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr) == kPtraceFailed) {
135*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to attached to tid %d: %s\n", tid, strerror(errno));
136*eb293b8fSAndroid Build Coastguard Worker return false;
137*eb293b8fSAndroid Build Coastguard Worker }
138*eb293b8fSAndroid Build Coastguard Worker int status;
139*eb293b8fSAndroid Build Coastguard Worker if (waitpid(tid, &status, 0) == kWaitpidFailed) {
140*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to stop tid %d: %s\n", tid, strerror(errno));
141*eb293b8fSAndroid Build Coastguard Worker return false;
142*eb293b8fSAndroid Build Coastguard Worker }
143*eb293b8fSAndroid Build Coastguard Worker
144*eb293b8fSAndroid Build Coastguard Worker cur_attached_tid_ = tid;
145*eb293b8fSAndroid Build Coastguard Worker return true;
146*eb293b8fSAndroid Build Coastguard Worker }
147*eb293b8fSAndroid Build Coastguard Worker
StopInDesiredElf(const std::string & elf_name)148*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::StopInDesiredElf(const std::string& elf_name) {
149*eb293b8fSAndroid Build Coastguard Worker signal(SIGINT, [](int) { keepWaitingForPcInElf = false; });
150*eb293b8fSAndroid Build Coastguard Worker bool pc_in_desired_elf = true;
151*eb293b8fSAndroid Build Coastguard Worker do {
152*eb293b8fSAndroid Build Coastguard Worker if (!Attach(pid_)) return false;
153*eb293b8fSAndroid Build Coastguard Worker pc_in_desired_elf = ProcIsInDesiredElf(pid_, elf_name);
154*eb293b8fSAndroid Build Coastguard Worker if (!Detach(pid_)) return false;
155*eb293b8fSAndroid Build Coastguard Worker
156*eb293b8fSAndroid Build Coastguard Worker if (!pc_in_desired_elf) {
157*eb293b8fSAndroid Build Coastguard Worker for (pid_t tid : tids_) {
158*eb293b8fSAndroid Build Coastguard Worker if (!Attach(tid)) return false;
159*eb293b8fSAndroid Build Coastguard Worker pc_in_desired_elf = ProcIsInDesiredElf(tid, elf_name);
160*eb293b8fSAndroid Build Coastguard Worker if (!Detach(tid)) return false;
161*eb293b8fSAndroid Build Coastguard Worker if (pc_in_desired_elf) break;
162*eb293b8fSAndroid Build Coastguard Worker }
163*eb293b8fSAndroid Build Coastguard Worker }
164*eb293b8fSAndroid Build Coastguard Worker
165*eb293b8fSAndroid Build Coastguard Worker // If the process is not in the desired ELF, resume it for a short time, then check again.
166*eb293b8fSAndroid Build Coastguard Worker if (!pc_in_desired_elf) {
167*eb293b8fSAndroid Build Coastguard Worker Resume();
168*eb293b8fSAndroid Build Coastguard Worker usleep(1000); // 1 ms
169*eb293b8fSAndroid Build Coastguard Worker Stop();
170*eb293b8fSAndroid Build Coastguard Worker }
171*eb293b8fSAndroid Build Coastguard Worker } while (!pc_in_desired_elf && keepWaitingForPcInElf);
172*eb293b8fSAndroid Build Coastguard Worker
173*eb293b8fSAndroid Build Coastguard Worker if (!pc_in_desired_elf) {
174*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "\nExited while waiting for pid %d to enter %s.\n", pid_, elf_name.c_str());
175*eb293b8fSAndroid Build Coastguard Worker return false;
176*eb293b8fSAndroid Build Coastguard Worker }
177*eb293b8fSAndroid Build Coastguard Worker return true;
178*eb293b8fSAndroid Build Coastguard Worker }
179*eb293b8fSAndroid Build Coastguard Worker
UsesSharedLibrary(pid_t pid,const std::string & desired_elf_name)180*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::UsesSharedLibrary(pid_t pid, const std::string& desired_elf_name) {
181*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Maps> maps = std::make_unique<RemoteMaps>(pid);
182*eb293b8fSAndroid Build Coastguard Worker if (!maps->Parse()) {
183*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Could not parse maps for pid %d.\n", pid);
184*eb293b8fSAndroid Build Coastguard Worker return false;
185*eb293b8fSAndroid Build Coastguard Worker }
186*eb293b8fSAndroid Build Coastguard Worker for (const auto& map : *maps) {
187*eb293b8fSAndroid Build Coastguard Worker if (android::base::Basename(map->name()).c_str() == desired_elf_name) return true;
188*eb293b8fSAndroid Build Coastguard Worker }
189*eb293b8fSAndroid Build Coastguard Worker return false;
190*eb293b8fSAndroid Build Coastguard Worker }
191*eb293b8fSAndroid Build Coastguard Worker
ProcIsInDesiredElf(pid_t pid,const std::string & desired_elf_name)192*eb293b8fSAndroid Build Coastguard Worker bool ProcessTracer::ProcIsInDesiredElf(pid_t pid, const std::string& desired_elf_name) {
193*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
194*eb293b8fSAndroid Build Coastguard Worker if (regs == nullptr) {
195*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Unable to get remote reg data.\n");
196*eb293b8fSAndroid Build Coastguard Worker return false;
197*eb293b8fSAndroid Build Coastguard Worker }
198*eb293b8fSAndroid Build Coastguard Worker UnwinderFromPid unwinder(1024, pid);
199*eb293b8fSAndroid Build Coastguard Worker unwinder.SetRegs(regs.get());
200*eb293b8fSAndroid Build Coastguard Worker if (!unwinder.Init()) {
201*eb293b8fSAndroid Build Coastguard Worker fprintf(stderr, "Unable to intitialize unwinder.\n");
202*eb293b8fSAndroid Build Coastguard Worker return false;
203*eb293b8fSAndroid Build Coastguard Worker }
204*eb293b8fSAndroid Build Coastguard Worker Maps* maps = unwinder.GetMaps();
205*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps->Find(regs->pc());
206*eb293b8fSAndroid Build Coastguard Worker if (map_info == nullptr) {
207*eb293b8fSAndroid Build Coastguard Worker regs->fallback_pc();
208*eb293b8fSAndroid Build Coastguard Worker map_info = maps->Find(regs->pc());
209*eb293b8fSAndroid Build Coastguard Worker if (map_info == nullptr) {
210*eb293b8fSAndroid Build Coastguard Worker return false;
211*eb293b8fSAndroid Build Coastguard Worker }
212*eb293b8fSAndroid Build Coastguard Worker }
213*eb293b8fSAndroid Build Coastguard Worker
214*eb293b8fSAndroid Build Coastguard Worker const std::string& current_elf_name = android::base::Basename(map_info->name()).c_str();
215*eb293b8fSAndroid Build Coastguard Worker bool in_desired_elf = current_elf_name == desired_elf_name;
216*eb293b8fSAndroid Build Coastguard Worker if (in_desired_elf) printf("pid %d is in %s! Unwinding...\n\n", pid, desired_elf_name.c_str());
217*eb293b8fSAndroid Build Coastguard Worker return in_desired_elf;
218*eb293b8fSAndroid Build Coastguard Worker }
219*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
220