xref: /aosp_15_r20/system/core/debuggerd/debuggerd.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker  * Copyright 2016, The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker  *
4*00c7fec1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*00c7fec1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*00c7fec1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*00c7fec1SAndroid Build Coastguard Worker  *
8*00c7fec1SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*00c7fec1SAndroid Build Coastguard Worker  *
10*00c7fec1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*00c7fec1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*00c7fec1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*00c7fec1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*00c7fec1SAndroid Build Coastguard Worker  * limitations under the License.
15*00c7fec1SAndroid Build Coastguard Worker  */
16*00c7fec1SAndroid Build Coastguard Worker 
17*00c7fec1SAndroid Build Coastguard Worker #include <err.h>
18*00c7fec1SAndroid Build Coastguard Worker #include <stdio.h>
19*00c7fec1SAndroid Build Coastguard Worker #include <stdlib.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
21*00c7fec1SAndroid Build Coastguard Worker 
22*00c7fec1SAndroid Build Coastguard Worker #include <limits>
23*00c7fec1SAndroid Build Coastguard Worker #include <string_view>
24*00c7fec1SAndroid Build Coastguard Worker #include <thread>
25*00c7fec1SAndroid Build Coastguard Worker 
26*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
27*00c7fec1SAndroid Build Coastguard Worker #include <android-base/parseint.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <debuggerd/client.h>
30*00c7fec1SAndroid Build Coastguard Worker #include <processgroup/processgroup.h>
31*00c7fec1SAndroid Build Coastguard Worker #include <procinfo/process.h>
32*00c7fec1SAndroid Build Coastguard Worker #include "util.h"
33*00c7fec1SAndroid Build Coastguard Worker 
34*00c7fec1SAndroid Build Coastguard Worker using android::base::unique_fd;
35*00c7fec1SAndroid Build Coastguard Worker 
usage(int exit_code)36*00c7fec1SAndroid Build Coastguard Worker static void usage(int exit_code) {
37*00c7fec1SAndroid Build Coastguard Worker   fprintf(stderr, "usage: debuggerd [-bj] PID\n");
38*00c7fec1SAndroid Build Coastguard Worker   fprintf(stderr, "\n");
39*00c7fec1SAndroid Build Coastguard Worker   fprintf(stderr, "-b, --backtrace    just a backtrace rather than a full tombstone\n");
40*00c7fec1SAndroid Build Coastguard Worker   fprintf(stderr, "-j                 collect java traces\n");
41*00c7fec1SAndroid Build Coastguard Worker   _exit(exit_code);
42*00c7fec1SAndroid Build Coastguard Worker }
43*00c7fec1SAndroid Build Coastguard Worker 
main(int argc,char * argv[])44*00c7fec1SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
45*00c7fec1SAndroid Build Coastguard Worker   if (argc <= 1) usage(0);
46*00c7fec1SAndroid Build Coastguard Worker   if (argc > 3) usage(1);
47*00c7fec1SAndroid Build Coastguard Worker 
48*00c7fec1SAndroid Build Coastguard Worker   DebuggerdDumpType dump_type = kDebuggerdTombstone;
49*00c7fec1SAndroid Build Coastguard Worker 
50*00c7fec1SAndroid Build Coastguard Worker   if (argc == 3) {
51*00c7fec1SAndroid Build Coastguard Worker     std::string_view flag = argv[1];
52*00c7fec1SAndroid Build Coastguard Worker     if (flag == "-b" || flag == "--backtrace") {
53*00c7fec1SAndroid Build Coastguard Worker       dump_type = kDebuggerdNativeBacktrace;
54*00c7fec1SAndroid Build Coastguard Worker     } else if (flag == "-j") {
55*00c7fec1SAndroid Build Coastguard Worker       dump_type = kDebuggerdJavaBacktrace;
56*00c7fec1SAndroid Build Coastguard Worker     } else {
57*00c7fec1SAndroid Build Coastguard Worker       usage(1);
58*00c7fec1SAndroid Build Coastguard Worker     }
59*00c7fec1SAndroid Build Coastguard Worker   }
60*00c7fec1SAndroid Build Coastguard Worker 
61*00c7fec1SAndroid Build Coastguard Worker   pid_t pid;
62*00c7fec1SAndroid Build Coastguard Worker   if (!android::base::ParseInt(argv[argc - 1], &pid, 1, std::numeric_limits<pid_t>::max())) {
63*00c7fec1SAndroid Build Coastguard Worker     usage(1);
64*00c7fec1SAndroid Build Coastguard Worker   }
65*00c7fec1SAndroid Build Coastguard Worker 
66*00c7fec1SAndroid Build Coastguard Worker   if (getuid() != 0) {
67*00c7fec1SAndroid Build Coastguard Worker     errx(1, "root is required");
68*00c7fec1SAndroid Build Coastguard Worker   }
69*00c7fec1SAndroid Build Coastguard Worker 
70*00c7fec1SAndroid Build Coastguard Worker   // Check to see if the process exists and that we can actually send a signal to it.
71*00c7fec1SAndroid Build Coastguard Worker   android::procinfo::ProcessInfo proc_info;
72*00c7fec1SAndroid Build Coastguard Worker   if (!android::procinfo::GetProcessInfo(pid, &proc_info)) {
73*00c7fec1SAndroid Build Coastguard Worker     err(1, "failed to fetch info for process %d", pid);
74*00c7fec1SAndroid Build Coastguard Worker   }
75*00c7fec1SAndroid Build Coastguard Worker 
76*00c7fec1SAndroid Build Coastguard Worker   if (proc_info.state == android::procinfo::kProcessStateZombie) {
77*00c7fec1SAndroid Build Coastguard Worker     errx(1, "process %d is a zombie", pid);
78*00c7fec1SAndroid Build Coastguard Worker   }
79*00c7fec1SAndroid Build Coastguard Worker 
80*00c7fec1SAndroid Build Coastguard Worker   // Send a signal to the main thread pid, not a side thread. The signal
81*00c7fec1SAndroid Build Coastguard Worker   // handler always sets the crashing tid to the main thread pid when sent this
82*00c7fec1SAndroid Build Coastguard Worker   // signal. This is to avoid a problem where the signal is sent to a process,
83*00c7fec1SAndroid Build Coastguard Worker   // but happens on a side thread and the intercept mismatches since it
84*00c7fec1SAndroid Build Coastguard Worker   // is looking for the main thread pid, not the tid of this random thread.
85*00c7fec1SAndroid Build Coastguard Worker   // See b/194346289 for extra details.
86*00c7fec1SAndroid Build Coastguard Worker   if (kill(proc_info.pid, 0) != 0) {
87*00c7fec1SAndroid Build Coastguard Worker     if (pid == proc_info.pid) {
88*00c7fec1SAndroid Build Coastguard Worker       err(1, "cannot send signal to process %d", pid);
89*00c7fec1SAndroid Build Coastguard Worker     } else {
90*00c7fec1SAndroid Build Coastguard Worker       err(1, "cannot send signal to main thread %d (requested thread %d)", proc_info.pid, pid);
91*00c7fec1SAndroid Build Coastguard Worker     }
92*00c7fec1SAndroid Build Coastguard Worker   }
93*00c7fec1SAndroid Build Coastguard Worker 
94*00c7fec1SAndroid Build Coastguard Worker   // unfreeze if pid is frozen.
95*00c7fec1SAndroid Build Coastguard Worker   SetProcessProfiles(proc_info.uid, proc_info.pid, {"Unfrozen"});
96*00c7fec1SAndroid Build Coastguard Worker   // we don't restore the frozen state as this is considered a benign change.
97*00c7fec1SAndroid Build Coastguard Worker 
98*00c7fec1SAndroid Build Coastguard Worker   unique_fd output_fd(fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0));
99*00c7fec1SAndroid Build Coastguard Worker   if (output_fd.get() == -1) {
100*00c7fec1SAndroid Build Coastguard Worker     err(1, "failed to fcntl dup stdout");
101*00c7fec1SAndroid Build Coastguard Worker   }
102*00c7fec1SAndroid Build Coastguard Worker   if (!debuggerd_trigger_dump(proc_info.pid, dump_type, 0, std::move(output_fd))) {
103*00c7fec1SAndroid Build Coastguard Worker     if (pid == proc_info.pid) {
104*00c7fec1SAndroid Build Coastguard Worker       errx(1, "failed to dump process %d", pid);
105*00c7fec1SAndroid Build Coastguard Worker     } else {
106*00c7fec1SAndroid Build Coastguard Worker       errx(1, "failed to dump main thread %d (requested thread %d)", proc_info.pid, pid);
107*00c7fec1SAndroid Build Coastguard Worker     }
108*00c7fec1SAndroid Build Coastguard Worker   }
109*00c7fec1SAndroid Build Coastguard Worker 
110*00c7fec1SAndroid Build Coastguard Worker   return 0;
111*00c7fec1SAndroid Build Coastguard Worker }
112