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

Side by Side 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: fixes Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « snapshot/win/system_snapshot_win.h ('k') | snapshot/win/system_snapshot_win_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "snapshot/win/system_snapshot_win.h"
16
17 #include <intrin.h>
18 #include <powrprof.h>
19 #include <windows.h>
20 #include <winnt.h>
21
22 #include <algorithm>
23 #include <utility>
24 #include <vector>
25
26 #include "base/memory/scoped_ptr.h"
27 #include "base/numerics/safe_conversions.h"
28 #include "base/strings/stringprintf.h"
29 #include "base/strings/utf_string_conversions.h"
30
31 namespace crashpad {
32
33 namespace {
34
35 //! \brief Gets a string representation for a VS_FIXEDFILEINFO.dwFileFlags
36 //! value.
37 std::string GetStringForFileFlags(uint32_t file_flags) {
38 std::string result;
39 DCHECK_EQ(file_flags & VS_FF_INFOINFERRED, 0u);
40 if (file_flags & VS_FF_DEBUG)
41 result += "Debug,";
42 if (file_flags & VS_FF_PATCHED)
43 result += "Patched,";
44 if (file_flags & VS_FF_PRERELEASE)
45 result += "Prerelease,";
46 if (file_flags & VS_FF_PRIVATEBUILD)
47 result += "Private,";
48 if (file_flags & VS_FF_SPECIALBUILD)
49 result += "Special,";
50 if (!result.empty())
51 return result.substr(0, result.size() - 1); // Remove trailing comma.
52 return result;
53 }
54
55 //! \brief Gets a string representation for a VS_FIXEDFILEINFO.dwFileOS value.
56 std::string GetStringForFileOS(uint32_t file_os) {
57 // There are a variety of ancient things this could theoretically be. In
58 // practice, we're always going to get VOS_NT_WINDOWS32 here.
59 if ((file_os & VOS_NT_WINDOWS32) == VOS_NT_WINDOWS32)
60 return "Windows NT";
61 else
62 return "Unknown";
63 }
64
65 } // namespace
66
67 namespace internal {
68
69 SystemSnapshotWin::SystemSnapshotWin()
70 : SystemSnapshot(),
71 os_version_full_(),
72 os_version_build_(),
73 process_reader_(nullptr),
74 os_version_major_(0),
75 os_version_minor_(0),
76 os_version_bugfix_(0),
77 os_server_(false),
78 initialized_() {
79 }
80
81 SystemSnapshotWin::~SystemSnapshotWin() {
82 }
83
84 void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
85 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
86
87 process_reader_ = process_reader;
88
89 // We use both GetVersionEx and VerQueryValue. GetVersionEx is not trustworthy
90 // after Windows 8 (depending on the application manifest) so its data is used
91 // only to fill the os_server_ field, and the rest comes from the version
92 // information stamped on kernel32.dll.
93 OSVERSIONINFOEX version_info = {sizeof(version_info)};
94 if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info))) {
95 PLOG(WARNING) << "GetVersionEx";
96 } else {
97 const wchar_t kSystemDll[] = L"kernel32.dll";
98 DWORD size = GetFileVersionInfoSize(kSystemDll, nullptr);
99 if (!size) {
100 PLOG(WARNING) << "GetFileVersionInfoSize";
101 } else {
102 scoped_ptr<uint8_t[]> data(new uint8_t[size]);
103 if (!GetFileVersionInfo(kSystemDll, 0, size, data.get())) {
104 PLOG(WARNING) << "GetFileVersionInfo";
105 } else {
106 VS_FIXEDFILEINFO* fixed_file_info;
107 UINT size;
108 if (!VerQueryValue(data.get(),
109 L"\\",
110 reinterpret_cast<void**>(&fixed_file_info),
111 &size)) {
112 PLOG(WARNING) << "VerQueryValue";
113 } else {
114 uint32_t valid_flags =
115 fixed_file_info->dwFileFlags & fixed_file_info->dwFileFlagsMask;
116 std::string flags_string = GetStringForFileFlags(valid_flags);
117 os_version_major_ =
118 (fixed_file_info->dwFileVersionMS & 0xffff0000) >> 16;
119 os_version_minor_ = fixed_file_info->dwFileVersionMS & 0xffff;
120 os_version_bugfix_ =
121 (fixed_file_info->dwFileVersionLS & 0xffff0000) >> 16;
122 os_version_build_ = base::StringPrintf(
123 "%d", fixed_file_info->dwFileVersionLS & 0xffff);
124 os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
125 std::string os_name = GetStringForFileOS(fixed_file_info->dwFileOS);
126 os_version_full_ = base::StringPrintf(
127 "%s %d.%d.%d.%s%s",
128 os_name.c_str(),
129 os_version_major_,
130 os_version_minor_,
131 os_version_bugfix_,
132 os_version_build_.c_str(),
133 flags_string.empty() ? "" : (std::string(" (") + flags_string +
134 ")").c_str());
135 }
136 }
137 }
138 }
139
140 INITIALIZATION_STATE_SET_VALID(initialized_);
141 }
142
143 CPUArchitecture SystemSnapshotWin::GetCPUArchitecture() const {
144 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
145
146 return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
147 : kCPUArchitectureX86;
148 }
149
150 uint32_t SystemSnapshotWin::CPURevision() const {
151 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
152
153 uint32_t raw = CPUX86Signature();
154 uint8_t stepping = raw & 0xf;
155 uint8_t model = (raw & 0xf0) >> 4;
156 uint8_t family = (raw & 0xf00) >> 8;
157 uint8_t extended_model = static_cast<uint8_t>((raw & 0xf0000) >> 16);
158 uint16_t extended_family = (raw & 0xff00000) >> 20;
159
160 // For families before 15, extended_family are simply reserved bits.
161 if (family < 15)
162 extended_family = 0;
163 // extended_model is only used for families 6 and 15.
164 if (family != 6 && family != 15)
165 extended_model = 0;
166
167 uint16_t adjusted_family = family + extended_family;
168 uint8_t adjusted_model = model + (extended_model << 4);
169 return (adjusted_family << 16) | (adjusted_model << 8) | stepping;
170 }
171
172 uint8_t SystemSnapshotWin::CPUCount() const {
173 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
174
175 SYSTEM_INFO system_info;
176 GetSystemInfo(&system_info);
177 if (!base::IsValueInRangeForNumericType<uint8_t>(
178 system_info.dwNumberOfProcessors)) {
179 LOG(WARNING) << "dwNumberOfProcessors exceeds uint8_t storage";
180 }
181 return base::saturated_cast<uint8_t>(system_info.dwNumberOfProcessors);
182 }
183
184 std::string SystemSnapshotWin::CPUVendor() const {
185 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
186
187 int cpu_info[4];
188 __cpuid(cpu_info, 0);
189 char vendor[12];
190 *reinterpret_cast<int*>(vendor) = cpu_info[1];
191 *reinterpret_cast<int*>(vendor + 4) = cpu_info[3];
192 *reinterpret_cast<int*>(vendor + 8) = cpu_info[2];
193 return std::string(vendor, sizeof(vendor));
194 }
195
196 void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
197 uint64_t* max_hz) const {
198 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
199
200 int num_cpus = CPUCount();
201 DCHECK_GT(num_cpus, 0);
202 std::vector<PROCESSOR_POWER_INFORMATION> info(num_cpus);
203 if (CallNtPowerInformation(ProcessorInformation,
204 nullptr,
205 0,
206 &info[0],
207 sizeof(PROCESSOR_POWER_INFORMATION) * num_cpus) !=
208 0) {
209 *current_hz = 0;
210 *max_hz = 0;
211 return;
212 }
213 const uint64_t kMhzToHz = static_cast<uint64_t>(1E6);
214 *current_hz = std::max_element(info.begin(),
215 info.end(),
216 [](const PROCESSOR_POWER_INFORMATION& a,
217 const PROCESSOR_POWER_INFORMATION& b) {
218 return a.CurrentMhz < b.CurrentMhz;
219 })->CurrentMhz *
220 kMhzToHz;
221 *max_hz = std::max_element(info.begin(),
222 info.end(),
223 [](const PROCESSOR_POWER_INFORMATION& a,
224 const PROCESSOR_POWER_INFORMATION& b) {
225 return a.MaxMhz < b.MaxMhz;
226 })->MaxMhz *
227 kMhzToHz;
228 }
229
230 uint32_t SystemSnapshotWin::CPUX86Signature() const {
231 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
232
233 int cpu_info[4];
234 // We will never run on any processors that don't support at least function 1.
235 __cpuid(cpu_info, 1);
236 return cpu_info[0];
237 }
238
239 uint64_t SystemSnapshotWin::CPUX86Features() const {
240 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
241
242 int cpu_info[4];
243 // We will never run on any processors that don't support at least function 1.
244 __cpuid(cpu_info, 1);
245 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
246 static_cast<uint64_t>(cpu_info[3]);
247 }
248
249 uint64_t SystemSnapshotWin::CPUX86ExtendedFeatures() const {
250 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
251
252 int cpu_info[4];
253 // We will never run on any processors that don't support at least extended
254 // function 1.
255 __cpuid(cpu_info, 0x80000001);
256 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
257 static_cast<uint64_t>(cpu_info[3]);
258 }
259
260 uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
261 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
262
263 int cpu_info[4];
264
265 // Make sure leaf 7 can be called.
266 __cpuid(cpu_info, 0);
267 if (cpu_info[0] < 7)
268 return 0;
269
270 __cpuidex(cpu_info, 7, 0);
271 return cpu_info[1];
272 }
273
274 bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
275 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
276
277 // The correct way to check for denormals-as-zeros (DAZ) support is to examine
278 // mxcsr mask, which can be done with fxsave. See Intel Software Developer's
279 // Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 "Checking for the
280 // DAZ Flag in the MXCSR Register". Note that since this function tests for
281 // DAZ support in the CPU, it checks the mxcsr mask. Testing mxcsr would
282 // indicate whether DAZ is actually enabled, which is a per-thread context
283 // concern.
284
285 // Test for fxsave support.
286 uint64_t features = CPUX86Features();
287 if (!(features & (UINT64_C(1) << 24))) {
288 return false;
289 }
290
291 // Call fxsave.
292 __declspec(align(16)) uint32_t extended_registers[128];
293 _fxsave(&extended_registers);
294 uint32_t mxcsr_mask = extended_registers[7];
295
296 // Test the DAZ bit.
297 return mxcsr_mask & (1 << 6);
298 }
299
300 SystemSnapshot::OperatingSystem SystemSnapshotWin::GetOperatingSystem() const {
301 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
302 return kOperatingSystemWindows;
303 }
304
305 bool SystemSnapshotWin::OSServer() const {
306 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
307 return os_server_;
308 }
309
310 void SystemSnapshotWin::OSVersion(int* major,
311 int* minor,
312 int* bugfix,
313 std::string* build) const {
314 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
315 *major = os_version_major_;
316 *minor = os_version_minor_;
317 *bugfix = os_version_bugfix_;
318 build->assign(os_version_build_);
319 }
320
321 std::string SystemSnapshotWin::OSVersionFull() const {
322 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
323 return os_version_full_;
324 }
325
326 std::string SystemSnapshotWin::MachineDescription() const {
327 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
328 // TODO(scottmg): Not sure if there's anything sensible to put here.
329 return std::string();
330 }
331
332 bool SystemSnapshotWin::NXEnabled() const {
333 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
334 return IsProcessorFeaturePresent(PF_NX_ENABLED);
335 }
336
337 void SystemSnapshotWin::TimeZone(DaylightSavingTimeStatus* dst_status,
338 int* standard_offset_seconds,
339 int* daylight_offset_seconds,
340 std::string* standard_name,
341 std::string* daylight_name) const {
342 // This returns the current time zone status rather than the status at the
343 // time of the snapshot. This differs from the Mac implementation.
344 TIME_ZONE_INFORMATION time_zone_information;
345 *dst_status = static_cast<DaylightSavingTimeStatus>(
346 GetTimeZoneInformation(&time_zone_information));
347 *standard_offset_seconds =
348 (time_zone_information.Bias + time_zone_information.StandardBias) * -60;
349 *daylight_offset_seconds =
350 (time_zone_information.Bias + time_zone_information.DaylightBias) * -60;
351 *standard_name = base::UTF16ToUTF8(time_zone_information.StandardName);
352 *daylight_name = base::UTF16ToUTF8(time_zone_information.DaylightName);
353 }
354
355 } // namespace internal
356 } // namespace crashpad
OLDNEW
« no previous file with comments | « snapshot/win/system_snapshot_win.h ('k') | snapshot/win/system_snapshot_win_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698