win: Add support for CPUTimes and StartTime to snapshot

Follows https://codereview.chromium.org/1120383003/.

R=mark@chromium.org
BUG=crashpad:1

Review URL: https://codereview.chromium.org/1119393003
This commit is contained in:
Scott Graham 2015-05-06 11:13:44 -07:00
parent ff52791faf
commit 06db728457
5 changed files with 82 additions and 9 deletions

View File

@ -15,6 +15,7 @@
#include "snapshot/win/process_reader_win.h" #include "snapshot/win/process_reader_win.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "util/win/time.h"
namespace crashpad { namespace crashpad {
@ -54,6 +55,28 @@ bool ProcessReaderWin::ReadMemory(WinVMAddress at,
return true; return true;
} }
bool ProcessReaderWin::StartTime(timeval* start_time) const {
FILETIME creation, exit, kernel, user;
if (!GetProcessTimes(process_, &creation, &exit, &kernel, &user)) {
PLOG(ERROR) << "GetProcessTimes";
return false;
}
*start_time = FiletimeToTimevalEpoch(creation);
return true;
}
bool ProcessReaderWin::CPUTimes(timeval* user_time,
timeval* system_time) const {
FILETIME creation, exit, kernel, user;
if (!GetProcessTimes(process_, &creation, &exit, &kernel, &user)) {
PLOG(ERROR) << "GetProcessTimes";
return false;
}
*user_time = FiletimeToTimevalInterval(user);
*system_time = FiletimeToTimevalInterval(kernel);
return true;
}
const std::vector<ProcessInfo::Module>& ProcessReaderWin::Modules() { const std::vector<ProcessInfo::Module>& ProcessReaderWin::Modules() {
INITIALIZATION_STATE_DCHECK_VALID(initialized_); INITIALIZATION_STATE_DCHECK_VALID(initialized_);

View File

@ -15,6 +15,7 @@
#ifndef CRASHPAD_SNAPSHOT_WIN_PROCESS_READER_WIN_H_ #ifndef CRASHPAD_SNAPSHOT_WIN_PROCESS_READER_WIN_H_
#define CRASHPAD_SNAPSHOT_WIN_PROCESS_READER_WIN_H_ #define CRASHPAD_SNAPSHOT_WIN_PROCESS_READER_WIN_H_
#include <sys/time.h>
#include <windows.h> #include <windows.h>
#include "util/misc/initialization_state_dcheck.h" #include "util/misc/initialization_state_dcheck.h"
@ -48,6 +49,23 @@ class ProcessReaderWin {
bool ReadMemory(WinVMAddress at, WinVMSize num_bytes, void* into); bool ReadMemory(WinVMAddress at, WinVMSize num_bytes, void* into);
//! \brief Determines the target process' start time.
//!
//! \param[out] start_time The time that the process started.
//!
//! \return `true` on success, `false` on failure, with a warning logged.
bool StartTime(timeval* start_time) const;
//! \brief Determines the target process' execution time.
//!
//! \param[out] user_time The amount of time the process has executed code in
//! user mode.
//! \param[out] system_time The amount of time the process has executed code
//! in kernel mode.
//!
//! \return `true` on success, `false` on failure, with a warning logged.
bool CPUTimes(timeval* user_time, timeval* system_time) const;
//! \return The modules loaded in the process. The first element (at index //! \return The modules loaded in the process. The first element (at index
//! `0`) corresponds to the main executable. //! `0`) corresponds to the main executable.
const std::vector<ProcessInfo::Module>& Modules(); const std::vector<ProcessInfo::Module>& Modules();

View File

@ -99,12 +99,14 @@ void ProcessSnapshotWin::SnapshotTime(timeval* snapshot_time) const {
} }
void ProcessSnapshotWin::ProcessStartTime(timeval* start_time) const { void ProcessSnapshotWin::ProcessStartTime(timeval* start_time) const {
CHECK(false) << "TODO(scottmg)"; INITIALIZATION_STATE_DCHECK_VALID(initialized_);
process_reader_.StartTime(start_time);
} }
void ProcessSnapshotWin::ProcessCPUTimes(timeval* user_time, void ProcessSnapshotWin::ProcessCPUTimes(timeval* user_time,
timeval* system_time) const { timeval* system_time) const {
CHECK(false) << "TODO(scottmg)"; INITIALIZATION_STATE_DCHECK_VALID(initialized_);
process_reader_.CPUTimes(user_time, system_time);
} }
void ProcessSnapshotWin::ReportID(UUID* report_id) const { void ProcessSnapshotWin::ReportID(UUID* report_id) const {

View File

@ -15,15 +15,25 @@
#include "util/win/time.h" #include "util/win/time.h"
#include <inttypes.h> #include <inttypes.h>
#include <windows.h>
#include "base/logging.h" #include "base/logging.h"
namespace crashpad { namespace crashpad {
void GetTimeOfDay(timeval* tv) { namespace {
FILETIME filetime;
GetSystemTimeAsFileTime(&filetime); const uint64_t kMicrosecondsPerSecond = static_cast<uint64_t>(1E6);
timeval MicrosecondsToTimeval(uint64_t t) {
timeval tv;
tv.tv_sec = static_cast<long>(t / kMicrosecondsPerSecond);
tv.tv_usec = static_cast<long>(t % kMicrosecondsPerSecond);
return tv;
}
} // namespace
timeval FiletimeToTimevalEpoch(const FILETIME& filetime) {
uint64_t t = (static_cast<uint64_t>(filetime.dwHighDateTime) << 32) | uint64_t t = (static_cast<uint64_t>(filetime.dwHighDateTime) << 32) |
filetime.dwLowDateTime; filetime.dwLowDateTime;
t /= 10; // 100 nanosecond intervals to microseconds. t /= 10; // 100 nanosecond intervals to microseconds.
@ -32,11 +42,22 @@ void GetTimeOfDay(timeval* tv) {
// day. It's not entirely clear, but it appears that these are solar seconds, // day. It's not entirely clear, but it appears that these are solar seconds,
// not SI seconds, so there are no leap seconds to be considered. // not SI seconds, so there are no leap seconds to be considered.
const uint64_t kNumSecondsFrom1601To1970 = (369 * 365 + 89) * 86400ULL; const uint64_t kNumSecondsFrom1601To1970 = (369 * 365 + 89) * 86400ULL;
const uint64_t kMicrosecondsPerSecond = static_cast<uint64_t>(1E6);
DCHECK_GE(t, kNumSecondsFrom1601To1970 * kMicrosecondsPerSecond); DCHECK_GE(t, kNumSecondsFrom1601To1970 * kMicrosecondsPerSecond);
t -= kNumSecondsFrom1601To1970 * kMicrosecondsPerSecond; t -= kNumSecondsFrom1601To1970 * kMicrosecondsPerSecond;
tv->tv_sec = static_cast<long>(t / kMicrosecondsPerSecond); return MicrosecondsToTimeval(t);
tv->tv_usec = static_cast<long>(t % kMicrosecondsPerSecond); }
timeval FiletimeToTimevalInterval(const FILETIME& filetime) {
uint64_t t = (static_cast<uint64_t>(filetime.dwHighDateTime) << 32) |
filetime.dwLowDateTime;
t /= 10; // 100 nanosecond intervals to microseconds.
return MicrosecondsToTimeval(t);
}
void GetTimeOfDay(timeval* tv) {
FILETIME filetime;
GetSystemTimeAsFileTime(&filetime);
*tv = FiletimeToTimevalEpoch(filetime);
} }
} // namespace crashpad } // namespace crashpad

View File

@ -16,9 +16,18 @@
#define CRASHPAD_UTIL_WIN_TIME_H_ #define CRASHPAD_UTIL_WIN_TIME_H_
#include <sys/time.h> #include <sys/time.h>
#include <windows.h>
namespace crashpad { namespace crashpad {
//! \brief Convert Windows `FILETIME` to `timeval`, converting from Windows
//! epoch to POSIX epoch.
timeval FiletimeToTimevalEpoch(const FILETIME& filetime);
//! \brief Convert Windows `FILETIME` to `timeval`, treating the values as
//! an interval of elapsed time.
timeval FiletimeToTimevalInterval(const FILETIME& filetime);
//! \brief Similar to POSIX gettimeofday(), gets the current system time in UTC. //! \brief Similar to POSIX gettimeofday(), gets the current system time in UTC.
void GetTimeOfDay(timeval* tv); void GetTimeOfDay(timeval* tv);