1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/*
* Copyright (C) 2012-2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "DEBUG"
#include "libdebuggerd/tombstone.h"
#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <android/log.h>
#include <async_safe/log.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Error.h>
#include <unwindstack/Regs.h>
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/open_files_list.h"
#include "libdebuggerd/utility.h"
#include "util.h"
#include "tombstone.pb.h"
using android::base::unique_fd;
using namespace std::literals::string_literals;
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
siginfo_t* siginfo, ucontext_t* ucontext) {
pid_t uid = getuid();
pid_t pid = getpid();
pid_t target_tid = gettid();
log_t log;
log.current_tid = target_tid;
log.crashed_tid = target_tid;
log.tfd = tombstone_fd;
log.amfd_data = nullptr;
std::string thread_name = get_thread_name(target_tid);
std::vector<std::string> command_line = get_command_line(pid);
std::unique_ptr<unwindstack::Regs> regs(
unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
std::string selinux_label;
android::base::ReadFileToString("/proc/self/attr/current", &selinux_label);
std::map<pid_t, ThreadInfo> threads;
threads[target_tid] = ThreadInfo {
.registers = std::move(regs), .uid = uid, .tid = target_tid,
.thread_name = std::move(thread_name), .pid = pid, .command_line = std::move(command_line),
.selinux_label = std::move(selinux_label), .siginfo = siginfo,
// Only supported on aarch64 for now.
#if defined(__aarch64__)
.tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
.pac_enabled_keys = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0),
#endif
};
const ThreadInfo& thread = threads[pid];
if (!iterate_tids(pid, [&threads, &thread, &target_tid](pid_t tid) {
if (target_tid == tid) {
return;
}
threads[tid] = ThreadInfo{
.uid = thread.uid,
.tid = tid,
.pid = thread.pid,
.command_line = thread.command_line,
.thread_name = get_thread_name(tid),
.tagged_addr_ctrl = thread.tagged_addr_ctrl,
.pac_enabled_keys = thread.pac_enabled_keys,
};
})) {
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to open /proc/%d/task: %s", pid,
strerror(errno));
}
// Do not use the thread cache here because it will call pthread_key_create
// which doesn't work in linker code. See b/189803009.
// Use a normal cached object because the thread is stopped, and there
// is no chance of data changing between reads.
auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
unwindstack::AndroidLocalUnwinder unwinder(process_memory);
unwindstack::ErrorData error;
if (!unwinder.Initialize(error)) {
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object: %s",
unwindstack::GetErrorCodeString(error.code));
return;
}
ProcessInfo process_info;
process_info.abort_msg_address = abort_msg_address;
engrave_tombstone(unique_fd(dup(tombstone_fd)), unique_fd(dup(proto_fd)), &unwinder, threads,
target_tid, process_info, nullptr, nullptr);
}
void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data) {
// Don't copy log messages to tombstone unless this is a development device.
Tombstone tombstone;
engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files);
if (proto_fd != -1) {
if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) {
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to write proto tombstone: %s",
strerror(errno));
}
}
log_t log;
log.current_tid = target_thread;
log.crashed_tid = target_thread;
log.tfd = output_fd.get();
log.amfd_data = amfd_data;
tombstone_proto_to_text(tombstone, [&log](const std::string& line, bool should_log) {
_LOG(&log, should_log ? logtype::HEADER : logtype::LOGS, "%s\n", line.c_str());
});
}
|