Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1281)

Unified Diff: snapshot/win/system_snapshot_win.cc

Issue 936333004: win: Add implementation of system_snapshot for Windows (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@add-time-win
Patch Set: . Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: snapshot/win/system_snapshot_win.cc
diff --git a/snapshot/win/system_snapshot_win.cc b/snapshot/win/system_snapshot_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c90582d2376d337086f4384c917e0484ef356a24
--- /dev/null
+++ b/snapshot/win/system_snapshot_win.cc
@@ -0,0 +1,293 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/win/system_snapshot_win.h"
+
+#include <immintrin.h>
Mark Mentovai 2015/02/27 22:27:42 Just <intrin.h>? I don’t see you using any multime
scottmg 2015/02/28 00:37:32 Done.
+#include <powrprof.h>
+#include <windows.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "compat/win/processor_power_information.h"
Mark Mentovai 2015/02/27 22:27:42 Things in compat should be treated as system heade
scottmg 2015/02/28 00:37:32 Done.
+
+namespace crashpad {
+
+namespace internal {
+
+SystemSnapshotWin::SystemSnapshotWin()
+ : SystemSnapshot(),
+ os_version_full_(),
+ os_version_build_(),
+ process_reader_(nullptr),
+ os_version_major_(0),
+ os_version_minor_(0),
+ os_version_bugfix_(0),
+ os_server_(false),
+ initialized_() {
+}
+
+SystemSnapshotWin::~SystemSnapshotWin() {
+}
+
+void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
+ INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+ process_reader_ = process_reader;
+
+ OSVERSIONINFOEX version_info = {sizeof(version_info)};
+ if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info))) {
Mark Mentovai 2015/02/27 22:27:42 The only concern here is that if the manifest does
scottmg 2015/02/28 00:37:32 Understood. I hunted a bit more and it seems the
+ PLOG(WARNING) << "GetVersionEx";
+ } else {
+ os_version_major_ = version_info.dwMajorVersion;
+ os_version_minor_ = version_info.dwMinorVersion;
+ os_version_bugfix_ = version_info.dwBuildNumber;
+ if (version_info.wServicePackMajor != 0) {
+ os_version_build_ =
+ base::StringPrintf("Service Pack %u", version_info.wServicePackMajor);
+ if (version_info.wServicePackMinor != 0) {
+ os_version_build_ +=
+ base::StringPrintf(".%u", version_info.wServicePackMinor);
+ }
+ }
+ os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
+ // TODO(scottmg): Is there something more we can retrieve here?
+ os_version_full_ = base::StringPrintf("Windows %d.%d.%d",
Mark Mentovai 2015/02/27 22:27:42 I asked if this should be Windows NT or if there w
scottmg 2015/02/28 00:37:32 Switched to using the dwFileOS field.
+ os_version_major_,
+ os_version_minor_,
+ os_version_bugfix_);
+ if (!os_version_build_.empty())
+ os_version_full_ += std::string(" ") + os_version_build_;
+ }
+
+ INITIALIZATION_STATE_SET_VALID(initialized_);
+}
+
+CPUArchitecture SystemSnapshotWin::GetCPUArchitecture() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
+ : kCPUArchitectureX86;
+}
+
+uint32_t SystemSnapshotWin::CPURevision() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ uint32_t raw = CPUX86Signature();
+ uint32_t stepping = raw & 0xf;
Mark Mentovai 2015/02/27 22:27:42 If you can stick this into a uint8_t… Same with 8
scottmg 2015/02/28 00:37:32 Done.
+ uint32_t model = (raw & 0xf0) >> 4;
+ uint32_t family = (raw & 0xf00) >> 8;
+ uint32_t extended_model = (raw & 0xf0000) >> 16;
+ uint32_t extended_family = (raw & 0xff00000) >> 20;
+
+ if (family < 15) {
+ // For families before 15, these are simply reserved bits so ignore them.
+ extended_model = 0;
Mark Mentovai 2015/02/27 22:27:42 extended_model is valid when family is 15 or 6.
scottmg 2015/02/28 00:37:32 Done.
+ extended_family = 0;
Mark Mentovai 2015/02/27 22:27:42 but this is correct for extended_family. See Inte
scottmg 2015/02/28 00:37:32 Oops, that'll teach me to use Wikipedia! http://en
+ }
+
+ uint32_t adjusted_family = family + extended_family;
+ uint32_t adjusted_model = model + (extended_model << 4);
+ return (adjusted_family << 16) | (adjusted_model << 8) | stepping;
+}
+
+uint8_t SystemSnapshotWin::CPUCount() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ if (!base::IsValueInRangeForNumericType<uint8_t>(
+ system_info.dwNumberOfProcessors)) {
+ LOG(WARNING) << "dwNumberOfProcessors exceeds uint8_t storage";
+ }
+ return base::saturated_cast<uint8_t>(system_info.dwNumberOfProcessors);
+}
+
+std::string SystemSnapshotWin::CPUVendor() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int cpu_info[4];
+ __cpuid(cpu_info, 0);
+ char vendor[12];
+ *reinterpret_cast<int*>(vendor) = cpu_info[1];
+ *reinterpret_cast<int*>(vendor + 4) = cpu_info[3];
+ *reinterpret_cast<int*>(vendor + 8) = cpu_info[2];
+ return std::string(vendor, sizeof(vendor));
+}
+
+void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
+ uint64_t* max_hz) const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int num_cpus = CPUCount();
+ DCHECK_GT(num_cpus, 0);
+ std::vector<PROCESSOR_POWER_INFORMATION> info(num_cpus);
+ if (CallNtPowerInformation(ProcessorInformation,
+ nullptr,
+ 0,
+ &info[0],
+ sizeof(PROCESSOR_POWER_INFORMATION) * num_cpus) !=
+ 0) {
+ *current_hz = 0;
+ *max_hz = 0;
+ return;
+ }
+ const uint64_t kMhzToHz = static_cast<uint64_t>(1E6);
+ *current_hz = std::max_element(info.begin(),
Mark Mentovai 2015/02/27 22:27:42 #include <utility>
scottmg 2015/02/28 00:37:32 Done.
+ info.end(),
+ [](const PROCESSOR_POWER_INFORMATION& a,
+ const PROCESSOR_POWER_INFORMATION& b) {
+ return a.CurrentMhz < b.CurrentMhz;
+ })->CurrentMhz *
+ kMhzToHz;
+ *max_hz = std::max_element(info.begin(),
+ info.end(),
+ [](const PROCESSOR_POWER_INFORMATION& a,
+ const PROCESSOR_POWER_INFORMATION& b) {
+ return a.MaxMhz < b.MaxMhz;
+ })->MaxMhz *
+ kMhzToHz;
+}
+
+uint32_t SystemSnapshotWin::CPUX86Signature() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int cpu_info[4];
+ // We will never run on any processors that don't support at least function 1.
+ __cpuid(cpu_info, 1);
+ return cpu_info[0];
+}
+
+uint64_t SystemSnapshotWin::CPUX86Features() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int cpu_info[4];
+ // We will never run on any processors that don't support at least function 1.
+ __cpuid(cpu_info, 1);
+ return (static_cast<uint64_t>(cpu_info[2]) << 32) |
+ static_cast<uint64_t>(cpu_info[3]);
+}
+
+uint64_t SystemSnapshotWin::CPUX86ExtendedFeatures() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int cpu_info[4];
+ // We will never run on any processors that don't support at least extended
+ // function 1.
+ __cpuid(cpu_info, 0x80000001);
+ return (static_cast<uint64_t>(cpu_info[2]) << 32) |
+ static_cast<uint64_t>(cpu_info[3]);
+}
+
+uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ int cpu_info[4];
+
+ // Make sure leaf 7 can be called.
+ __cpuid(cpu_info, 0);
+ if (cpu_info[0] < 7)
+ return 0;
+
+ __cpuidex(cpu_info, 7, 0);
+ return cpu_info[1];
+}
+
+bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ // The correct way to check for denormals-as-zeros (DAZ) support is to examine
+ // mxcsr mask, which can be done with fxsave. See Intel Software Developer's
+ // Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 "Checking for the
+ // DAZ Flag in the MXCSR Register". Note that since this function tests for
+ // DAZ support in the CPU, it checks the mxcsr mask. Testing mxcsr would
+ // indicate whether DAZ is actually enabled, which is a per-thread context
+ // concern.
+
+ // Test for fxsave support.
+ uint64_t features = CPUX86Features();
+ if (!(features & (UINT64_C(1) << 24))) {
+ return false;
+ }
+
+ // Call fxsave.
+ __declspec(align(16)) uint32_t extended_registers[128];
+ _fxsave(&extended_registers);
+ uint32_t mxcsr_mask = extended_registers[7];
+
+ // Test the DAZ bit.
+ return mxcsr_mask & (1 << 6);
+}
+
+SystemSnapshot::OperatingSystem SystemSnapshotWin::GetOperatingSystem() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ return kOperatingSystemWindows;
+}
+
+bool SystemSnapshotWin::OSServer() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ return os_server_;
+}
+
+void SystemSnapshotWin::OSVersion(int* major,
+ int* minor,
+ int* bugfix,
+ std::string* build) const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ *major = os_version_major_;
+ *minor = os_version_minor_;
+ *bugfix = os_version_bugfix_;
+ build->assign(os_version_build_);
+}
+
+std::string SystemSnapshotWin::OSVersionFull() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ return os_version_full_;
+}
+
+std::string SystemSnapshotWin::MachineDescription() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ // TODO(scottmg): Not sure if there's anything sensible to put here.
+ return std::string();
+}
+
+bool SystemSnapshotWin::NXEnabled() const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+ return IsProcessorFeaturePresent(PF_NX_ENABLED);
+}
+
+void SystemSnapshotWin::TimeZone(DaylightSavingTimeStatus* dst_status,
+ int* standard_offset_seconds,
+ int* daylight_offset_seconds,
+ std::string* standard_name,
+ std::string* daylight_name) const {
+ // This returns the current time zone status rather than the status at the
+ // time of the snapshot. This differs from the Mac implementation.
+ TIME_ZONE_INFORMATION time_zone_information;
+ *dst_status = static_cast<DaylightSavingTimeStatus>(
+ GetTimeZoneInformation(&time_zone_information));
+ *standard_offset_seconds =
+ (time_zone_information.Bias + time_zone_information.StandardBias) * -60;
+ *daylight_offset_seconds =
+ (time_zone_information.Bias + time_zone_information.DaylightBias) * -60;
+ *standard_name = base::UTF16ToUTF8(time_zone_information.StandardName);
+ *daylight_name = base::UTF16ToUTF8(time_zone_information.DaylightName);
+}
+
+} // namespace internal
+} // namespace crashpad

Powered by Google App Engine
This is Rietveld 408576698