debuggerd: use One True timestamp function.

An OEM asks for sub-second granularity, and that's most easily done if
we only have one timestamp generator. I'm not convinced sub-second
granularity is particularly useful myself, and I definitely don't think
that nanosecond resolution is meaningful but I do like this cleanup, and
if I'm going to use sub-second precision I may as well use the maximum
precision available to me.

Also reduce some duplication of code reading cmdline/comm.

Bug: https://issuetracker.google.com/161860597
Test: head /data/tombstones/*
Change-Id: I035ecfd4a3338ccd84dae0ef973a998a7c7c5056
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 5c02738..6bfb5f2 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -70,36 +70,6 @@
   tv->tv_usec = static_cast<long>(microseconds.count());
 }
 
-static void get_wchan_header(pid_t pid, std::stringstream& buffer) {
-  struct tm now;
-  time_t t = time(nullptr);
-  localtime_r(&t, &now);
-  char timestamp[32];
-  strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &now);
-  std::string time_now(timestamp);
-
-  std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
-
-  char proc_name_buf[1024];
-  const char* proc_name = nullptr;
-  std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path.c_str(), "r"), &fclose);
-
-  if (fp) {
-    proc_name = fgets(proc_name_buf, sizeof(proc_name_buf), fp.get());
-  }
-
-  if (!proc_name) {
-    proc_name = "<unknown>";
-  }
-
-  buffer << "\n----- Waiting Channels: pid " << pid << " at " << time_now << " -----\n"
-         << "Cmd line: " << proc_name << "\n";
-}
-
-static void get_wchan_footer(pid_t pid, std::stringstream& buffer) {
-  buffer << "----- end " << std::to_string(pid) << " -----\n";
-}
-
 /**
  * Returns the wchan data for each thread in the process,
  * or empty string if unable to obtain any data.
@@ -125,9 +95,10 @@
   }
 
   if (std::string str = data.str(); !str.empty()) {
-    get_wchan_header(pid, buffer);
+    buffer << "\n----- Waiting Channels: pid " << pid << " at " << get_timestamp() << " -----\n"
+           << "Cmd line: " << get_process_name(pid) << "\n";
     buffer << "\n" << str << "\n";
-    get_wchan_footer(pid, buffer);
+    buffer << "----- end " << std::to_string(pid) << " -----\n";
     buffer << "\n";
   }
 
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index c606970..f5a873c 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <sys/ptrace.h>
 #include <sys/types.h>
-#include <time.h>
 #include <unistd.h>
 
 #include <map>
@@ -40,14 +39,10 @@
 
 #include "libdebuggerd/types.h"
 #include "libdebuggerd/utility.h"
+#include "util.h"
 
 static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
-  time_t t = time(NULL);
-  struct tm tm;
-  localtime_r(&t, &tm);
-  char timestr[64];
-  strftime(timestr, sizeof(timestr), "%F %T", &tm);
-  _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr);
+  _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);
@@ -106,9 +101,8 @@
   log.tfd = output_fd;
   log.amfd_data = nullptr;
 
-  char process_name[128];
-  read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
-  dump_process_header(&log, getpid(), process_name);
+  pid_t pid = getpid();
+  dump_process_header(&log, pid, get_process_name(pid).c_str());
 }
 
 void dump_backtrace_footer(int output_fd) {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 7bfcf5d..76155b1 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -83,8 +83,6 @@
 
 void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const std::string&);
 
-void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
-
 void drop_capabilities();
 
 bool signal_has_sender(const siginfo_t*, pid_t caller_pid);
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index aec8c60..b42d70c 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -359,13 +359,6 @@
   ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
 }
 
-TEST_F(TombstoneTest, dump_timestamp) {
-  setenv("TZ", "UTC", 1);
-  tzset();
-  dump_timestamp(&log_, 0);
-  ASSERT_STREQ("Timestamp: 1970-01-01 00:00:00+0000\n", amfd_data_.c_str());
-}
-
 class GwpAsanCrashDataTest : public GwpAsanCrashData {
 public:
   GwpAsanCrashDataTest(
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index ab65dd1..face02b 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -58,6 +58,7 @@
 #include "libdebuggerd/open_files_list.h"
 #include "libdebuggerd/scudo.h"
 #include "libdebuggerd/utility.h"
+#include "util.h"
 
 #include "gwp_asan/common.h"
 #include "gwp_asan/crash_handler.h"
@@ -80,15 +81,6 @@
   _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
 }
 
-static void dump_timestamp(log_t* log, time_t time) {
-  struct tm tm;
-  localtime_r(&time, &tm);
-
-  char buf[strlen("1970-01-01 00:00:00+0830") + 1];
-  strftime(buf, sizeof(buf), "%F %T%z", &tm);
-  _LOG(log, logtype::HEADER, "Timestamp: %s\n", buf);
-}
-
 static std::string get_stack_overflow_cause(uint64_t fault_addr, uint64_t sp,
                                             unwindstack::Maps* maps) {
   static constexpr uint64_t kMaxDifferenceBytes = 256;
@@ -507,10 +499,9 @@
     // (although in this case the pid is redundant).
     char timeBuf[32];
     time_t sec = static_cast<time_t>(log_entry.entry.sec);
-    struct tm tmBuf;
-    struct tm* ptm;
-    ptm = localtime_r(&sec, &tmBuf);
-    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
+    tm tm;
+    localtime_r(&sec, &tm);
+    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", &tm);
 
     char* msg = log_entry.msg();
     if (msg == nullptr) {
@@ -571,23 +562,20 @@
   log.tfd = tombstone_fd;
   log.amfd_data = nullptr;
 
-  char thread_name[16];
-  char process_name[128];
-
-  read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
-  read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
+  std::string thread_name = get_thread_name(tid);
+  std::string process_name = get_process_name(pid);
 
   std::unique_ptr<unwindstack::Regs> regs(
       unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
 
   std::map<pid_t, ThreadInfo> threads;
-  threads[gettid()] = ThreadInfo{
+  threads[tid] = ThreadInfo{
       .registers = std::move(regs),
       .uid = uid,
       .tid = tid,
-      .thread_name = thread_name,
+      .thread_name = thread_name.c_str(),
       .pid = pid,
-      .process_name = process_name,
+      .process_name = process_name.c_str(),
       .siginfo = siginfo,
   };
 
@@ -606,8 +594,8 @@
                        const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                        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);
+  // Don't copy log messages to tombstone unless this is a development device.
+  bool want_logs = GetBoolProperty("ro.debuggable", false);
 
   log_t log;
   log.current_tid = target_thread;
@@ -617,7 +605,7 @@
 
   _LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
   dump_header_info(&log);
-  dump_timestamp(&log, time(nullptr));
+  _LOG(&log, logtype::HEADER, "Timestamp: %s\n", get_timestamp().c_str());
 
   auto it = threads.find(target_thread);
   if (it == threads.end()) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index c8a3431..92d1da3 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -226,23 +226,6 @@
   }
 }
 
-void read_with_default(const char* path, char* buf, size_t len, const char* default_value) {
-  unique_fd fd(open(path, O_RDONLY | O_CLOEXEC));
-  if (fd != -1) {
-    int rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, len - 1));
-    if (rc != -1) {
-      buf[rc] = '\0';
-
-      // Trim trailing newlines.
-      if (rc > 0 && buf[rc - 1] == '\n') {
-        buf[rc - 1] = '\0';
-      }
-      return;
-    }
-  }
-  strcpy(buf, default_value);
-}
-
 void drop_capabilities() {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index a37b3b9..9d09210 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -17,6 +17,7 @@
 #include "util.h"
 
 #include <sys/socket.h>
+#include <time.h>
 
 #include <string>
 #include <utility>
@@ -38,3 +39,19 @@
   android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/comm", tid), &result);
   return android::base::Trim(result);
 }
+
+std::string get_timestamp() {
+  timespec ts;
+  clock_gettime(CLOCK_REALTIME, &ts);
+
+  tm tm;
+  localtime_r(&ts.tv_sec, &tm);
+
+  char buf[strlen("1970-01-01 00:00:00.123456789+0830") + 1];
+  char* s = buf;
+  size_t sz = sizeof(buf), n;
+  n = strftime(s, sz, "%F %H:%M", &tm), s += n, sz -= n;
+  n = snprintf(s, sz, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec), s += n, sz -= n;
+  n = strftime(s, sz, "%z", &tm), s += n, sz -= n;
+  return buf;
+}
diff --git a/debuggerd/util.h b/debuggerd/util.h
index e964423..07e7e99 100644
--- a/debuggerd/util.h
+++ b/debuggerd/util.h
@@ -23,3 +23,5 @@
 
 std::string get_process_name(pid_t pid);
 std::string get_thread_name(pid_t tid);
+
+std::string get_timestamp();