1 /* 2 * Copyright 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <err.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include <limits> 23 #include <string_view> 24 #include <thread> 25 26 #include <android-base/file.h> 27 #include <android-base/logging.h> 28 #include <android-base/parseint.h> 29 #include <android-base/unique_fd.h> 30 #include <debuggerd/client.h> 31 #include <procinfo/process.h> 32 #include "util.h" 33 34 using android::base::unique_fd; 35 36 static void usage(int exit_code) { 37 fprintf(stderr, "usage: debuggerd [-bj] PID\n"); 38 fprintf(stderr, "\n"); 39 fprintf(stderr, "-b, --backtrace just a backtrace rather than a full tombstone\n"); 40 fprintf(stderr, "-j collect java traces\n"); 41 _exit(exit_code); 42 } 43 44 static std::thread spawn_redirect_thread(unique_fd fd) { 45 return std::thread([fd{ std::move(fd) }]() { 46 while (true) { 47 char buf[BUFSIZ]; 48 ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf))); 49 if (rc <= 0) { 50 return; 51 } 52 53 if (!android::base::WriteFully(STDOUT_FILENO, buf, rc)) { 54 return; 55 } 56 } 57 }); 58 } 59 60 int main(int argc, char* argv[]) { 61 if (argc <= 1) usage(0); 62 if (argc > 3) usage(1); 63 64 DebuggerdDumpType dump_type = kDebuggerdTombstone; 65 66 if (argc == 3) { 67 std::string_view flag = argv[1]; 68 if (flag == "-b" || flag == "--backtrace") { 69 dump_type = kDebuggerdNativeBacktrace; 70 } else if (flag == "-j") { 71 dump_type = kDebuggerdJavaBacktrace; 72 } else { 73 usage(1); 74 } 75 } 76 77 pid_t pid; 78 if (!android::base::ParseInt(argv[argc - 1], &pid, 1, std::numeric_limits<pid_t>::max())) { 79 usage(1); 80 } 81 82 if (getuid() != 0) { 83 errx(1, "root is required"); 84 } 85 86 // Check to see if the process exists and that we can actually send a signal to it. 87 android::procinfo::ProcessInfo proc_info; 88 if (!android::procinfo::GetProcessInfo(pid, &proc_info)) { 89 err(1, "failed to fetch info for process %d", pid); 90 } 91 92 if (proc_info.state == android::procinfo::kProcessStateZombie) { 93 errx(1, "process %d is a zombie", pid); 94 } 95 96 if (kill(pid, 0) != 0) { 97 err(1, "cannot send signal to process %d", pid); 98 } 99 100 unique_fd piperead, pipewrite; 101 if (!Pipe(&piperead, &pipewrite)) { 102 err(1, "failed to create pipe"); 103 } 104 105 std::thread redirect_thread = spawn_redirect_thread(std::move(piperead)); 106 if (!debuggerd_trigger_dump(pid, dump_type, 0, std::move(pipewrite))) { 107 redirect_thread.join(); 108 errx(1, "failed to dump process %d", pid); 109 } 110 111 redirect_thread.join(); 112 return 0; 113 } 114