blob: 6a9f2c1c5283840b9f83f2685a306847c6191e9e [file] [log] [blame]
// Copyright 2020 The Crashpad Authors
//
// 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/ios/system_snapshot_ios_intermediate_dump.h"
#include <mach/mach.h>
#include <stddef.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <algorithm>
#include "base/apple/mach_logging.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "snapshot/cpu_context.h"
#include "snapshot/ios/intermediate_dump_reader_util.h"
#include "snapshot/posix/timezone.h"
#include "util/ios/ios_intermediate_dump_data.h"
#include "util/mac/mac_util.h"
#include "util/numeric/in_range_cast.h"
namespace crashpad {
namespace internal {
using Key = IntermediateDumpKey;
SystemSnapshotIOSIntermediateDump::SystemSnapshotIOSIntermediateDump()
: SystemSnapshot(),
os_version_build_(),
machine_description_(),
os_version_major_(0),
os_version_minor_(0),
os_version_bugfix_(0),
active_(0),
inactive_(0),
wired_(0),
free_(0),
cpu_count_(0),
cpu_vendor_(),
dst_status_(),
standard_offset_seconds_(0),
daylight_offset_seconds_(0),
standard_name_(),
daylight_name_(),
address_mask_(0),
initialized_() {}
SystemSnapshotIOSIntermediateDump::~SystemSnapshotIOSIntermediateDump() {}
void SystemSnapshotIOSIntermediateDump::Initialize(
const IOSIntermediateDumpMap* system_data) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
GetDataStringFromMap(system_data, Key::kOSVersionBuild, &os_version_build_);
GetDataStringFromMap(
system_data, Key::kMachineDescription, &machine_description_);
GetDataStringFromMap(system_data, Key::kCpuVendor, &cpu_vendor_);
GetDataStringFromMap(system_data, Key::kStandardName, &standard_name_);
GetDataStringFromMap(system_data, Key::kDaylightName, &daylight_name_);
GetDataValueFromMap(system_data, Key::kOSVersionMajor, &os_version_major_);
GetDataValueFromMap(system_data, Key::kOSVersionMinor, &os_version_minor_);
GetDataValueFromMap(system_data, Key::kOSVersionBugfix, &os_version_bugfix_);
GetDataValueFromMap(system_data, Key::kCpuCount, &cpu_count_);
GetDataValueFromMap(
system_data, Key::kStandardOffsetSeconds, &standard_offset_seconds_);
GetDataValueFromMap(
system_data, Key::kDaylightOffsetSeconds, &daylight_offset_seconds_);
bool has_daylight_saving_time;
GetDataValueFromMap(
system_data, Key::kHasDaylightSavingTime, &has_daylight_saving_time);
bool is_daylight_saving_time;
GetDataValueFromMap(
system_data, Key::kIsDaylightSavingTime, &is_daylight_saving_time);
if (has_daylight_saving_time) {
dst_status_ = is_daylight_saving_time
? SystemSnapshot::kObservingDaylightSavingTime
: SystemSnapshot::kObservingStandardTime;
} else {
dst_status_ = SystemSnapshot::kDoesNotObserveDaylightSavingTime;
}
GetDataValueFromMap(system_data, Key::kAddressMask, &address_mask_);
vm_size_t page_size;
if (GetDataValueFromMap(system_data, Key::kPageSize, &page_size)) {
const IOSIntermediateDumpMap* vm_stat =
GetMapFromMap(system_data, Key::kVMStat);
if (vm_stat) {
GetDataValueFromMap(vm_stat, Key::kActive, &active_);
active_ *= page_size;
GetDataValueFromMap(vm_stat, Key::kInactive, &inactive_);
inactive_ *= page_size;
GetDataValueFromMap(vm_stat, Key::kWired, &wired_);
wired_ *= page_size;
GetDataValueFromMap(vm_stat, Key::kFree, &free_);
free_ *= page_size;
}
}
GetDataValueFromMap(system_data, Key::kCrashpadUptime, &crashpad_uptime_ns_);
INITIALIZATION_STATE_SET_VALID(initialized_);
}
CPUArchitecture SystemSnapshotIOSIntermediateDump::GetCPUArchitecture() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_64)
return kCPUArchitectureX86_64;
#elif defined(ARCH_CPU_ARM64)
return kCPUArchitectureARM64;
#endif
}
uint32_t SystemSnapshotIOSIntermediateDump::CPURevision() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): sysctlbyname machdep.cpu.* returns -1 on iOS/ARM64, but
// consider recording this for X86_64 only.
return 0;
}
uint8_t SystemSnapshotIOSIntermediateDump::CPUCount() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return cpu_count_;
}
std::string SystemSnapshotIOSIntermediateDump::CPUVendor() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return cpu_vendor_;
}
void SystemSnapshotIOSIntermediateDump::CPUFrequency(uint64_t* current_hz,
uint64_t* max_hz) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): sysctlbyname hw.cpufrequency returns -1 on iOS/ARM64,
// but consider recording this for X86_64 only.
*current_hz = 0;
*max_hz = 0;
}
uint32_t SystemSnapshotIOSIntermediateDump::CPUX86Signature() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider recording this for X86_64 only.
return 0;
}
uint64_t SystemSnapshotIOSIntermediateDump::CPUX86Features() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider recording this for X86_64 only.
return 0;
}
uint64_t SystemSnapshotIOSIntermediateDump::CPUX86ExtendedFeatures() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider recording this for X86_64 only.
return 0;
}
uint32_t SystemSnapshotIOSIntermediateDump::CPUX86Leaf7Features() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider recording this for X86_64 only.
return 0;
}
bool SystemSnapshotIOSIntermediateDump::CPUX86SupportsDAZ() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider recording this for X86_64 only.
return false;
}
SystemSnapshot::OperatingSystem
SystemSnapshotIOSIntermediateDump::GetOperatingSystem() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return kOperatingSystemIOS;
}
bool SystemSnapshotIOSIntermediateDump::OSServer() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return false;
}
void SystemSnapshotIOSIntermediateDump::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 SystemSnapshotIOSIntermediateDump::OSVersionFull() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return base::StringPrintf("%d.%d.%d %s",
os_version_major_,
os_version_minor_,
os_version_bugfix_,
os_version_build_.c_str());
}
std::string SystemSnapshotIOSIntermediateDump::MachineDescription() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return machine_description_;
}
bool SystemSnapshotIOSIntermediateDump::NXEnabled() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
// TODO(justincohen): Consider using kern.nx when available (pre-iOS 13,
// pre-OS X 10.15). Otherwise the bit is always enabled.
return true;
}
void SystemSnapshotIOSIntermediateDump::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_);
*dst_status = dst_status_;
*standard_offset_seconds = standard_offset_seconds_;
*daylight_offset_seconds = daylight_offset_seconds_;
standard_name->assign(standard_name_);
daylight_name->assign(daylight_name_);
}
uint64_t SystemSnapshotIOSIntermediateDump::AddressMask() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return address_mask_;
}
uint64_t SystemSnapshotIOSIntermediateDump::CrashpadUptime() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return crashpad_uptime_ns_;
}
} // namespace internal
} // namespace crashpad