| Jeff Brown | 053b865 | 2012-06-06 16:25:03 -0700 | [diff] [blame] | 1 | /* | 
| Mark Salyzyn | fca0bd1 | 2013-12-12 12:21:20 -0800 | [diff] [blame] | 2 |  * Copyright (C) 2012-2014 The Android Open Source Project | 
| Jeff Brown | 053b865 | 2012-06-06 16:25:03 -0700 | [diff] [blame] | 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 |  | 
| Brigid Smith | 62ba489 | 2014-06-10 11:53:08 -0700 | [diff] [blame] | 17 | #define LOG_TAG "DEBUG" | 
 | 18 |  | 
| Josh Gao | c370666 | 2017-08-29 13:08:32 -0700 | [diff] [blame] | 19 | #include "libdebuggerd/tombstone.h" | 
 | 20 |  | 
| Kévin PETIT | 4bb4772 | 2013-12-18 16:44:24 +0000 | [diff] [blame] | 21 | #include <errno.h> | 
| Kévin PETIT | 4bb4772 | 2013-12-18 16:44:24 +0000 | [diff] [blame] | 22 | #include <signal.h> | 
 | 23 | #include <stddef.h> | 
 | 24 | #include <stdio.h> | 
 | 25 | #include <stdlib.h> | 
| Christopher Ferris | b999b82 | 2022-02-09 17:57:21 -0800 | [diff] [blame] | 26 | #include <sys/prctl.h> | 
| Christopher Ferris | bdea3bb | 2021-11-17 01:09:22 +0000 | [diff] [blame] | 27 | #include <sys/types.h> | 
 | 28 | #include <unistd.h> | 
| Jeff Brown | 053b865 | 2012-06-06 16:25:03 -0700 | [diff] [blame] | 29 |  | 
| Christopher Ferris | 6e96403 | 2015-05-15 17:30:21 -0700 | [diff] [blame] | 30 | #include <memory> | 
 | 31 | #include <string> | 
 | 32 |  | 
| Josh Gao | 57f58f8 | 2017-03-15 23:23:22 -0700 | [diff] [blame] | 33 | #include <android-base/file.h> | 
| Josh Gao | 57f58f8 | 2017-03-15 23:23:22 -0700 | [diff] [blame] | 34 | #include <android-base/unique_fd.h> | 
 | 35 | #include <android/log.h> | 
| Josh Gao | 618cea3 | 2021-01-26 17:45:43 -0800 | [diff] [blame] | 36 | #include <async_safe/log.h> | 
| Mark Salyzyn | cfd5b08 | 2016-10-17 14:28:00 -0700 | [diff] [blame] | 37 | #include <log/log.h> | 
| Mark Salyzyn | ff2dcd9 | 2016-09-28 15:54:45 -0700 | [diff] [blame] | 38 | #include <private/android_filesystem_config.h> | 
| Christopher Ferris | 3b7b7ba | 2022-03-15 16:56:09 -0700 | [diff] [blame] | 39 | #include <unwindstack/AndroidUnwinder.h> | 
 | 40 | #include <unwindstack/Error.h> | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 41 | #include <unwindstack/Regs.h> | 
| Jeff Brown | 053b865 | 2012-06-06 16:25:03 -0700 | [diff] [blame] | 42 |  | 
| Josh Gao | c370666 | 2017-08-29 13:08:32 -0700 | [diff] [blame] | 43 | #include "libdebuggerd/backtrace.h" | 
| Josh Gao | c370666 | 2017-08-29 13:08:32 -0700 | [diff] [blame] | 44 | #include "libdebuggerd/open_files_list.h" | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 45 | #include "libdebuggerd/utility.h" | 
| Elliott Hughes | a660cb3 | 2020-07-23 15:26:10 -0700 | [diff] [blame] | 46 | #include "util.h" | 
| Jeff Brown | 053b865 | 2012-06-06 16:25:03 -0700 | [diff] [blame] | 47 |  | 
| Josh Gao | 76e1e30 | 2021-01-26 15:53:11 -0800 | [diff] [blame] | 48 | #include "tombstone.pb.h" | 
 | 49 |  | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 50 | using android::base::unique_fd; | 
 | 51 |  | 
| Elliott Hughes | e1415a5 | 2018-02-15 09:18:21 -0800 | [diff] [blame] | 52 | using namespace std::literals::string_literals; | 
 | 53 |  | 
| Josh Gao | 76e1e30 | 2021-01-26 15:53:11 -0800 | [diff] [blame] | 54 | void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address, | 
 | 55 |                                 siginfo_t* siginfo, ucontext_t* ucontext) { | 
| Misha Wagner | 39c5b8c | 2019-04-18 16:07:33 +0100 | [diff] [blame] | 56 |   pid_t uid = getuid(); | 
| Josh Gao | e1aa0ca | 2017-03-01 17:23:22 -0800 | [diff] [blame] | 57 |   pid_t pid = getpid(); | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 58 |   pid_t target_tid = gettid(); | 
| Josh Gao | e1aa0ca | 2017-03-01 17:23:22 -0800 | [diff] [blame] | 59 |  | 
| Josh Gao | e73c932 | 2017-02-08 16:06:26 -0800 | [diff] [blame] | 60 |   log_t log; | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 61 |   log.current_tid = target_tid; | 
 | 62 |   log.crashed_tid = target_tid; | 
| Josh Gao | e73c932 | 2017-02-08 16:06:26 -0800 | [diff] [blame] | 63 |   log.tfd = tombstone_fd; | 
 | 64 |   log.amfd_data = nullptr; | 
 | 65 |  | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 66 |   std::string thread_name = get_thread_name(target_tid); | 
| Josh Gao | 31348a7 | 2021-03-29 21:53:42 -0700 | [diff] [blame] | 67 |   std::vector<std::string> command_line = get_command_line(pid); | 
| Josh Gao | 57f58f8 | 2017-03-15 23:23:22 -0700 | [diff] [blame] | 68 |  | 
| Christopher Ferris | 60eb197 | 2019-01-15 15:18:43 -0800 | [diff] [blame] | 69 |   std::unique_ptr<unwindstack::Regs> regs( | 
 | 70 |       unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext)); | 
| Josh Gao | e73c932 | 2017-02-08 16:06:26 -0800 | [diff] [blame] | 71 |  | 
| Josh Gao | 76e1e30 | 2021-01-26 15:53:11 -0800 | [diff] [blame] | 72 |   std::string selinux_label; | 
 | 73 |   android::base::ReadFileToString("/proc/self/attr/current", &selinux_label); | 
 | 74 |  | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 75 |   std::map<pid_t, ThreadInfo> threads; | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 76 |   threads[target_tid] = ThreadInfo { | 
 | 77 |     .registers = std::move(regs), .uid = uid, .tid = target_tid, | 
 | 78 |     .thread_name = std::move(thread_name), .pid = pid, .command_line = std::move(command_line), | 
 | 79 |     .selinux_label = std::move(selinux_label), .siginfo = siginfo, | 
| Christopher Ferris | b999b82 | 2022-02-09 17:57:21 -0800 | [diff] [blame] | 80 |     // Only supported on aarch64 for now. | 
| Christopher Ferris | fac411d | 2022-10-27 15:23:38 -0700 | [diff] [blame] | 81 | #if defined(__aarch64__) | 
 | 82 |     .tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0), | 
| Christopher Ferris | b999b82 | 2022-02-09 17:57:21 -0800 | [diff] [blame] | 83 |     .pac_enabled_keys = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0), | 
 | 84 | #endif | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 85 |   }; | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 86 |   const ThreadInfo& thread = threads[pid]; | 
 | 87 |   if (!iterate_tids(pid, [&threads, &thread, &target_tid](pid_t tid) { | 
 | 88 |         if (target_tid == tid) { | 
 | 89 |           return; | 
 | 90 |         } | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 91 |         threads[tid] = ThreadInfo{ | 
 | 92 |             .uid = thread.uid, | 
 | 93 |             .tid = tid, | 
 | 94 |             .pid = thread.pid, | 
 | 95 |             .command_line = thread.command_line, | 
 | 96 |             .thread_name = get_thread_name(tid), | 
 | 97 |             .tagged_addr_ctrl = thread.tagged_addr_ctrl, | 
 | 98 |             .pac_enabled_keys = thread.pac_enabled_keys, | 
 | 99 |         }; | 
 | 100 |       })) { | 
 | 101 |     async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to open /proc/%d/task: %s", pid, | 
 | 102 |                           strerror(errno)); | 
| Christopher Ferris | b999b82 | 2022-02-09 17:57:21 -0800 | [diff] [blame] | 103 |   } | 
| Josh Gao | 77b00ed | 2017-05-05 18:11:23 -0700 | [diff] [blame] | 104 |  | 
| Christopher Ferris | 3b7b7ba | 2022-03-15 16:56:09 -0700 | [diff] [blame] | 105 |   // Do not use the thread cache here because it will call pthread_key_create | 
 | 106 |   // which doesn't work in linker code. See b/189803009. | 
 | 107 |   // Use a normal cached object because the thread is stopped, and there | 
 | 108 |   // is no chance of data changing between reads. | 
 | 109 |   auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid()); | 
 | 110 |   unwindstack::AndroidLocalUnwinder unwinder(process_memory); | 
 | 111 |   unwindstack::ErrorData error; | 
 | 112 |   if (!unwinder.Initialize(error)) { | 
 | 113 |     async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object: %s", | 
 | 114 |                           unwindstack::GetErrorCodeString(error.code)); | 
| Christopher Ferris | b999b82 | 2022-02-09 17:57:21 -0800 | [diff] [blame] | 115 |     return; | 
| Josh Gao | e73c932 | 2017-02-08 16:06:26 -0800 | [diff] [blame] | 116 |   } | 
| Josh Gao | fdc95c9 | 2017-09-13 15:33:39 -0700 | [diff] [blame] | 117 |  | 
| Peter Collingbourne | 843f7e6 | 2020-02-28 19:07:33 -0800 | [diff] [blame] | 118 |   ProcessInfo process_info; | 
 | 119 |   process_info.abort_msg_address = abort_msg_address; | 
| Christopher Ferris | 7c2e7e3 | 2022-05-27 12:57:58 -0700 | [diff] [blame] | 120 |   engrave_tombstone(unique_fd(dup(tombstone_fd)), unique_fd(dup(proto_fd)), &unwinder, threads, | 
 | 121 |                     target_tid, process_info, nullptr, nullptr); | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 122 | } | 
 | 123 |  | 
| Christopher Ferris | 3b7b7ba | 2022-03-15 16:56:09 -0700 | [diff] [blame] | 124 | void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd, | 
 | 125 |                        unwindstack::AndroidUnwinder* unwinder, | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 126 |                        const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread, | 
| Peter Collingbourne | 843f7e6 | 2020-02-28 19:07:33 -0800 | [diff] [blame] | 127 |                        const ProcessInfo& process_info, OpenFilesList* open_files, | 
 | 128 |                        std::string* amfd_data) { | 
| Elliott Hughes | a660cb3 | 2020-07-23 15:26:10 -0700 | [diff] [blame] | 129 |   // Don't copy log messages to tombstone unless this is a development device. | 
| Josh Gao | 76e1e30 | 2021-01-26 15:53:11 -0800 | [diff] [blame] | 130 |   Tombstone tombstone; | 
 | 131 |   engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files); | 
 | 132 |  | 
| Josh Gao | 618cea3 | 2021-01-26 17:45:43 -0800 | [diff] [blame] | 133 |   if (proto_fd != -1) { | 
 | 134 |     if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) { | 
 | 135 |       async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to write proto tombstone: %s", | 
 | 136 |                             strerror(errno)); | 
 | 137 |     } | 
| Josh Gao | 76e1e30 | 2021-01-26 15:53:11 -0800 | [diff] [blame] | 138 |   } | 
| Josh Gao | 2b2ae0c | 2017-08-21 14:31:17 -0700 | [diff] [blame] | 139 |  | 
 | 140 |   log_t log; | 
 | 141 |   log.current_tid = target_thread; | 
 | 142 |   log.crashed_tid = target_thread; | 
 | 143 |   log.tfd = output_fd.get(); | 
 | 144 |   log.amfd_data = amfd_data; | 
 | 145 |  | 
| Christopher Ferris | bdea3bb | 2021-11-17 01:09:22 +0000 | [diff] [blame] | 146 |   tombstone_proto_to_text(tombstone, [&log](const std::string& line, bool should_log) { | 
 | 147 |     _LOG(&log, should_log ? logtype::HEADER : logtype::LOGS, "%s\n", line.c_str()); | 
 | 148 |   }); | 
| Josh Gao | e73c932 | 2017-02-08 16:06:26 -0800 | [diff] [blame] | 149 | } |