debuggerd: store commandline instead of process name.
Bug: http://b/180605583
Test: debuggerd_test
Change-Id: I018d399a5460f357766dc1b429f645f78fe88565
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 6bfb5f2..530e0e8 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -96,7 +96,7 @@
if (std::string str = data.str(); !str.empty()) {
buffer << "\n----- Waiting Channels: pid " << pid << " at " << get_timestamp() << " -----\n"
- << "Cmd line: " << get_process_name(pid) << "\n";
+ << "Cmd line: " << android::base::Join(get_command_line(pid), " ") << "\n";
buffer << "\n" << str << "\n";
buffer << "----- end " << std::to_string(pid) << " -----\n";
buffer << "\n";
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 04e1e4e..a152740 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -450,9 +450,6 @@
// unwind, do not make this too small. b/62828735
alarm(30 * android::base::HwTimeoutMultiplier());
- // Get the process name (aka cmdline).
- std::string process_name = get_process_name(g_target_thread);
-
// Collect the list of open files.
OpenFilesList open_files;
{
@@ -489,7 +486,6 @@
info.pid = target_process;
info.tid = thread;
info.uid = getuid();
- info.process_name = process_name;
info.thread_name = get_thread_name(thread);
unique_fd attr_fd(openat(target_proc_fd, "attr/current", O_RDONLY | O_CLOEXEC));
@@ -517,6 +513,8 @@
ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info);
info.siginfo = &siginfo;
info.signo = info.siginfo->si_signo;
+
+ info.command_line = get_command_line(g_target_thread);
} else {
info.registers.reset(unwindstack::Regs::RemoteGet(thread));
if (!info.registers) {
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index c543a83..fd91038 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -34,6 +34,7 @@
#include <memory>
#include <string>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <log/log.h>
#include <unwindstack/Unwinder.h>
@@ -42,11 +43,12 @@
#include "libdebuggerd/utility.h"
#include "util.h"
-static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
+static void dump_process_header(log_t* log, pid_t pid,
+ const std::vector<std::string>& command_line) {
_LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, get_timestamp().c_str());
- if (process_name) {
- _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name);
+ if (!command_line.empty()) {
+ _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", android::base::Join(command_line, " ").c_str());
}
_LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING);
}
@@ -89,7 +91,7 @@
return;
}
- dump_process_header(&log, target->second.pid, target->second.process_name.c_str());
+ dump_process_header(&log, target->second.pid, target->second.command_line);
dump_backtrace_thread(output_fd.get(), unwinder, target->second);
for (const auto& [tid, info] : thread_info) {
@@ -107,7 +109,7 @@
log.amfd_data = nullptr;
pid_t pid = getpid();
- dump_process_header(&log, pid, get_process_name(pid).c_str());
+ dump_process_header(&log, pid, get_command_line(pid));
}
void dump_backtrace_footer(int output_fd) {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index dcb52f9..086dc97 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -18,6 +18,7 @@
#include <memory>
#include <string>
+#include <vector>
#include <unwindstack/Regs.h>
@@ -32,13 +33,14 @@
pid_t pid;
- std::string process_name;
+ std::vector<std::string> command_line;
std::string selinux_label;
int signo = 0;
siginfo_t* siginfo = nullptr;
};
+// This struct is written into a pipe from inside the crashing process.
struct ProcessInfo {
uintptr_t abort_msg_address = 0;
uintptr_t fdsan_table_address = 0;
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 79ac122..a14dcb0 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -350,11 +350,11 @@
}
TEST_F(TombstoneTest, dump_thread_info_uid) {
- dump_thread_info(&log_, ThreadInfo{.uid = 1,
- .tid = 3,
- .thread_name = "some_thread",
- .pid = 2,
- .process_name = "some_process"});
+ std::vector<std::string> cmdline = {"some_process"};
+ dump_thread_info(
+ &log_,
+ ThreadInfo{
+ .uid = 1, .tid = 3, .thread_name = "some_thread", .pid = 2, .command_line = cmdline});
std::string expected = "pid: 2, tid: 3, name: some_thread >>> some_process <<<\nuid: 1\n";
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 4f75ff1..e0cc662 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -182,8 +182,13 @@
// Don't try to collect logs from the threads that implement the logging system itself.
if (thread_info.uid == AID_LOGD) log->should_retrieve_logcat = false;
+ const char* process_name = "<unknown>";
+ if (!thread_info.command_line.empty()) {
+ process_name = thread_info.command_line[0].c_str();
+ }
+
_LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s >>> %s <<<\n", thread_info.pid,
- thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str());
+ thread_info.tid, thread_info.thread_name.c_str(), process_name);
_LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid);
if (thread_info.tagged_addr_ctrl != -1) {
_LOG(log, logtype::HEADER, "tagged_addr_ctrl: %016lx\n", thread_info.tagged_addr_ctrl);
@@ -567,7 +572,7 @@
log.amfd_data = nullptr;
std::string thread_name = get_thread_name(tid);
- std::string process_name = get_process_name(pid);
+ std::vector<std::string> command_line = get_command_line(pid);
std::unique_ptr<unwindstack::Regs> regs(
unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
@@ -582,7 +587,7 @@
.tid = tid,
.thread_name = std::move(thread_name),
.pid = pid,
- .process_name = std::move(process_name),
+ .command_line = std::move(command_line),
.selinux_label = std::move(selinux_label),
.siginfo = siginfo,
};
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 3444e29..7657001 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -562,7 +562,11 @@
result.set_uid(main_thread.uid);
result.set_selinux_label(main_thread.selinux_label);
- result.set_process_name(main_thread.process_name);
+ auto cmd_line = result.mutable_command_line();
+ for (const auto& arg : main_thread.command_line) {
+ *cmd_line->Add() = arg;
+ }
+
if (!main_thread.siginfo) {
async_safe_fatal("siginfo missing");
}
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 00ca7c1..020b0a5 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -26,6 +26,7 @@
#include <vector>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <async_safe/log.h>
@@ -71,8 +72,13 @@
static void print_thread_header(CallbackType callback, const Tombstone& tombstone,
const Thread& thread, bool should_log) {
+ const char* process_name = "<unknown>";
+ if (!tombstone.command_line().empty()) {
+ process_name = tombstone.command_line()[0].c_str();
+ CB(should_log, "Cmdline: %s", android::base::Join(tombstone.command_line(), " ").c_str());
+ }
CB(should_log, "pid: %d, tid: %d, name: %s >>> %s <<<", tombstone.pid(), thread.id(),
- thread.name().c_str(), tombstone.process_name().c_str());
+ thread.name().c_str(), process_name);
CB(should_log, "uid: %d", tombstone.uid());
if (thread.tagged_addr_ctrl() != -1) {
CB(should_log, "tagged_addr_ctrl: %016" PRIx64, thread.tagged_addr_ctrl());
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index dd15ff6..294e4e5 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -17,7 +17,7 @@
uint32 uid = 7;
string selinux_label = 8;
- string process_name = 9;
+ repeated string command_line = 9;
// Process uptime in seconds.
uint32 process_uptime = 20;
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index f3bff8c..ce0fd30 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -26,10 +26,31 @@
#include <android-base/strings.h>
#include "protocol.h"
+std::vector<std::string> get_command_line(pid_t pid) {
+ std::vector<std::string> result;
+
+ std::string cmdline;
+ android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &cmdline);
+
+ auto it = cmdline.cbegin();
+ while (it != cmdline.cend()) {
+ // string::iterator is a wrapped type, not a raw char*.
+ auto terminator = std::find(it, cmdline.cend(), '\0');
+ result.emplace_back(it, terminator);
+ it = std::find_if(terminator, cmdline.cend(), [](char c) { return c != '\0'; });
+ }
+ if (result.empty()) {
+ result.emplace_back("<unknown>");
+ }
+
+ return result;
+}
+
std::string get_process_name(pid_t pid) {
std::string result = "<unknown>";
android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &result);
- return result;
+ // We only want the name, not the whole command line, so truncate at the first NUL.
+ return result.c_str();
}
std::string get_thread_name(pid_t tid) {
diff --git a/debuggerd/util.h b/debuggerd/util.h
index 07e7e99..ec2862a 100644
--- a/debuggerd/util.h
+++ b/debuggerd/util.h
@@ -17,10 +17,12 @@
#pragma once
#include <string>
+#include <vector>
#include <sys/cdefs.h>
#include <sys/types.h>
+std::vector<std::string> get_command_line(pid_t pid);
std::string get_process_name(pid_t pid);
std::string get_thread_name(pid_t tid);