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:
parent
ad9d034e7d
commit
843f7e645d
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue