Index: snapshot/system_snapshot_mac.cc |
diff --git a/snapshot/system_snapshot_mac.cc b/snapshot/system_snapshot_mac.cc |
deleted file mode 100644 |
index 2f6e6985d0fe8e619f46ed5cbc25e5ee050438e4..0000000000000000000000000000000000000000 |
--- a/snapshot/system_snapshot_mac.cc |
+++ /dev/null |
@@ -1,399 +0,0 @@ |
-// 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/system_snapshot_mac.h" |
- |
-#include <sys/sysctl.h> |
-#include <sys/types.h> |
-#include <sys/utsname.h> |
-#include <time.h> |
- |
-#include "base/logging.h" |
-#include "base/strings/stringprintf.h" |
-#include "build/build_config.h" |
-#include "snapshot/cpu_context.h" |
-#include "util/mac/mac_util.h" |
-#include "util/mac/process_reader.h" |
-#include "util/numeric/in_range_cast.h" |
- |
-namespace crashpad { |
- |
-namespace { |
- |
-template <typename T> |
-T ReadIntSysctlByName(const char* name, T default_value) { |
- T value; |
- size_t value_len = sizeof(value); |
- if (sysctlbyname(name, &value, &value_len, nullptr, 0) != 0) { |
- PLOG(WARNING) << "sysctlbyname " << name; |
- return default_value; |
- } |
- |
- return value; |
-} |
- |
-template <typename T> |
-T CastIntSysctlByName(const char* name, T default_value) { |
- int int_value = ReadIntSysctlByName<int>(name, default_value); |
- return InRangeCast<T>(int_value, default_value); |
-} |
- |
-std::string ReadStringSysctlByName(const char* name) { |
- size_t buf_len; |
- if (sysctlbyname(name, nullptr, &buf_len, nullptr, 0) != 0) { |
- PLOG(WARNING) << "sysctlbyname (size) " << name; |
- return std::string(); |
- } |
- |
- if (buf_len == 0) { |
- return std::string(); |
- } |
- |
- std::string value(buf_len - 1, '\0'); |
- if (sysctlbyname(name, &value[0], &buf_len, nullptr, 0) != 0) { |
- PLOG(WARNING) << "sysctlbyname " << name; |
- return std::string(); |
- } |
- |
- return value; |
-} |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
-void CallCPUID(uint32_t leaf, |
- uint32_t* eax, |
- uint32_t* ebx, |
- uint32_t* ecx, |
- uint32_t* edx) { |
- asm("cpuid" |
- : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) |
- : "a"(leaf), "b"(0), "c"(0), "d"(0)); |
-} |
-#endif |
- |
-} // namespace |
- |
-namespace internal { |
- |
-SystemSnapshotMac::SystemSnapshotMac() |
- : SystemSnapshot(), |
- os_version_full_(), |
- os_version_build_(), |
- process_reader_(nullptr), |
- snapshot_time_(nullptr), |
- os_version_major_(0), |
- os_version_minor_(0), |
- os_version_bugfix_(0), |
- os_server_(false), |
- initialized_() { |
-} |
- |
-SystemSnapshotMac::~SystemSnapshotMac() { |
-} |
- |
-void SystemSnapshotMac::Initialize(ProcessReader* process_reader, |
- const timeval* snapshot_time) { |
- INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
- |
- process_reader_ = process_reader; |
- snapshot_time_ = snapshot_time; |
- |
- // MacOSXVersion() logs its own warnings if it can’t figure anything out. It’s |
- // not fatal if this happens. The default values are reasonable. |
- std::string os_version_string; |
- MacOSXVersion(&os_version_major_, |
- &os_version_minor_, |
- &os_version_bugfix_, |
- &os_version_build_, |
- &os_server_, |
- &os_version_string); |
- |
- std::string uname_string; |
- utsname uts; |
- if (uname(&uts) != 0) { |
- PLOG(WARNING) << "uname"; |
- } else { |
- uname_string = base::StringPrintf( |
- "%s %s %s %s", uts.sysname, uts.release, uts.version, uts.machine); |
- } |
- |
- if (!os_version_string.empty()) { |
- if (!uname_string.empty()) { |
- os_version_full_ = base::StringPrintf( |
- "%s; %s", os_version_string.c_str(), uname_string.c_str()); |
- } else { |
- os_version_full_ = os_version_string; |
- } |
- } else { |
- os_version_full_ = uname_string; |
- } |
- |
- INITIALIZATION_STATE_SET_VALID(initialized_); |
-} |
- |
-CPUArchitecture SystemSnapshotMac::GetCPUArchitecture() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- return process_reader_->Is64Bit() ? kCPUArchitectureX86_64 |
- : kCPUArchitectureX86; |
-#else |
-#error port to your architecture |
-#endif |
-} |
- |
-uint32_t SystemSnapshotMac::CPURevision() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- // machdep.cpu.family and machdep.cpu.model already take the extended family |
- // and model IDs into account. See 10.9.2 xnu-2422.90.20/osfmk/i386/cpuid.c |
- // cpuid_set_generic_info(). |
- uint16_t family = CastIntSysctlByName<uint16_t>("machdep.cpu.family", 0); |
- uint8_t model = CastIntSysctlByName<uint8_t>("machdep.cpu.model", 0); |
- uint8_t stepping = CastIntSysctlByName<uint8_t>("machdep.cpu.stepping", 0); |
- |
- return (family << 16) | (model << 8) | stepping; |
-#else |
-#error port to your architecture |
-#endif |
-} |
- |
-uint8_t SystemSnapshotMac::CPUCount() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- return CastIntSysctlByName<uint8_t>("hw.ncpu", 1); |
-} |
- |
-std::string SystemSnapshotMac::CPUVendor() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- return ReadStringSysctlByName("machdep.cpu.vendor"); |
-#else |
-#error port to your architecture |
-#endif |
-} |
- |
-void SystemSnapshotMac::CPUFrequency( |
- uint64_t* current_hz, uint64_t* max_hz) const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- *current_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency", 0); |
- *max_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency_max", 0); |
-} |
- |
-uint32_t SystemSnapshotMac::CPUX86Signature() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- return ReadIntSysctlByName<uint32_t>("machdep.cpu.signature", 0); |
-#else |
- NOTREACHED(); |
- return 0; |
-#endif |
-} |
- |
-uint64_t SystemSnapshotMac::CPUX86Features() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- return ReadIntSysctlByName<uint64_t>("machdep.cpu.feature_bits", 0); |
-#else |
- NOTREACHED(); |
- return 0; |
-#endif |
-} |
- |
-uint64_t SystemSnapshotMac::CPUX86ExtendedFeatures() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- return ReadIntSysctlByName<uint64_t>("machdep.cpu.extfeature_bits", 0); |
-#else |
- NOTREACHED(); |
- return 0; |
-#endif |
-} |
- |
-uint32_t SystemSnapshotMac::CPUX86Leaf7Features() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- // The machdep.cpu.leaf7_feature_bits sysctl isn’t supported prior to Mac OS X |
- // 10.7, so read this by calling cpuid directly. |
- // |
- // machdep.cpu.max_basic could be used to check whether to read the leaf, but |
- // that sysctl isn’t supported prior to Mac OS X 10.6, so read the maximum |
- // basic leaf by calling cpuid directly as well. All CPUs that Apple is known |
- // to have shipped should support a maximum basic leaf value of at least 0xa. |
- uint32_t eax, ebx, ecx, edx; |
- CallCPUID(0, &eax, &ebx, &ecx, &edx); |
- if (eax < 7) { |
- return 0; |
- } |
- |
- CallCPUID(7, &eax, &ebx, &ecx, &edx); |
- return ebx; |
-#else |
- NOTREACHED(); |
- return 0; |
-#endif |
-} |
- |
-bool SystemSnapshotMac::CPUX86SupportsDAZ() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
-#if defined(ARCH_CPU_X86_FAMILY) |
- // 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. |
- // |
- // All CPUs that Apple is known to have shipped should support DAZ. |
- |
- // Test for fxsave support. |
- uint64_t features = CPUX86Features(); |
- if (!(features & (UINT64_C(1) << 24))) { |
- return false; |
- } |
- |
- // Call fxsave. |
-#if defined(ARCH_CPU_X86) |
- CPUContextX86::Fxsave fxsave __attribute__((aligned(16))) = {}; |
-#elif defined(ARCH_CPU_X86_64) |
- CPUContextX86_64::Fxsave fxsave __attribute__((aligned(16))) = {}; |
-#endif |
- static_assert(sizeof(fxsave) == 512, "fxsave size"); |
- static_assert(offsetof(decltype(fxsave), mxcsr_mask) == 28, |
- "mxcsr_mask offset"); |
- asm("fxsave %0" : "=m"(fxsave)); |
- |
- // Test the DAZ bit. |
- return fxsave.mxcsr_mask & (1 << 6); |
-#else |
- NOTREACHED(); |
- return false; |
-#endif |
-} |
- |
-SystemSnapshot::OperatingSystem SystemSnapshotMac::GetOperatingSystem() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- return kOperatingSystemMacOSX; |
-} |
- |
-bool SystemSnapshotMac::OSServer() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- return os_server_; |
-} |
- |
-void SystemSnapshotMac::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 SystemSnapshotMac::OSVersionFull() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- return os_version_full_; |
-} |
- |
-std::string SystemSnapshotMac::MachineDescription() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
- std::string model; |
- std::string board_id; |
- MacModelAndBoard(&model, &board_id); |
- |
- if (!model.empty()) { |
- if (!board_id.empty()) { |
- return base::StringPrintf("%s (%s)", model.c_str(), board_id.c_str()); |
- } |
- return model; |
- } |
- if (!board_id.empty()) { |
- return base::StringPrintf("(%s)", board_id.c_str()); |
- } |
- return std::string(); |
-} |
- |
-bool SystemSnapshotMac::NXEnabled() const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- return ReadIntSysctlByName<int>("kern.nx", 0); |
-} |
- |
-void SystemSnapshotMac::TimeZone(DaylightSavingTimeStatus* dst_status, |
- int* standard_offset_seconds, |
- int* daylight_offset_seconds, |
- std::string* standard_name, |
- std::string* daylight_name) const { |
- INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
- |
- tm local; |
- PCHECK(localtime_r(&snapshot_time_->tv_sec, &local)) << "localtime_r"; |
- |
- *standard_name = tzname[0]; |
- if (daylight) { |
- // Scan forward and backward, one month at a time, looking for an instance |
- // when the observance of daylight saving time is different than it is in |
- // |local|. |
- long probe_gmtoff = local.tm_gmtoff; |
- |
- const int kMonthDeltas[] = |
- { 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, |
- 7, -7, 8, -8, 9, -9, 10, -10, 11, -11, 12, -12 }; |
- for (size_t index = 0; index < arraysize(kMonthDeltas); ++index) { |
- // Look at the 15th day of each month at local noon. Set tm_isdst to -1 to |
- // avoid giving mktime() any hints about whether to consider daylight |
- // saving time in effect. mktime() accepts values of tm_mon that are |
- // outside of its normal range and behaves as expected: if tm_mon is -1, |
- // it references December of the preceding year, and if it is 12, it |
- // references January of the following year. |
- tm probe_tm = {}; |
- probe_tm.tm_hour = 12; |
- probe_tm.tm_mday = 15; |
- probe_tm.tm_mon = local.tm_mon + kMonthDeltas[index]; |
- probe_tm.tm_year = local.tm_year; |
- probe_tm.tm_isdst = -1; |
- if (mktime(&probe_tm) != -1 && probe_tm.tm_isdst != local.tm_isdst) { |
- probe_gmtoff = probe_tm.tm_gmtoff; |
- break; |
- } |
- } |
- |
- *daylight_name = tzname[1]; |
- if (!local.tm_isdst) { |
- *dst_status = kObservingStandardTime; |
- *standard_offset_seconds = local.tm_gmtoff; |
- *daylight_offset_seconds = probe_gmtoff; |
- } else { |
- *dst_status = kObservingDaylightSavingTime; |
- *standard_offset_seconds = probe_gmtoff; |
- *daylight_offset_seconds = local.tm_gmtoff; |
- } |
- } else { |
- *daylight_name = tzname[0]; |
- *dst_status = kDoesNotObserveDaylightSavingTime; |
- *standard_offset_seconds = local.tm_gmtoff; |
- *daylight_offset_seconds = local.tm_gmtoff; |
- } |
-} |
- |
-} // namespace internal |
-} // namespace crashpad |