debuggerd: store commandline instead of process name.

Bug: http://b/180605583
Test: debuggerd_test
Change-Id: I018d399a5460f357766dc1b429f645f78fe88565
This commit is contained in:
Josh Gao 2021-03-29 21:53:42 -07:00
parent 5d5e16db57
commit 31348a74e0
11 changed files with 63 additions and 23 deletions

View file

@ -96,7 +96,7 @@ static std::string get_wchan_data(pid_t pid) {
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";

View file

@ -450,9 +450,6 @@ int main(int argc, char** argv) {
// 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 @@ int main(int argc, char** argv) {
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 @@ int main(int argc, char** argv) {
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) {

View file

@ -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 @@ void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* u
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 @@ void dump_backtrace_header(int output_fd) {
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) {

View file

@ -18,6 +18,7 @@
#include <memory>
#include <string>
#include <vector>
#include <unwindstack/Regs.h>
@ -32,13 +33,14 @@ struct ThreadInfo {
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;

View file

@ -350,11 +350,11 @@ TEST_F(TombstoneTest, dump_header_info) {
}
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());
}

View file

@ -182,8 +182,13 @@ static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
// 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 @@ void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_m
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 @@ void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_m
.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,
};

View file

@ -562,7 +562,11 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwind
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");
}

View file

@ -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 int pointer_width(const Tombstone& tombstone) {
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());

View file

@ -17,7 +17,7 @@ message Tombstone {
uint32 uid = 7;
string selinux_label = 8;
string process_name = 9;
repeated string command_line = 9;
// Process uptime in seconds.
uint32 process_uptime = 20;

View file

@ -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) {

View file

@ -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);