diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp index fb274ec03..7b6f6c067 100644 --- a/debuggerd/Android.bp +++ b/debuggerd/Android.bp @@ -238,6 +238,7 @@ cc_library_static { "gwp_asan_crash_handler", "libscudo", "libtombstone_proto", + "libprocinfo", "libprotobuf-cpp-lite", ], diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp index 1ab93fe1d..3444e29e1 100644 --- a/debuggerd/libdebuggerd/tombstone_proto.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto.cpp @@ -31,10 +31,12 @@ #include #include +#include #include #include +#include #include #include #include @@ -47,6 +49,7 @@ #include #include +#include #include #include #include @@ -519,6 +522,14 @@ static void dump_logcat(Tombstone* tombstone, pid_t pid) { dump_log_file(tombstone, "main", pid); } +static std::optional read_uptime_secs() { + std::string uptime; + if (!android::base::ReadFileToString("/proc/uptime", &uptime)) { + return {}; + } + return strtoll(uptime.c_str(), nullptr, 10); +} + void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder, const std::map& threads, pid_t target_thread, const ProcessInfo& process_info, const OpenFilesList* open_files) { @@ -529,6 +540,22 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwind result.set_revision(android::base::GetProperty("ro.revision", "unknown")); result.set_timestamp(get_timestamp()); + std::optional system_uptime = read_uptime_secs(); + if (system_uptime) { + android::procinfo::ProcessInfo proc_info; + std::string error; + if (android::procinfo::GetProcessInfo(target_thread, &proc_info, &error)) { + uint64_t starttime = proc_info.starttime / sysconf(_SC_CLK_TCK); + result.set_process_uptime(*system_uptime - starttime); + } else { + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to read process info: %s", + error.c_str()); + } + } else { + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to read /proc/uptime: %s", + strerror(errno)); + } + const ThreadInfo& main_thread = threads.at(target_thread); result.set_pid(main_thread.pid); result.set_tid(main_thread.tid); diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp index e4dd6df1b..00ca7c18f 100644 --- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp @@ -360,6 +360,7 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) CBL("Revision: '%s'", tombstone.revision().c_str()); CBL("ABI: '%s'", abi_string(tombstone)); CBL("Timestamp: %s", tombstone.timestamp().c_str()); + CBL("Process uptime: %ds", tombstone.process_uptime()); // Process header const auto& threads = tombstone.threads(); diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto index 433c406ac..dd15ff637 100644 --- a/debuggerd/proto/tombstone.proto +++ b/debuggerd/proto/tombstone.proto @@ -19,6 +19,9 @@ message Tombstone { string process_name = 9; + // Process uptime in seconds. + uint32 process_uptime = 20; + Signal signal_info = 10; string abort_message = 14; repeated Cause causes = 15; @@ -28,7 +31,7 @@ message Tombstone { repeated LogBuffer log_buffers = 18; repeated FD open_fds = 19; - reserved 20 to 999; + reserved 21 to 999; } enum Architecture {