Create a ProcessInfo structure with the process-wide information from the crasher.

We're now passing around a couple of addresses for GWP-ASan in addition
to abort_msg_address and fdsan_table_address, and I'm going to need to add
more of them for MTE. Move them into a data structure in order to simplify
various function signatures.

Bug: 135772972
Change-Id: Ie01e1bd93a9ab64f21865f56574696825a6a125f
This commit is contained in:
Peter Collingbourne 2020-02-28 19:07:33 -08:00
parent ad9d034e7d
commit 843f7e645d
7 changed files with 51 additions and 58 deletions

View file

@ -254,9 +254,7 @@ static void ParseArgs(int argc, char** argv, pid_t* pseudothread_tid, DebuggerdD
}
static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_msg_address,
uintptr_t* fdsan_table_address, uintptr_t* gwp_asan_state,
uintptr_t* gwp_asan_metadata) {
std::unique_ptr<unwindstack::Regs>* regs, ProcessInfo* process_info) {
std::aligned_storage<sizeof(CrashInfo) + 1, alignof(CrashInfo)>::type buf;
CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &buf, sizeof(buf)));
@ -288,19 +286,16 @@ static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
}
}
*fdsan_table_address = 0;
*gwp_asan_state = 0;
*gwp_asan_metadata = 0;
switch (crash_info->header.version) {
case 3:
*gwp_asan_state = crash_info->data.v3.gwp_asan_state;
*gwp_asan_metadata = crash_info->data.v3.gwp_asan_metadata;
process_info->gwp_asan_state = crash_info->data.v3.gwp_asan_state;
process_info->gwp_asan_metadata = crash_info->data.v3.gwp_asan_metadata;
FALLTHROUGH_INTENDED;
case 2:
*fdsan_table_address = crash_info->data.v2.fdsan_table_address;
process_info->fdsan_table_address = crash_info->data.v2.fdsan_table_address;
FALLTHROUGH_INTENDED;
case 1:
*abort_msg_address = crash_info->data.v1.abort_msg_address;
process_info->abort_msg_address = crash_info->data.v1.abort_msg_address;
*siginfo = crash_info->data.v1.siginfo;
regs->reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(),
&crash_info->data.v1.ucontext));
@ -425,10 +420,7 @@ int main(int argc, char** argv) {
ATRACE_NAME("after reparent");
pid_t pseudothread_tid;
DebuggerdDumpType dump_type;
uintptr_t abort_msg_address = 0;
uintptr_t fdsan_table_address = 0;
uintptr_t gwp_asan_state = 0;
uintptr_t gwp_asan_metadata = 0;
ProcessInfo process_info;
Initialize(argv);
ParseArgs(argc, argv, &pseudothread_tid, &dump_type);
@ -489,8 +481,7 @@ int main(int argc, char** argv) {
if (thread == g_target_thread) {
// Read the thread's registers along with the rest of the crash info out of the pipe.
ReadCrashInfo(input_pipe, &siginfo, &info.registers, &abort_msg_address,
&fdsan_table_address, &gwp_asan_state, &gwp_asan_metadata);
ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info);
info.siginfo = &siginfo;
info.signo = info.siginfo->si_signo;
} else {
@ -599,14 +590,14 @@ int main(int argc, char** argv) {
} else {
{
ATRACE_NAME("fdsan table dump");
populate_fdsan_table(&open_files, unwinder.GetProcessMemory(), fdsan_table_address);
populate_fdsan_table(&open_files, unwinder.GetProcessMemory(),
process_info.fdsan_table_address);
}
{
ATRACE_NAME("engrave_tombstone");
engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread,
abort_msg_address, &open_files, &amfd_data, gwp_asan_state,
gwp_asan_metadata);
engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread, process_info,
&open_files, &amfd_data);
}
}

View file

