diff --git a/minidump/minidump_system_info_writer.cc b/minidump/minidump_system_info_writer.cc index 05e0bacb..3e1d91f2 100644 --- a/minidump/minidump_system_info_writer.cc +++ b/minidump/minidump_system_info_writer.cc @@ -19,10 +19,86 @@ #include "base/logging.h" #include "minidump/minidump_string_writer.h" +#include "snapshot/system_snapshot.h" #include "util/file/file_writer.h" namespace crashpad { +namespace { + +uint64_t AMD64FeaturesFromSystemSnapshot( + const SystemSnapshot* system_snapshot) { +#define ADD_FEATURE(minidump_bit) (UINT64_C(1) << (minidump_bit)) + + // Features for which no cpuid bits are present, but that always exist on + // x86_64. cmpxchg is supported on 486 and later. + uint64_t minidump_features = ADD_FEATURE(PF_COMPARE_EXCHANGE_DOUBLE); + +#define MAP_FEATURE(features, cpuid_bit, minidump_bit) \ +do { \ + if ((features) & (static_cast(1) << (cpuid_bit))) { \ + minidump_features |= ADD_FEATURE(minidump_bit); \ + } \ +} while (false) + +#define F_TSC 4 +#define F_PAE 6 +#define F_MMX 23 +#define F_SSE 25 +#define F_SSE2 26 +#define F_SSE3 32 +#define F_CX16 45 +#define F_XSAVE 58 +#define F_RDRAND 62 + + uint64_t cpuid_features = system_snapshot->CPUX86Features(); + + MAP_FEATURE(cpuid_features, F_TSC, PF_RDTSC_INSTRUCTION_AVAILABLE); + MAP_FEATURE(cpuid_features, F_PAE, PF_PAE_ENABLED); + MAP_FEATURE(cpuid_features, F_MMX, PF_MMX_INSTRUCTIONS_AVAILABLE); + MAP_FEATURE(cpuid_features, F_SSE, PF_XMMI_INSTRUCTIONS_AVAILABLE); + MAP_FEATURE(cpuid_features, F_SSE2, PF_XMMI64_INSTRUCTIONS_AVAILABLE); + MAP_FEATURE(cpuid_features, F_SSE3, PF_SSE3_INSTRUCTIONS_AVAILABLE); + MAP_FEATURE(cpuid_features, F_CX16, PF_COMPARE_EXCHANGE128); + MAP_FEATURE(cpuid_features, F_XSAVE, PF_XSAVE_ENABLED); + MAP_FEATURE(cpuid_features, F_RDRAND, PF_RDRAND_INSTRUCTION_AVAILABLE); + +#define FX_XD 20 +#define FX_3DNOW 31 + + uint64_t extended_features = system_snapshot->CPUX86ExtendedFeatures(); + + MAP_FEATURE(extended_features, FX_3DNOW, PF_3DNOW_INSTRUCTIONS_AVAILABLE); + +#define F7_FSGSBASE 0 + + uint32_t leaf7_features = system_snapshot->CPUX86Leaf7Features(); + + MAP_FEATURE(leaf7_features, F7_FSGSBASE, PF_RDWRFSGSBASE_AVAILABLE); + + // This feature bit should be set if NX (XD, DEP) is enabled, not just if + // it’s available on the CPU as indicated by the XF_XD bit. + if (system_snapshot->NXEnabled()) { + minidump_features |= ADD_FEATURE(PF_NX_ENABLED); + } + + if (system_snapshot->CPUX86SupportsDAZ()) { + minidump_features |= ADD_FEATURE(PF_SSE_DAZ_MODE_AVAILABLE); + } + + // PF_SECOND_LEVEL_ADDRESS_TRANSLATION can’t be determined without + // consulting model-specific registers, a privileged operation. The exact + // use of PF_VIRT_FIRMWARE_ENABLED is unknown. PF_FASTFAIL_AVAILABLE is + // irrelevant outside of Windows. + +#undef MAP_FEATURE +#undef ADD_FEATURE + + return minidump_features; +} + +} // namespace + MinidumpSystemInfoWriter::MinidumpSystemInfoWriter() : MinidumpStreamWriter(), system_info_(), csd_version_() { system_info_.ProcessorArchitecture = kMinidumpCPUArchitectureUnknown; @@ -31,6 +107,72 @@ MinidumpSystemInfoWriter::MinidumpSystemInfoWriter() MinidumpSystemInfoWriter::~MinidumpSystemInfoWriter() { } +void MinidumpSystemInfoWriter::InitializeFromSnapshot( + const SystemSnapshot* system_snapshot) { + DCHECK_EQ(state(), kStateMutable); + DCHECK(!csd_version_); + + MinidumpCPUArchitecture cpu_architecture; + switch (system_snapshot->GetCPUArchitecture()) { + case kCPUArchitectureX86: + cpu_architecture = kMinidumpCPUArchitectureX86; + break; + case kCPUArchitectureX86_64: + cpu_architecture = kMinidumpCPUArchitectureAMD64; + break; + default: + NOTREACHED(); + cpu_architecture = kMinidumpCPUArchitectureUnknown; + break; + } + SetCPUArchitecture(cpu_architecture); + + uint32_t cpu_revision = system_snapshot->CPURevision(); + SetCPULevelAndRevision( + (cpu_revision & 0xffff0000) >> 16, cpu_revision & 0x0000ffff); + SetCPUCount(system_snapshot->CPUCount()); + + if (cpu_architecture == kMinidumpCPUArchitectureX86) { + std::string cpu_vendor = system_snapshot->CPUVendor(); + SetCPUX86VendorString(cpu_vendor); + + // The minidump file format only has room for the bottom 32 bits of CPU + // features and extended CPU features. + SetCPUX86VersionAndFeatures(system_snapshot->CPUX86Signature(), + system_snapshot->CPUX86Features() & 0xffffffff); + + if (cpu_vendor == "AuthenticAMD") { + SetCPUX86AMDExtendedFeatures( + system_snapshot->CPUX86ExtendedFeatures() & 0xffffffff); + } + } else if (cpu_architecture == kMinidumpCPUArchitectureAMD64) { + SetCPUOtherFeatures(AMD64FeaturesFromSystemSnapshot(system_snapshot), 0); + } + + MinidumpOS operating_system; + switch (system_snapshot->GetOperatingSystem()) { + case SystemSnapshot::kOperatingSystemMacOSX: + operating_system = kMinidumpOSMacOSX; + break; + default: + NOTREACHED(); + operating_system = kMinidumpOSUnknown; + break; + } + SetOS(operating_system); + + SetOSType(system_snapshot->OSServer() ? kMinidumpOSTypeServer + : kMinidumpOSTypeWorkstation); + + int major; + int minor; + int bugfix; + std::string build; + system_snapshot->OSVersion(&major, &minor, &bugfix, &build); + SetOSVersion(major, minor, bugfix); + SetCSDVersion(build); +} + void MinidumpSystemInfoWriter::SetCSDVersion(const std::string& csd_version) { DCHECK_EQ(state(), kStateMutable); diff --git a/minidump/minidump_system_info_writer.h b/minidump/minidump_system_info_writer.h index 6cd133fa..ce483e8c 100644 --- a/minidump/minidump_system_info_writer.h +++ b/minidump/minidump_system_info_writer.h @@ -29,6 +29,8 @@ namespace crashpad { +class SystemSnapshot; + namespace internal { class MinidumpUTF16StringWriter; } // namespace internal @@ -39,6 +41,15 @@ class MinidumpSystemInfoWriter final : public internal::MinidumpStreamWriter { MinidumpSystemInfoWriter(); ~MinidumpSystemInfoWriter() override; + //! \brief Initializes MINIDUMP_SYSTEM_INFO based on \a system_snapshot. + //! + //! \param[in] system_snapshot The system snapshot to use as source data. + //! + //! \note Valid in #kStateMutable. No mutator methods may be called before + //! this method, and it is not normally necessary to call any mutator + //! methods after this method. + void InitializeFromSnapshot(const SystemSnapshot* system_snapshot); + //! \brief Sets MINIDUMP_SYSTEM_INFO::ProcessorArchitecture. void SetCPUArchitecture(MinidumpCPUArchitecture processor_architecture) { system_info_.ProcessorArchitecture = processor_architecture; diff --git a/minidump/minidump_system_info_writer_test.cc b/minidump/minidump_system_info_writer_test.cc index e6f0030b..a75e84b7 100644 --- a/minidump/minidump_system_info_writer_test.cc +++ b/minidump/minidump_system_info_writer_test.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include "gtest/gtest.h" @@ -25,6 +26,7 @@ #include "minidump/test/minidump_file_writer_test_util.h" #include "minidump/test/minidump_string_writer_test_util.h" #include "minidump/test/minidump_writable_test_util.h" +#include "snapshot/test/test_system_snapshot.h" #include "util/file/string_file_writer.h" namespace crashpad { @@ -181,7 +183,7 @@ TEST(MinidumpSystemInfoWriter, X86_Win) { } } -TEST(MinidumpSystemInfoWriter, X86_64_Mac) { +TEST(MinidumpSystemInfoWriter, AMD64_Mac) { MinidumpFileWriter minidump_file_writer; auto system_info_writer = make_scoped_ptr(new MinidumpSystemInfoWriter()); @@ -269,6 +271,198 @@ TEST(MinidumpSystemInfoWriter, X86_CPUVendorFromRegisters) { EXPECT_EQ(0u, system_info->Cpu.X86CpuInfo.VersionInformation); } +TEST(MinidumpSystemInfoWriter, InitializeFromSnapshot_X86) { + MINIDUMP_SYSTEM_INFO expect_system_info = {}; + + const uint16_t kCPUFamily = 6; + const uint8_t kCPUModel = 70; + const uint8_t kCPUStepping = 1; + + const uint8_t kCPUBasicFamily = + std::min(kCPUFamily, static_cast(15)); + const uint8_t kCPUExtendedFamily = kCPUFamily - kCPUBasicFamily; + + // These checks ensure that even if the constants above change, they represent + // something that can legitimately be encoded in the form used by cpuid 1 eax. + EXPECT_LE(kCPUFamily, 270); + EXPECT_LE(kCPUStepping, 15); + EXPECT_TRUE(kCPUBasicFamily == 6 || kCPUBasicFamily == 15 || kCPUModel <= 15); + + const uint8_t kCPUBasicModel = kCPUModel & 0xf; + const uint8_t kCPUExtendedModel = kCPUModel >> 4; + const uint32_t kCPUSignature = + (kCPUExtendedFamily << 20) | (kCPUExtendedModel << 16) | + (kCPUBasicFamily << 8) | (kCPUBasicModel << 4) | kCPUStepping; + const uint64_t kCPUX86Features = 0x7ffafbffbfebfbff; + expect_system_info.ProcessorArchitecture = kMinidumpCPUArchitectureX86; + expect_system_info.ProcessorLevel = kCPUFamily; + expect_system_info.ProcessorRevision = (kCPUModel << 8) | kCPUStepping; + expect_system_info.NumberOfProcessors = 8; + expect_system_info.ProductType = kMinidumpOSTypeServer; + expect_system_info.MajorVersion = 10; + expect_system_info.MinorVersion = 9; + expect_system_info.BuildNumber = 5; + expect_system_info.PlatformId = kMinidumpOSMacOSX; + expect_system_info.SuiteMask = 0; + expect_system_info.Cpu.X86CpuInfo.VendorId[0] = 'uneG'; + expect_system_info.Cpu.X86CpuInfo.VendorId[1] = 'Ieni'; + expect_system_info.Cpu.X86CpuInfo.VendorId[2] = 'letn'; + expect_system_info.Cpu.X86CpuInfo.VersionInformation = kCPUSignature; + expect_system_info.Cpu.X86CpuInfo.FeatureInformation = + kCPUX86Features & 0xffffffff; + const char kCPUVendor[] = "GenuineIntel"; + const char kOSVersionBuild[] = "13F34"; + + TestSystemSnapshot system_snapshot; + system_snapshot.SetCPUArchitecture(kCPUArchitectureX86); + system_snapshot.SetCPURevision( + (kCPUFamily << 16) | (kCPUModel << 8) | kCPUStepping); + system_snapshot.SetCPUCount(expect_system_info.NumberOfProcessors); + system_snapshot.SetCPUVendor(kCPUVendor); + system_snapshot.SetCPUX86Signature(kCPUSignature); + system_snapshot.SetCPUX86Features(kCPUX86Features); + system_snapshot.SetOperatingSystem(SystemSnapshot::kOperatingSystemMacOSX); + system_snapshot.SetOSServer(true); + system_snapshot.SetOSVersion(expect_system_info.MajorVersion, + expect_system_info.MinorVersion, + expect_system_info.BuildNumber, + kOSVersionBuild); + + auto system_info_writer = make_scoped_ptr(new MinidumpSystemInfoWriter()); + system_info_writer->InitializeFromSnapshot(&system_snapshot); + + MinidumpFileWriter minidump_file_writer; + minidump_file_writer.AddStream(system_info_writer.Pass()); + + StringFileWriter file_writer; + ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); + + const MINIDUMP_SYSTEM_INFO* system_info; + const MINIDUMP_STRING* csd_version; + + ASSERT_NO_FATAL_FAILURE(GetSystemInfoStream(file_writer.string(), + strlen(kOSVersionBuild), + &system_info, + &csd_version)); + + EXPECT_EQ(expect_system_info.ProcessorArchitecture, + system_info->ProcessorArchitecture); + EXPECT_EQ(expect_system_info.ProcessorLevel, system_info->ProcessorLevel); + EXPECT_EQ(expect_system_info.ProcessorRevision, + system_info->ProcessorRevision); + EXPECT_EQ(expect_system_info.NumberOfProcessors, + system_info->NumberOfProcessors); + EXPECT_EQ(expect_system_info.ProductType, system_info->ProductType); + EXPECT_EQ(expect_system_info.MajorVersion, system_info->MajorVersion); + EXPECT_EQ(expect_system_info.MinorVersion, system_info->MinorVersion); + EXPECT_EQ(expect_system_info.BuildNumber, system_info->BuildNumber); + EXPECT_EQ(expect_system_info.PlatformId, system_info->PlatformId); + EXPECT_EQ(expect_system_info.SuiteMask, system_info->SuiteMask); + EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[0], + system_info->Cpu.X86CpuInfo.VendorId[0]); + EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[1], + system_info->Cpu.X86CpuInfo.VendorId[1]); + EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VendorId[2], + system_info->Cpu.X86CpuInfo.VendorId[2]); + EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.VersionInformation, + system_info->Cpu.X86CpuInfo.VersionInformation); + EXPECT_EQ(expect_system_info.Cpu.X86CpuInfo.FeatureInformation, + system_info->Cpu.X86CpuInfo.FeatureInformation); + + for (size_t index = 0; index < strlen(kOSVersionBuild); ++index) { + EXPECT_EQ(kOSVersionBuild[index], csd_version->Buffer[index]) << index; + } +} + +TEST(MinidumpSystemInfoWriter, InitializeFromSnapshot_AMD64) { + MINIDUMP_SYSTEM_INFO expect_system_info = {}; + + const uint8_t kCPUFamily = 6; + const uint8_t kCPUModel = 70; + const uint8_t kCPUStepping = 1; + expect_system_info.ProcessorArchitecture = kMinidumpCPUArchitectureAMD64; + expect_system_info.ProcessorLevel = kCPUFamily; + expect_system_info.ProcessorRevision = (kCPUModel << 8) | kCPUStepping; + expect_system_info.NumberOfProcessors = 8; + expect_system_info.ProductType = kMinidumpOSTypeServer; + expect_system_info.MajorVersion = 10; + expect_system_info.MinorVersion = 9; + expect_system_info.BuildNumber = 5; + expect_system_info.PlatformId = kMinidumpOSMacOSX; + expect_system_info.SuiteMask = 0; + expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[0] = + (1 << PF_COMPARE_EXCHANGE_DOUBLE) | + (1 << PF_MMX_INSTRUCTIONS_AVAILABLE) | + (1 << PF_XMMI_INSTRUCTIONS_AVAILABLE) | + (1 << PF_RDTSC_INSTRUCTION_AVAILABLE) | + (1 << PF_PAE_ENABLED) | + (1 << PF_XMMI64_INSTRUCTIONS_AVAILABLE) | + (1 << PF_SSE_DAZ_MODE_AVAILABLE) | + (1 << PF_NX_ENABLED) | + (1 << PF_SSE3_INSTRUCTIONS_AVAILABLE) | + (1 << PF_COMPARE_EXCHANGE128) | + (1 << PF_XSAVE_ENABLED) | + (1 << PF_RDWRFSGSBASE_AVAILABLE) | + (1 << PF_RDRAND_INSTRUCTION_AVAILABLE); + expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[1] = 0; + const char kOSVersionBuild[] = "13F34"; + + TestSystemSnapshot system_snapshot; + system_snapshot.SetCPUArchitecture(kCPUArchitectureX86_64); + system_snapshot.SetCPURevision( + (kCPUFamily << 16) | (kCPUModel << 8) | kCPUStepping); + system_snapshot.SetCPUCount(expect_system_info.NumberOfProcessors); + system_snapshot.SetCPUX86Features(0x7ffafbffbfebfbff); + system_snapshot.SetCPUX86ExtendedFeatures(0x000000212c100900); + system_snapshot.SetCPUX86Leaf7Features(0x00002fbb); + system_snapshot.SetCPUX86SupportsDAZ(true); + system_snapshot.SetOperatingSystem(SystemSnapshot::kOperatingSystemMacOSX); + system_snapshot.SetOSServer(true); + system_snapshot.SetOSVersion(expect_system_info.MajorVersion, + expect_system_info.MinorVersion, + expect_system_info.BuildNumber, + kOSVersionBuild); + system_snapshot.SetNXEnabled(true); + + auto system_info_writer = make_scoped_ptr(new MinidumpSystemInfoWriter()); + system_info_writer->InitializeFromSnapshot(&system_snapshot); + + MinidumpFileWriter minidump_file_writer; + minidump_file_writer.AddStream(system_info_writer.Pass()); + + StringFileWriter file_writer; + ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); + + const MINIDUMP_SYSTEM_INFO* system_info; + const MINIDUMP_STRING* csd_version; + ASSERT_NO_FATAL_FAILURE(GetSystemInfoStream(file_writer.string(), + strlen(kOSVersionBuild), + &system_info, + &csd_version)); + + EXPECT_EQ(expect_system_info.ProcessorArchitecture, + system_info->ProcessorArchitecture); + EXPECT_EQ(expect_system_info.ProcessorLevel, system_info->ProcessorLevel); + EXPECT_EQ(expect_system_info.ProcessorRevision, + system_info->ProcessorRevision); + EXPECT_EQ(expect_system_info.NumberOfProcessors, + system_info->NumberOfProcessors); + EXPECT_EQ(expect_system_info.ProductType, system_info->ProductType); + EXPECT_EQ(expect_system_info.MajorVersion, system_info->MajorVersion); + EXPECT_EQ(expect_system_info.MinorVersion, system_info->MinorVersion); + EXPECT_EQ(expect_system_info.BuildNumber, system_info->BuildNumber); + EXPECT_EQ(expect_system_info.PlatformId, system_info->PlatformId); + EXPECT_EQ(expect_system_info.SuiteMask, system_info->SuiteMask); + EXPECT_EQ(expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[0], + system_info->Cpu.OtherCpuInfo.ProcessorFeatures[0]); + EXPECT_EQ(expect_system_info.Cpu.OtherCpuInfo.ProcessorFeatures[1], + system_info->Cpu.OtherCpuInfo.ProcessorFeatures[1]); + + for (size_t index = 0; index < strlen(kOSVersionBuild); ++index) { + EXPECT_EQ(kOSVersionBuild[index], csd_version->Buffer[index]) << index; + } +} + TEST(MinidumpSystemInfoWriterDeathTest, NoCSDVersion) { MinidumpFileWriter minidump_file_writer; auto system_info_writer = make_scoped_ptr(new MinidumpSystemInfoWriter()); diff --git a/snapshot/snapshot.gyp b/snapshot/snapshot.gyp index 2c52ff99..ae0bcf39 100644 --- a/snapshot/snapshot.gyp +++ b/snapshot/snapshot.gyp @@ -94,6 +94,8 @@ 'test/test_memory_snapshot.h', 'test/test_module_snapshot.cc', 'test/test_module_snapshot.h', + 'test/test_system_snapshot.cc', + 'test/test_system_snapshot.h', 'test/test_thread_snapshot.cc', 'test/test_thread_snapshot.h', ], diff --git a/snapshot/system_snapshot.h b/snapshot/system_snapshot.h index 6dfede68..7a41227c 100644 --- a/snapshot/system_snapshot.h +++ b/snapshot/system_snapshot.h @@ -79,8 +79,11 @@ class SystemSnapshot { //! \brief Returns the snapshot system’s CPU revision. //! //! For x86-family CPUs (including x86_64 and 32-bit x86), this is the CPU - //! family ID value from `cpuid 1` `eax`, adjusted to take the extended family - //! ID into account. + //! family, model, and stepping ID values from `cpuid 1` `eax`. The family and + //! model values are adjusted to take the extended family and model IDs into + //! account. These values are encoded in this method’s return value with the + //! family in the high high 16 bits, the model in the next 8 bits, and the + //! stepping in the low 8 bits. //! //! \return A CPU architecture-specific value identifying the CPU revision. virtual uint32_t CPURevision() const = 0; diff --git a/snapshot/test/test_system_snapshot.cc b/snapshot/test/test_system_snapshot.cc new file mode 100644 index 00000000..0f3605cf --- /dev/null +++ b/snapshot/test/test_system_snapshot.cc @@ -0,0 +1,134 @@ +// Copyright 2014 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/test/test_system_snapshot.h" + +namespace crashpad { +namespace test { + +TestSystemSnapshot::TestSystemSnapshot() + : cpu_architecture_(kCPUArchitectureUnknown), + cpu_revision_(0), + cpu_count_(0), + cpu_vendor_(), + cpu_frequency_current_hz_(0), + cpu_frequency_max_hz_(0), + cpu_x86_signature_(0), + cpu_x86_features_(0), + cpu_x86_extended_features_(0), + cpu_x86_leaf_7_features_(0), + cpu_x86_supports_daz_(false), + operating_system_(kOperatingSystemUnknown), + os_server_(false), + os_version_major_(0), + os_version_minor_(0), + os_version_bugfix_(0), + os_version_build_(), + os_version_full_(), + nx_enabled_(false), + machine_description_(), + time_zone_dst_status_(kDoesNotObserveDaylightSavingTime), + time_zone_standard_offset_seconds_(0), + time_zone_daylight_offset_seconds_(0), + time_zone_standard_name_(), + time_zone_daylight_name_() { +} + +TestSystemSnapshot::~TestSystemSnapshot() { +} + +CPUArchitecture TestSystemSnapshot::GetCPUArchitecture() const { + return cpu_architecture_; +} + +uint32_t TestSystemSnapshot::CPURevision() const { + return cpu_revision_; +} + +uint8_t TestSystemSnapshot::CPUCount() const { + return cpu_count_; +} + +std::string TestSystemSnapshot::CPUVendor() const { + return cpu_vendor_; +} + +void TestSystemSnapshot::CPUFrequency(uint64_t* current_hz, + uint64_t* max_hz) const { + *current_hz = cpu_frequency_current_hz_; + *max_hz = cpu_frequency_max_hz_; +} + +uint32_t TestSystemSnapshot::CPUX86Signature() const { + return cpu_x86_signature_; +} + +uint64_t TestSystemSnapshot::CPUX86Features() const { + return cpu_x86_features_; +} + +uint64_t TestSystemSnapshot::CPUX86ExtendedFeatures() const { + return cpu_x86_extended_features_; +} + +uint32_t TestSystemSnapshot::CPUX86Leaf7Features() const { + return cpu_x86_leaf_7_features_; +} + +bool TestSystemSnapshot::CPUX86SupportsDAZ() const { + return cpu_x86_supports_daz_; +} + +SystemSnapshot::OperatingSystem TestSystemSnapshot::GetOperatingSystem() const { + return operating_system_; +} + +bool TestSystemSnapshot::OSServer() const { + return os_server_; +} + +void TestSystemSnapshot::OSVersion( + int* major, int* minor, int* bugfix, std::string* build) const { + *major = os_version_major_; + *minor = os_version_minor_; + *bugfix = os_version_bugfix_; + *build = os_version_build_; +} + +std::string TestSystemSnapshot::OSVersionFull() const { + return os_version_full_; +} + +bool TestSystemSnapshot::NXEnabled() const { + return nx_enabled_; +} + +std::string TestSystemSnapshot::MachineDescription() const { + return machine_description_; +} + +void TestSystemSnapshot::TimeZone(DaylightSavingTimeStatus* dst_status, + int* standard_offset_seconds, + int* daylight_offset_seconds, + std::string* standard_name, + std::string* daylight_name) const { + *dst_status = time_zone_dst_status_; + *standard_offset_seconds = time_zone_standard_offset_seconds_; + *daylight_offset_seconds = time_zone_daylight_offset_seconds_; + *standard_name = time_zone_standard_name_; + *daylight_name = time_zone_daylight_name_; +} + +} // namespace test +} // namespace crashpad diff --git a/snapshot/test/test_system_snapshot.h b/snapshot/test/test_system_snapshot.h new file mode 100644 index 00000000..d626fae8 --- /dev/null +++ b/snapshot/test/test_system_snapshot.h @@ -0,0 +1,148 @@ +// Copyright 2014 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. + +#ifndef CRASHPAD_SNAPSHOT_TEST_TEST_SYSTEM_SNAPSHOT_H_ +#define CRASHPAD_SNAPSHOT_TEST_TEST_SYSTEM_SNAPSHOT_H_ + +#include + +#include + +#include "base/basictypes.h" +#include "snapshot/system_snapshot.h" + +namespace crashpad { +namespace test { + +//! \brief A test SystemSnapshot that can carry arbitrary data for testing +//! purposes. +class TestSystemSnapshot final : public SystemSnapshot { + public: + TestSystemSnapshot(); + ~TestSystemSnapshot() override; + + void SetCPUArchitecture(CPUArchitecture cpu_architecture) { + cpu_architecture_ = cpu_architecture; + } + void SetCPURevision(uint32_t cpu_revision) { cpu_revision_ = cpu_revision; } + void SetCPUCount(uint8_t cpu_count) { cpu_count_ = cpu_count; } + void SetCPUVendor(const std::string& cpu_vendor) { cpu_vendor_ = cpu_vendor; } + void SetCPUFrequency(uint64_t current_hz, uint64_t max_hz) { + cpu_frequency_current_hz_ = current_hz; + cpu_frequency_max_hz_ = max_hz; + } + void SetCPUX86Signature(uint32_t cpu_x86_signature) { + cpu_x86_signature_ = cpu_x86_signature; + } + void SetCPUX86Features(uint64_t cpu_x86_features) { + cpu_x86_features_ = cpu_x86_features; + } + void SetCPUX86ExtendedFeatures(uint64_t cpu_x86_extended_features) { + cpu_x86_extended_features_ = cpu_x86_extended_features; + } + void SetCPUX86Leaf7Features(uint32_t cpu_x86_leaf_7_features) { + cpu_x86_leaf_7_features_ = cpu_x86_leaf_7_features; + } + void SetCPUX86SupportsDAZ(bool cpu_x86_supports_daz) { + cpu_x86_supports_daz_ = cpu_x86_supports_daz; + } + void SetOperatingSystem(OperatingSystem operating_system) { + operating_system_ = operating_system; + } + void SetOSServer(bool os_server) { os_server_ = os_server; } + void SetOSVersion( + int major, int minor, int bugfix, const std::string& build) { + os_version_major_ = major; + os_version_minor_ = minor; + os_version_bugfix_ = bugfix; + os_version_build_ = build; + } + void SetOSVersionFull(const std::string& os_version_full) { + os_version_full_ = os_version_full; + } + void SetNXEnabled(bool nx_enabled) { nx_enabled_ = nx_enabled; } + void SetMachineDescription(const std::string& machine_description) { + machine_description_ = machine_description; + } + void SetTimeZone(DaylightSavingTimeStatus dst_status, + int standard_offset_seconds, + int daylight_offset_seconds, + const std::string& standard_name, + const std::string& daylight_name) { + time_zone_dst_status_ = dst_status; + time_zone_standard_offset_seconds_ = standard_offset_seconds; + time_zone_daylight_offset_seconds_ = daylight_offset_seconds; + time_zone_standard_name_ = standard_name; + time_zone_daylight_name_ = daylight_name; + } + + // SystemSnapshot: + + CPUArchitecture GetCPUArchitecture() const override; + uint32_t CPURevision() const override; + uint8_t CPUCount() const override; + std::string CPUVendor() const override; + void CPUFrequency(uint64_t* current_hz, uint64_t* max_hz) const override; + uint32_t CPUX86Signature() const override; + uint64_t CPUX86Features() const override; + uint64_t CPUX86ExtendedFeatures() const override; + uint32_t CPUX86Leaf7Features() const override; + bool CPUX86SupportsDAZ() const override; + OperatingSystem GetOperatingSystem() const override; + bool OSServer() const override; + void OSVersion( + int* major, int* minor, int* bugfix, std::string* build) const override; + std::string OSVersionFull() const override; + bool NXEnabled() const override; + std::string MachineDescription() const override; + void TimeZone(DaylightSavingTimeStatus* dst_status, + int* standard_offset_seconds, + int* daylight_offset_seconds, + std::string* standard_name, + std::string* daylight_name) const override; + + private: + CPUArchitecture cpu_architecture_; + uint32_t cpu_revision_; + uint8_t cpu_count_; + std::string cpu_vendor_; + uint64_t cpu_frequency_current_hz_; + uint64_t cpu_frequency_max_hz_; + uint32_t cpu_x86_signature_; + uint64_t cpu_x86_features_; + uint64_t cpu_x86_extended_features_; + uint32_t cpu_x86_leaf_7_features_; + bool cpu_x86_supports_daz_; + OperatingSystem operating_system_; + bool os_server_; + int os_version_major_; + int os_version_minor_; + int os_version_bugfix_; + std::string os_version_build_; + std::string os_version_full_; + bool nx_enabled_; + std::string machine_description_; + DaylightSavingTimeStatus time_zone_dst_status_; + int time_zone_standard_offset_seconds_; + int time_zone_daylight_offset_seconds_; + std::string time_zone_standard_name_; + std::string time_zone_daylight_name_; + + DISALLOW_COPY_AND_ASSIGN(TestSystemSnapshot); +}; + +} // namespace test +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_TEST_TEST_SYSTEM_SNAPSHOT_H_