crash_dump: pass the address of the fdsan table.
Pass the address of the fdsan table down to crash_dump so that we can
dump the fdsan table along with the open file descriptor list.
Test: debuggerd_test
Test: manually ran an old static_crasher
Change-Id: Icbac5487109f2db1e1061c4d46de11b016b299e3
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 1b20157..385f385 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -43,7 +43,7 @@
export_include_dirs: ["tombstoned/include"],
}
-// Utility library to tombstoned and get an output fd.
+// Utility library to talk to tombstoned and get an output fd.
cc_library_static {
name: "libtombstoned_client_static",
defaults: ["debuggerd_defaults"],
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 40cf6c3..43b7e05 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -249,24 +249,48 @@
}
static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
- std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_address) {
+ std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_msg_address,
+ uintptr_t* fdsan_table_address) {
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)));
if (rc == -1) {
PLOG(FATAL) << "failed to read target ucontext";
- } else if (rc != sizeof(CrashInfo)) {
- LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
- << sizeof(CrashInfo);
+ } else {
+ ssize_t expected_size = 0;
+ switch (crash_info->header.version) {
+ case 1:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV1);
+ break;
+
+ case 2:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV2);
+ break;
+
+ default:
+ LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
+ break;
+ };
+
+ if (rc != expected_size) {
+ LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
+ << expected_size;
+ }
}
- CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
- if (crash_info->version != 1) {
- LOG(FATAL) << "version mismatch, expected 1, received " << crash_info->version;
- }
+ *fdsan_table_address = 0;
+ switch (crash_info->header.version) {
+ case 2:
+ *fdsan_table_address = crash_info->data.v2.fdsan_table_address;
+ case 1:
+ *abort_msg_address = crash_info->data.v1.abort_msg_address;
+ *siginfo = crash_info->data.v1.siginfo;
+ regs->reset(Regs::CreateFromUcontext(Regs::CurrentArch(), &crash_info->data.v1.ucontext));
+ break;
- *siginfo = crash_info->siginfo;
- regs->reset(Regs::CreateFromUcontext(Regs::CurrentArch(), &crash_info->ucontext));
- *abort_address = crash_info->abort_msg_address;
+ default:
+ __builtin_unreachable();
+ }
}
// Wait for a process to clone and return the child's pid.
@@ -369,7 +393,8 @@
ATRACE_NAME("after reparent");
pid_t pseudothread_tid;
DebuggerdDumpType dump_type;
- uintptr_t abort_address = 0;
+ uintptr_t abort_msg_address = 0;
+ uintptr_t fdsan_table_address = 0;
Initialize(argv);
ParseArgs(argc, argv, &pseudothread_tid, &dump_type);
@@ -429,7 +454,8 @@
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_address);
+ ReadCrashInfo(input_pipe, &siginfo, &info.registers, &abort_msg_address,
+ &fdsan_table_address);
info.siginfo = &siginfo;
info.signo = info.siginfo->si_signo;
} else {
@@ -504,8 +530,8 @@
g_output_fd = std::move(devnull);
}
- LOG(INFO) << "performing dump of process " << target_process << " (target tid = " << g_target_thread
- << ")";
+ LOG(INFO) << "performing dump of process " << target_process
+ << " (target tid = " << g_target_thread << ")";
int signo = siginfo.si_signo;
bool fatal_signal = signo != DEBUGGER_SIGNAL;
@@ -543,7 +569,7 @@
} else {
ATRACE_NAME("engrave_tombstone");
engrave_tombstone(std::move(g_output_fd), map.get(), process_memory.get(), thread_info,
- g_target_thread, abort_address, &open_files, &amfd_data);
+ g_target_thread, abort_msg_address, &open_files, &amfd_data);
}
if (fatal_signal) {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 615fb46..91e6f71 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -108,6 +108,7 @@
int saved_errno_;
};
+extern "C" void* android_fdsan_get_fd_table();
extern "C" void debuggerd_fallback_handler(siginfo_t*, ucontext_t*, void*);
static debuggerd_callbacks_t g_callbacks;
@@ -286,6 +287,7 @@
siginfo_t* siginfo;
void* ucontext;
uintptr_t abort_msg;
+ uintptr_t fdsan_table;
};
// Logging and contacting debuggerd requires free file descriptors, which we might not have.
@@ -330,23 +332,23 @@
}
// ucontext_t is absurdly large on AArch64, so piece it together manually with writev.
- uint32_t version = 1;
- constexpr size_t expected =
- sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(uintptr_t);
+ uint32_t version = 2;
+ constexpr size_t expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV2);
errno = 0;
if (fcntl(output_write.get(), F_SETPIPE_SZ, expected) < static_cast<int>(expected)) {
- fatal_errno("failed to set pipe bufer size");
+ fatal_errno("failed to set pipe buffer size");
}
- struct iovec iovs[4] = {
+ struct iovec iovs[5] = {
{.iov_base = &version, .iov_len = sizeof(version)},
{.iov_base = thread_info->siginfo, .iov_len = sizeof(siginfo_t)},
{.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
{.iov_base = &thread_info->abort_msg, .iov_len = sizeof(uintptr_t)},
+ {.iov_base = &thread_info->fdsan_table, .iov_len = sizeof(uintptr_t)},
};
- ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 4));
+ ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 5));
if (rc == -1) {
fatal_errno("failed to write crash info");
} else if (rc != expected) {
@@ -504,6 +506,7 @@
.siginfo = info,
.ucontext = context,
.abort_msg = reinterpret_cast<uintptr_t>(abort_message),
+ .fdsan_table = reinterpret_cast<uintptr_t>(android_fdsan_get_fd_table()),
};
// Set PR_SET_DUMPABLE to 1, so that crash_dump can ptrace us.
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index 6903b0e..bfd0fbb 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -81,9 +81,24 @@
};
// Sent from handler to crash_dump via pipe.
-struct __attribute__((__packed__)) CrashInfo {
- uint32_t version; // must be 1.
+struct __attribute__((__packed__)) CrashInfoHeader {
+ uint32_t version;
+};
+
+struct __attribute__((__packed__)) CrashInfoDataV1 {
siginfo_t siginfo;
ucontext_t ucontext;
uintptr_t abort_msg_address;
};
+
+struct __attribute__((__packed__)) CrashInfoDataV2 : public CrashInfoDataV1 {
+ uintptr_t fdsan_table_address;
+};
+
+struct __attribute__((__packed__)) CrashInfo {
+ CrashInfoHeader header;
+ union {
+ CrashInfoDataV1 v1;
+ CrashInfoDataV2 v2;
+ } data;
+};