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
This commit is contained in:
parent
4aa073337d
commit
a660cb3f13
|
@ -70,36 +70,6 @@ static void populate_timeval(struct timeval* tv, const Duration& duration) {
|
|||
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 @@ static std::string get_wchan_data(pid_t pid) {
|
|||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ void dump_backtrace_header(int output_fd) {
|
|||
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) {
|
||||
|
|
|
@ -83,8 +83,6 @@ void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* pref
|
|||
|
||||
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);
|
||||
|
|
|
@ -359,13 +359,6 @@ TEST_F(TombstoneTest, dump_thread_info_uid) {
|
|||
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(
|
||||
|
|
|
@ -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 @@ static void dump_header_info(log_t* log) {
|
|||
_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 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, unsigned
|
|||
// (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 @@ void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, si
|
|||
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 @@ void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
|
|||
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 @@ void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
|
|||
|
||||
_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()) {
|
||||
|
|
|
@ -226,23 +226,6 @@ void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const s
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "util.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -38,3 +39,19 @@ std::string get_thread_name(pid_t tid) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -23,3 +23,5 @@
|
|||
|
||||
std::string get_process_name(pid_t pid);
|
||||
std::string get_thread_name(pid_t tid);
|
||||
|
||||
std::string get_timestamp();
|
||||
|
|
Loading…
Reference in New Issue