@ -63,12 +63,11 @@ static const gwp_asan::AllocationMetadata* retrieve_gwp_asan_metadata(
}
GwpAsanCrashData::GwpAsanCrashData(unwindstack::Memory* process_memory,
uintptr_t gwp_asan_state_ptr, uintptr_t gwp_asan_metadata_ptr,
const ThreadInfo& thread_info) {
if (!process_memory || !gwp_asan_metadata_ptr || !gwp_asan_state_ptr) return;
const ProcessInfo& process_info, const ThreadInfo& thread_info) {
if (!process_memory || !process_info.gwp_asan_metadata || !process_info.gwp_asan_state) return;
// Extract the GWP-ASan regions from the dead process.
if (!retrieve_gwp_asan_state(process_memory, gwp_asan_state_ptr, &state_)) return;
metadata_.reset(retrieve_gwp_asan_metadata(process_memory, state_, gwp_asan_metadata_ptr));
if (!retrieve_gwp_asan_state(process_memory, process_info.gwp_asan_state, &state_)) return;
metadata_.reset(retrieve_gwp_asan_metadata(process_memory, state_, process_info.gwp_asan_metadata));
if (!metadata_.get()) return;
// Get the external crash address from the thread info.

View file

@ -38,8 +38,8 @@ class GwpAsanCrashData {
// still be responsible, as it terminates when it detects an internal error
// (double free, invalid free). In these cases, we will retrieve the fault
// address from the GWP-ASan allocator's state.
GwpAsanCrashData(unwindstack::Memory* process_memory, uintptr_t gwp_asan_state_ptr,
uintptr_t gwp_asan_metadata_ptr, const ThreadInfo& thread_info);
GwpAsanCrashData(unwindstack::Memory* process_memory, const ProcessInfo& process_info,
const ThreadInfo& thread_info);
// Is GWP-ASan responsible for this crash.
bool CrashIsMine() const;

View file

@ -44,18 +44,13 @@ constexpr size_t kMaxFrames = 256;
int open_tombstone(std::string* path);
/* Creates a tombstone file and writes the crash dump to it. */
void engrave_tombstone(int tombstone_fd, unwindstack::Unwinder* unwinder,
const OpenFilesList* open_files, pid_t pid, pid_t tid,
const std::string& process_name, const std::map<pid_t, std::string>& threads,
uint64_t abort_msg_address, std::string* amfd_data);
void engrave_tombstone(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data);
void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
ucontext_t* ucontext);
void engrave_tombstone(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
uint64_t abort_msg_address, OpenFilesList* open_files,
std::string* amfd_data, uintptr_t gwp_asan_state,
uintptr_t gwp_asan_metadata);
#endif // _DEBUGGERD_TOMBSTONE_H

View file

@ -35,3 +35,10 @@ struct ThreadInfo {
int signo = 0;
siginfo_t* siginfo = nullptr;
};
struct ProcessInfo {
uintptr_t abort_msg_address = 0;
uintptr_t fdsan_table_address = 0;
uintptr_t gwp_asan_state = 0;
uintptr_t gwp_asan_metadata = 0;
};

View file

@ -371,7 +371,7 @@ public:
GwpAsanCrashDataTest(
gwp_asan::Error error,
const gwp_asan::AllocationMetadata *responsible_allocation) :
GwpAsanCrashData(nullptr, 0u, 0u, ThreadInfo{}) {
GwpAsanCrashData(nullptr, ProcessInfo{}, ThreadInfo{}) {
is_gwp_asan_responsible_ = true;
error_ = error;
responsible_allocation_ = responsible_allocation;

View file

@ -376,8 +376,7 @@ void dump_memory_and_code(log_t* log, unwindstack::Maps* maps, unwindstack::Memo
}
static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const ThreadInfo& thread_info,
uint64_t abort_msg_address, bool primary_thread,
const GwpAsanCrashData& gwp_asan_crash_data) {
const ProcessInfo& process_info, bool primary_thread) {
log->current_tid = thread_info.tid;
if (!primary_thread) {
_LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
@ -388,15 +387,21 @@ static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const Threa
dump_signal_info(log, thread_info, unwinder->GetProcessMemory().get());
}
if (primary_thread && gwp_asan_crash_data.CrashIsMine()) {
gwp_asan_crash_data.DumpCause(log);
std::unique_ptr<GwpAsanCrashData> gwp_asan_crash_data;
if (primary_thread) {
gwp_asan_crash_data = std::make_unique<GwpAsanCrashData>(unwinder->GetProcessMemory().get(),
process_info, thread_info);
}
if (primary_thread && gwp_asan_crash_data->CrashIsMine()) {
gwp_asan_crash_data->DumpCause(log);
} else if (thread_info.siginfo) {
dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps(),
thread_info.registers.get());
}
if (primary_thread) {
dump_abort_message(log, unwinder->GetProcessMemory().get(), abort_msg_address);
dump_abort_message(log, unwinder->GetProcessMemory().get(), process_info.abort_msg_address);
}
dump_registers(log, thread_info.registers.get());
@ -413,12 +418,12 @@ static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const Threa
}
if (primary_thread) {
if (gwp_asan_crash_data.HasDeallocationTrace()) {
gwp_asan_crash_data.DumpDeallocationTrace(log, unwinder);
if (gwp_asan_crash_data->HasDeallocationTrace()) {
gwp_asan_crash_data->DumpDeallocationTrace(log, unwinder);
}
if (gwp_asan_crash_data.HasAllocationTrace()) {
gwp_asan_crash_data.DumpAllocationTrace(log, unwinder);
if (gwp_asan_crash_data->HasAllocationTrace()) {
gwp_asan_crash_data->DumpAllocationTrace(log, unwinder);
}
unwindstack::Maps* maps = unwinder->GetMaps();
@ -601,15 +606,16 @@ void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, si
LOG(FATAL) << "Failed to init unwinder object.";
}
engrave_tombstone(unique_fd(dup(tombstone_fd)), &unwinder, threads, tid, abort_msg_address,
nullptr, nullptr, 0u, 0u);
ProcessInfo process_info;
process_info.abort_msg_address = abort_msg_address;
engrave_tombstone(unique_fd(dup(tombstone_fd)), &unwinder, threads, tid, process_info, nullptr,
nullptr);
}
void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
uint64_t abort_msg_address, OpenFilesList* open_files,
std::string* amfd_data, uintptr_t gwp_asan_state_ptr,
uintptr_t gwp_asan_metadata_ptr) {
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data) {
// don't copy log messages to tombstone unless this is a dev device
bool want_logs = android::base::GetBoolProperty("ro.debuggable", false);
@ -628,12 +634,7 @@ void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
LOG(FATAL) << "failed to find target thread";
}
GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(),
gwp_asan_state_ptr,
gwp_asan_metadata_ptr, it->second);
dump_thread(&log, unwinder, it->second, abort_msg_address, true,
gwp_asan_crash_data);
dump_thread(&log, unwinder, it->second, process_info, true);
if (want_logs) {
dump_logs(&log, it->second.pid, 50);
@ -644,7 +645,7 @@ void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
continue;
}
dump_thread(&log, unwinder, thread_info, 0, false, gwp_asan_crash_data);
dump_thread(&log, unwinder, thread_info, process_info, false);
}
if (open_files) {