mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
mac: Replace MacOSXMinorVersion with MacOSVersionNumber
MacOSXMinorVersion reported just the “y” value for an OS version 10.y.z. This is no longer sufficient to identify OS versions accurately in macOS 11. A new MacOSVersionNumber function reports the full OS version as “xxyyzz” for an OS version x.y.z. This is the same format used by <Availability.h> __MAC_* macros since 10.10. MacOSXVersion is also renamed to MacOSVersionComponents for disambiguation and proper modern nomenclature. Bug: crashpad:347 Test: crashpad_snapshot_test SystemSnapshotMacTest.OSVersion, crashpad_util_test MacUtil.MacOSVersionNumber Change-Id: I66421954f021c0627095474cb26359970fcd9101 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2386386 Commit-Queue: Mark Mentovai <mark@chromium.org> Reviewed-by: Robert Sesek <rsesek@chromium.org>
This commit is contained in:
parent
3965bc7d78
commit
5412beb633
@ -14,6 +14,7 @@
|
||||
|
||||
#include "client/crashpad_client.h"
|
||||
|
||||
#include <Availability.h>
|
||||
#include <errno.h>
|
||||
#include <mach/mach.h>
|
||||
#include <pthread.h>
|
||||
@ -454,14 +455,15 @@ bool CrashpadClient::StartHandler(
|
||||
// The “restartable” behavior can only be selected on OS X 10.10 and later. In
|
||||
// previous OS versions, if the initial client were to crash while attempting
|
||||
// to restart the handler, it would become an unkillable process.
|
||||
base::mac::ScopedMachSendRight exception_port(
|
||||
HandlerStarter::InitialStart(handler,
|
||||
database,
|
||||
metrics_dir,
|
||||
url,
|
||||
annotations,
|
||||
arguments,
|
||||
restartable && MacOSXMinorVersion() >= 10));
|
||||
base::mac::ScopedMachSendRight exception_port(HandlerStarter::InitialStart(
|
||||
handler,
|
||||
database,
|
||||
metrics_dir,
|
||||
url,
|
||||
annotations,
|
||||
arguments,
|
||||
restartable && (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 ||
|
||||
MacOSVersionNumber() >= 10'10'00)));
|
||||
if (!exception_port.is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/stl_util.h"
|
||||
@ -30,7 +31,7 @@
|
||||
#include "util/numeric/in_range_cast.h"
|
||||
#include "util/numeric/safe_assignment.h"
|
||||
|
||||
#if defined(OS_APPLE)
|
||||
#if defined(OS_MAC)
|
||||
#include <Availability.h>
|
||||
#elif defined(OS_ANDROID)
|
||||
#include <android/api-level.h>
|
||||
@ -69,24 +70,31 @@ std::string BuildString(const SystemSnapshot* system_snapshot) {
|
||||
#if defined(OS_MAC)
|
||||
// Converts the value of the __MAC_OS_X_VERSION_MIN_REQUIRED or
|
||||
// __MAC_OS_X_VERSION_MAX_ALLOWED macro from <Availability.h> to a number
|
||||
// identifying the minor macOS version that it represents. For example, with an
|
||||
// argument of __MAC_10_6, this function will return 6.
|
||||
int AvailabilityVersionToMacOSXMinorVersion(int availability) {
|
||||
// Through __MAC_10_9, the minor version is the tens digit.
|
||||
if (availability >= 1000 && availability <= 1099) {
|
||||
return (availability / 10) % 10;
|
||||
}
|
||||
// identifying the macOS version that it represents, in the same format used by
|
||||
// MacOSVersionNumber(). For example, with an argument of __MAC_10_15, this
|
||||
// function will return 10'15'00, which is incidentally the same as __MAC_10_15.
|
||||
// With an argument of __MAC_10_9, this function will return 10'09'00, different
|
||||
// from __MAC_10_9, which is 10'9'0.
|
||||
int AvailabilityVersionToMacOSVersionNumber(int availability) {
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_10
|
||||
DCHECK_GE(availability, 10'0'0);
|
||||
|
||||
// After __MAC_10_9, the older format was insufficient to represent versions.
|
||||
// Since then, the minor version is the thousands and hundreds digits.
|
||||
if (availability >= 100000 && availability <= 109999) {
|
||||
return (availability / 100) % 100;
|
||||
// Until __MAC_10_10, the format is major * 1'0'0 + minor * 1'0 + bugfix.
|
||||
if (availability >= 10'0'0 && availability <= 10'9'9) {
|
||||
int minor = (availability / 1'0) % 1'0;
|
||||
int bugfix = availability % 1'0;
|
||||
return 10'00'00 + minor * 1'00 + bugfix;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Since __MAC_10_10, the format is major * 1'00'00 + minor * 1'00 + bugfix.
|
||||
DCHECK_GE(availability, 10'10'00);
|
||||
DCHECK_LE(availability, 99'99'99);
|
||||
|
||||
return availability;
|
||||
}
|
||||
#endif // OS_MAC
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
@ -99,8 +107,10 @@ std::string MinidumpMiscInfoDebugBuildString() {
|
||||
// Caution: the minidump file format only has room for 39 UTF-16 code units
|
||||
// plus a UTF-16 NUL terminator. Don’t let strings get longer than this, or
|
||||
// they will be truncated and a message will be logged.
|
||||
#if defined(OS_APPLE)
|
||||
#if defined(OS_MAC)
|
||||
static constexpr char kOS[] = "mac";
|
||||
#elif defined(OS_IOS)
|
||||
static constexpr char kOS[] = "ios";
|
||||
#elif defined(OS_ANDROID)
|
||||
static constexpr char kOS[] = "android";
|
||||
#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
@ -138,8 +148,8 @@ std::string MinidumpMiscInfoDebugBuildString() {
|
||||
#if defined(OS_MAC)
|
||||
debug_build_string += base::StringPrintf(
|
||||
",%d,%d",
|
||||
AvailabilityVersionToMacOSXMinorVersion(__MAC_OS_X_VERSION_MIN_REQUIRED),
|
||||
AvailabilityVersionToMacOSXMinorVersion(__MAC_OS_X_VERSION_MAX_ALLOWED));
|
||||
AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MIN_REQUIRED),
|
||||
AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MAX_ALLOWED));
|
||||
#elif defined(OS_ANDROID)
|
||||
debug_build_string += base::StringPrintf(",%d", __ANDROID_API__);
|
||||
#endif
|
||||
|
@ -124,7 +124,8 @@ class TestMachOImageAnnotationsReader final
|
||||
// _dyld_fatal_error. This changed in 10.12 to use
|
||||
// abort_with_payload(), which appears as SIGABRT to a waiting parent.
|
||||
SetExpectedChildTermination(
|
||||
kTerminationSignal, MacOSXMinorVersion() < 12 ? SIGTRAP : SIGABRT);
|
||||
kTerminationSignal,
|
||||
MacOSVersionNumber() < 10'12'00 ? SIGTRAP : SIGABRT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -186,8 +187,8 @@ class TestMachOImageAnnotationsReader final
|
||||
// Mac OS X 10.6 doesn’t have support for CrashReporter annotations
|
||||
// (CrashReporterClient.h), so don’t look for any special annotations in
|
||||
// that version.
|
||||
int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
if (mac_os_x_minor_version > 7) {
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
if (macos_version_number > 10'07'00) {
|
||||
EXPECT_GE(all_annotations_vector.size(), 1u);
|
||||
|
||||
std::string expected_annotation;
|
||||
@ -204,7 +205,7 @@ class TestMachOImageAnnotationsReader final
|
||||
// exec() occurred. See 10.9.5 Libc-997.90.3/sys/_libc_fork_child.c
|
||||
// _libc_fork_child().
|
||||
expected_annotation =
|
||||
mac_os_x_minor_version <= 8
|
||||
macos_version_number <= 10'08'00
|
||||
? "abort() called"
|
||||
: "crashed on child side of fork pre-exec";
|
||||
break;
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "snapshot/mac/mach_o_image_segment_reader.h"
|
||||
|
||||
#include <Availability.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -44,7 +45,8 @@ bool IsMalformedCLKernelsModule(uint32_t mach_o_file_type,
|
||||
}
|
||||
|
||||
if (module_name == "cl_kernels") {
|
||||
if (MacOSXMinorVersion() >= 10) {
|
||||
if (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 ||
|
||||
MacOSVersionNumber() >= 10'10'00) {
|
||||
if (has_timestamp) {
|
||||
*has_timestamp = false;
|
||||
}
|
||||
@ -57,7 +59,8 @@ bool IsMalformedCLKernelsModule(uint32_t mach_o_file_type,
|
||||
"/private/var/db/CVMS/cvmsCodeSignObj";
|
||||
if (module_name.compare(
|
||||
0, strlen(kCvmsObjectPathPrefix), kCvmsObjectPathPrefix) == 0 &&
|
||||
MacOSXMinorVersion() >= 14) {
|
||||
(__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_14 ||
|
||||
MacOSVersionNumber() >= 10'14'00)) {
|
||||
if (has_timestamp) {
|
||||
*has_timestamp = true;
|
||||
}
|
||||
|
@ -712,11 +712,8 @@ class ScopedOpenCLNoOpKernel {
|
||||
// OpenCL kernels that run on the CPU do not result in cl_kernels images
|
||||
// appearing on that OS version.
|
||||
bool ExpectCLKernels() {
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7
|
||||
return true;
|
||||
#else
|
||||
return MacOSXMinorVersion() >= 7;
|
||||
#endif
|
||||
return __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7 ||
|
||||
MacOSVersionNumber() >= 10'07'00;
|
||||
}
|
||||
|
||||
TEST(ProcessReaderMac, SelfModules) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/numerics/safe_math.h"
|
||||
#include "base/stl_util.h"
|
||||
@ -161,13 +162,13 @@ size_t dyld_all_image_infos<Traits>::ExpectedSizeForVersion(
|
||||
// The revised one in macOS 10.13 grew. It’s safe to assume that the
|
||||
// dyld_all_image_infos structure came from the same system that’s now
|
||||
// interpreting it, so use an OS version check.
|
||||
int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
if (mac_os_x_minor_version == 12) {
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
if (macos_version_number / 1'00 == 10'12) {
|
||||
return offsetof(dyld_all_image_infos<Traits>, end_v14);
|
||||
}
|
||||
|
||||
DCHECK_GE(mac_os_x_minor_version, 13);
|
||||
DCHECK_LE(mac_os_x_minor_version, 14);
|
||||
DCHECK_GE(macos_version_number, 10'13'00);
|
||||
DCHECK_LT(macos_version_number, 10'15'00);
|
||||
return offsetof(dyld_all_image_infos<Traits>, platform);
|
||||
}
|
||||
|
||||
|
@ -48,17 +48,17 @@ namespace {
|
||||
TEST(ProcessTypes, DyldImagesSelf) {
|
||||
// Get the in-process view of dyld_all_image_infos, and check it for sanity.
|
||||
const dyld_all_image_infos* self_image_infos = DyldGetAllImageInfos();
|
||||
const int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
|
||||
if (mac_os_x_minor_version >= 15) {
|
||||
if (macos_version_number >= 10'15'00) {
|
||||
EXPECT_GE(self_image_infos->version, 16u);
|
||||
} else if (mac_os_x_minor_version >= 12) {
|
||||
} else if (macos_version_number >= 10'12'00) {
|
||||
EXPECT_GE(self_image_infos->version, 15u);
|
||||
} else if (mac_os_x_minor_version >= 9) {
|
||||
} else if (macos_version_number >= 10'09'00) {
|
||||
EXPECT_GE(self_image_infos->version, 13u);
|
||||
} else if (mac_os_x_minor_version >= 7) {
|
||||
} else if (macos_version_number >= 10'07'00) {
|
||||
EXPECT_GE(self_image_infos->version, 8u);
|
||||
} else if (mac_os_x_minor_version >= 6) {
|
||||
} else if (macos_version_number >= 10'06'00) {
|
||||
EXPECT_GE(self_image_infos->version, 2u);
|
||||
} else {
|
||||
EXPECT_GE(self_image_infos->version, 1u);
|
||||
@ -91,7 +91,7 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
// This field is only present in the OS X 10.7 SDK (at build time) and kernel
|
||||
// (at run time).
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7
|
||||
if (MacOSXMinorVersion() >= 7) {
|
||||
if (macos_version_number >= 10'07'00) {
|
||||
#if !defined(ARCH_CPU_64_BITS)
|
||||
EXPECT_EQ(dyld_info.all_image_info_format, TASK_DYLD_ALL_IMAGE_INFO_32);
|
||||
#else
|
||||
@ -130,11 +130,11 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
bool test_expected_size_for_version_matches_sdk_sizeof;
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED == __MAC_10_12
|
||||
test_expected_size_for_version_matches_sdk_sizeof =
|
||||
mac_os_x_minor_version == 12;
|
||||
macos_version_number / 1'00 == 10'12;
|
||||
#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13 && \
|
||||
__MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_15
|
||||
test_expected_size_for_version_matches_sdk_sizeof =
|
||||
mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14;
|
||||
macos_version_number >= 10'13'00 && macos_version_number < 10'15'00;
|
||||
#else
|
||||
test_expected_size_for_version_matches_sdk_sizeof = true;
|
||||
#endif
|
||||
@ -177,7 +177,7 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
SCOPED_TRACE(base::StringPrintf("index %zu, version %u", index, version));
|
||||
|
||||
if (version == 15) {
|
||||
if (mac_os_x_minor_version == 12) {
|
||||
if (macos_version_number / 1'00 == 10'12) {
|
||||
EXPECT_EQ(process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits32>::
|
||||
ExpectedSizeForVersion(version),
|
||||
@ -186,7 +186,8 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
process_types::internal::Traits64>::
|
||||
ExpectedSizeForVersion(version),
|
||||
304u);
|
||||
} else if (mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14) {
|
||||
} else if (macos_version_number >= 10'13'00 &&
|
||||
macos_version_number < 10'15'00) {
|
||||
EXPECT_EQ(process_types::internal::dyld_all_image_infos<
|
||||
process_types::internal::Traits32>::
|
||||
ExpectedSizeForVersion(version),
|
||||
@ -362,7 +363,7 @@ TEST(ProcessTypes, DyldImagesSelf) {
|
||||
#endif
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13
|
||||
if (proctype_image_infos.version >= 15 && mac_os_x_minor_version >= 13) {
|
||||
if (proctype_image_infos.version >= 15 && macos_version_number >= 10'13'00) {
|
||||
EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_addr,
|
||||
self_image_infos->compact_dyld_image_info_addr);
|
||||
EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_size,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "snapshot/mac/process_reader_mac.h"
|
||||
#include "snapshot/posix/timezone.h"
|
||||
#include "util/mac/mac_util.h"
|
||||
#include "util/mac/sysctl.h"
|
||||
#include "util/numeric/in_range_cast.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -60,26 +61,6 @@ T CastIntSysctlByName(const char* name, T 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,
|
||||
@ -119,15 +100,15 @@ void SystemSnapshotMac::Initialize(ProcessReaderMac* process_reader,
|
||||
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.
|
||||
// MacOSVersionComponents() 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);
|
||||
MacOSVersionComponents(&os_version_major_,
|
||||
&os_version_minor_,
|
||||
&os_version_bugfix_,
|
||||
&os_version_build_,
|
||||
&os_server_,
|
||||
&os_version_string);
|
||||
|
||||
std::string uname_string;
|
||||
utsname uts;
|
||||
@ -194,9 +175,9 @@ std::string SystemSnapshotMac::CPUVendor() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadStringSysctlByName("machdep.cpu.vendor");
|
||||
return ReadStringSysctlByName("machdep.cpu.vendor", true);
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
return ReadStringSysctlByName("machdep.cpu.brand_string");
|
||||
return ReadStringSysctlByName("machdep.cpu.brand_string", true);
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
@ -368,7 +349,7 @@ bool SystemSnapshotMac::NXEnabled() const {
|
||||
const bool nx_always_enabled = true;
|
||||
#else // DT >= 10.14
|
||||
base::ScopedClearLastError reset_errno;
|
||||
const bool nx_always_enabled = MacOSXMinorVersion() >= 14;
|
||||
const bool nx_always_enabled = MacOSVersionNumber() >= 10'14'00;
|
||||
#endif // DT >= 10.14
|
||||
if (nx_always_enabled) {
|
||||
return true;
|
||||
|
@ -117,8 +117,10 @@ TEST_F(SystemSnapshotMacTest, OSVersion) {
|
||||
std::string build;
|
||||
system_snapshot().OSVersion(&major, &minor, &bugfix, &build);
|
||||
|
||||
EXPECT_EQ(major, 10);
|
||||
EXPECT_EQ(minor, MacOSXMinorVersion());
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
EXPECT_EQ(major * 1'00'00 + minor * 1'00 +
|
||||
(macos_version_number >= 10'12'00 ? bugfix : 0),
|
||||
macos_version_number);
|
||||
EXPECT_FALSE(build.empty());
|
||||
}
|
||||
|
||||
|
@ -339,6 +339,8 @@ static_library("util") {
|
||||
"mac/mac_util.h",
|
||||
"mac/service_management.cc",
|
||||
"mac/service_management.h",
|
||||
"mac/sysctl.cc",
|
||||
"mac/sysctl.h",
|
||||
"mach/bootstrap.cc",
|
||||
"mach/bootstrap.h",
|
||||
"mach/child_port_handshake.cc",
|
||||
@ -746,6 +748,7 @@ source_set("util_test") {
|
||||
"mac/launchd_test.mm",
|
||||
"mac/mac_util_test.mm",
|
||||
"mac/service_management_test.mm",
|
||||
"mac/sysctl_test.cc",
|
||||
"mach/bootstrap_test.cc",
|
||||
"mach/child_port_handshake_test.cc",
|
||||
"mach/child_port_server_test.cc",
|
||||
|
@ -14,20 +14,24 @@
|
||||
|
||||
#include "util/mac/mac_util.h"
|
||||
|
||||
#include <Availability.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/scoped_cftyperef.h"
|
||||
#include "base/mac/scoped_ioobject.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "util/mac/sysctl.h"
|
||||
|
||||
extern "C" {
|
||||
// Private CoreFoundation internals. See 10.9.2 CF-855.14/CFPriv.h and
|
||||
@ -56,9 +60,10 @@ extern const CFStringRef _kCFSystemVersionBuildVersionKey WEAK_IMPORT;
|
||||
|
||||
namespace {
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12
|
||||
// Returns the running system’s Darwin major version. Don’t call this, it’s an
|
||||
// implementation detail and its result is meant to be cached by
|
||||
// MacOSXMinorVersion().
|
||||
// MacOSVersionNumber().
|
||||
//
|
||||
// This is very similar to Chromium’s base/mac/mac_util.mm
|
||||
// DarwinMajorVersionInternal().
|
||||
@ -92,6 +97,7 @@ int DarwinMajorVersion() {
|
||||
|
||||
return darwin_major_version;
|
||||
}
|
||||
#endif // DT < 10.12
|
||||
|
||||
// Helpers for the weak-imported private CoreFoundation internals.
|
||||
|
||||
@ -118,9 +124,10 @@ const void* TryCFDictionaryGetValue(CFDictionaryRef dictionary,
|
||||
}
|
||||
|
||||
// Converts |version| to a triplet of version numbers on behalf of
|
||||
// MacOSXVersion(). Returns true on success. If |version| does not have the
|
||||
// expected format, returns false. |version| must be in the form "10.9.2" or
|
||||
// just "10.9". In the latter case, |bugfix| will be set to 0.
|
||||
// MacOSVersionNumber() and MacOSVersionComponents(). Returns true on success.
|
||||
// If |version| does not have the expected format, returns false. |version| must
|
||||
// be in the form "10.9.2" or just "10.9". In the latter case, |bugfix| will be
|
||||
// set to 0.
|
||||
bool StringToVersionNumbers(const std::string& version,
|
||||
int* major,
|
||||
int* minor,
|
||||
@ -180,20 +187,62 @@ std::string IORegistryEntryDataPropertyAsString(io_registry_entry_t entry,
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
int MacOSXMinorVersion() {
|
||||
// The Darwin major version is always 4 greater than the macOS minor version
|
||||
// for Darwin versions beginning with 6, corresponding to Mac OS X 10.2.
|
||||
static int mac_os_x_minor_version = DarwinMajorVersion() - 4;
|
||||
DCHECK(mac_os_x_minor_version >= 2);
|
||||
return mac_os_x_minor_version;
|
||||
int MacOSVersionNumber() {
|
||||
static int macos_version_number = []() {
|
||||
// kern.osproductversion is a lightweight way to get the operating system
|
||||
// version from the kernel without having to open any files or spin up any
|
||||
// threads, but it’s only available in macOS 10.12 and later.
|
||||
std::string macos_version_number_string =
|
||||
ReadStringSysctlByName("kern.osproductversion",
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12);
|
||||
if (!macos_version_number_string.empty()) {
|
||||
int major;
|
||||
int minor;
|
||||
int bugfix;
|
||||
if (StringToVersionNumbers(
|
||||
macos_version_number_string, &major, &minor, &bugfix)) {
|
||||
DCHECK_GE(major, 10);
|
||||
DCHECK_LE(major, 99);
|
||||
DCHECK_GE(minor, 0);
|
||||
DCHECK_LE(minor, 99);
|
||||
DCHECK_GE(bugfix, 0);
|
||||
DCHECK_LE(bugfix, 99);
|
||||
return major * 1'00'00 + minor * 1'00 + bugfix;
|
||||
}
|
||||
}
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12
|
||||
// On macOS 10.12 and later, the sysctlbyname above should have been
|
||||
// successful.
|
||||
NOTREACHED();
|
||||
return -1;
|
||||
#else // DT >= 10.12
|
||||
// The Darwin major version is always 4 greater than the macOS minor version
|
||||
// for Darwin versions beginning with 6, corresponding to Mac OS X 10.2,
|
||||
// through Darwin 19, corresponding to macOS 10.15.
|
||||
int darwin_major_version = DarwinMajorVersion();
|
||||
DCHECK_GE(darwin_major_version, 6);
|
||||
DCHECK_LE(darwin_major_version, 19);
|
||||
|
||||
int macos_version_number = 10'00'00 + (darwin_major_version - 4) * 1'00;
|
||||
|
||||
// On macOS 10.12 and later, the sysctlbyname above should have been
|
||||
// successful.
|
||||
DCHECK_LT(macos_version_number, 10'12'00);
|
||||
|
||||
return macos_version_number;
|
||||
#endif // DT >= 10.12
|
||||
}();
|
||||
|
||||
return macos_version_number;
|
||||
}
|
||||
|
||||
bool MacOSXVersion(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build,
|
||||
bool* server,
|
||||
std::string* version_string) {
|
||||
bool MacOSVersionComponents(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build,
|
||||
bool* server,
|
||||
std::string* version_string) {
|
||||
base::ScopedCFTypeRef<CFDictionaryRef> dictionary(
|
||||
TryCFCopyServerVersionDictionary());
|
||||
if (dictionary) {
|
||||
@ -217,7 +266,16 @@ bool MacOSXVersion(int* major,
|
||||
success = false;
|
||||
} else {
|
||||
version = base::SysCFStringRefToUTF8(version_cf);
|
||||
success &= StringToVersionNumbers(version, major, minor, bugfix);
|
||||
if (!StringToVersionNumbers(version, major, minor, bugfix)) {
|
||||
success = false;
|
||||
} else {
|
||||
DCHECK_GE(*major, 10);
|
||||
DCHECK_LE(*major, 99);
|
||||
DCHECK_GE(*minor, 0);
|
||||
DCHECK_LE(*minor, 99);
|
||||
DCHECK_GE(*bugfix, 0);
|
||||
DCHECK_LE(*bugfix, 99);
|
||||
}
|
||||
}
|
||||
|
||||
CFStringRef build_cf = base::mac::CFCast<CFStringRef>(
|
||||
|
@ -21,14 +21,24 @@ namespace crashpad {
|
||||
|
||||
//! \brief Returns the version of the running operating system.
|
||||
//!
|
||||
//! \return The minor version of the operating system, such as `12` for macOS
|
||||
//! 10.12.1.
|
||||
//! \return The version of the operating system, such as `10'15'06` for macOS
|
||||
//! 10.15.6.
|
||||
//!
|
||||
//! The format of the return value matches what is used by the <Availability.h>
|
||||
//! `__MAC_OS_X_VERSION_MIN_REQUIRED`, `__MAC_OS_X_VERSION_MAX_ALLOWED`, and
|
||||
//! per-version `__MAC_*` macros, for versions since OS X 10.10.
|
||||
//!
|
||||
//! On macOS 10.12 and later, this function will return the major, minor, and
|
||||
//! bugfix components combined into a single number. On older OS versions, only
|
||||
//! the major and minor components will be returned, and the bugfix component
|
||||
//! will always be reported as 0. By contrast, MacOSVersionComponents() always
|
||||
//! returns the bugfix component.
|
||||
//!
|
||||
//! \note This is similar to the base::mac::IsOS*() family of functions, but
|
||||
//! is provided for situations where the caller needs to obtain version
|
||||
//! information beyond what is provided by Chromium’s base, or for when the
|
||||
//! caller needs the actual minor version value.
|
||||
int MacOSXMinorVersion();
|
||||
int MacOSVersionNumber();
|
||||
|
||||
//! \brief Returns the version of the running operating system.
|
||||
//!
|
||||
@ -51,12 +61,12 @@ int MacOSXMinorVersion();
|
||||
//! A failure is considered to have occurred if any element could not be
|
||||
//! determined. When this happens, their values will be untouched, but other
|
||||
//! values that could be determined will still be set properly.
|
||||
bool MacOSXVersion(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build,
|
||||
bool* server,
|
||||
std::string* version_string);
|
||||
bool MacOSVersionComponents(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build,
|
||||
bool* server,
|
||||
std::string* version_string);
|
||||
|
||||
//! \brief Returns the model name and board ID of the running system.
|
||||
//!
|
||||
|
@ -71,15 +71,22 @@ void SwVers(NSString* argument, std::string* output) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MacUtil, MacOSXVersion) {
|
||||
TEST(MacUtil, MacOSVersionComponents) {
|
||||
int major;
|
||||
int minor;
|
||||
int bugfix;
|
||||
std::string build;
|
||||
bool server;
|
||||
std::string version_string;
|
||||
ASSERT_TRUE(
|
||||
MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string));
|
||||
ASSERT_TRUE(MacOSVersionComponents(
|
||||
&major, &minor, &bugfix, &build, &server, &version_string));
|
||||
|
||||
EXPECT_GE(major, 10);
|
||||
EXPECT_LE(major, 99);
|
||||
EXPECT_GE(minor, 0);
|
||||
EXPECT_LE(minor, 99);
|
||||
EXPECT_GE(bugfix, 0);
|
||||
EXPECT_LE(bugfix, 99);
|
||||
|
||||
std::string version;
|
||||
if (bugfix) {
|
||||
@ -108,20 +115,26 @@ TEST(MacUtil, MacOSXVersion) {
|
||||
EXPECT_EQ(version_string.find(expected_product_name), 0u);
|
||||
}
|
||||
|
||||
TEST(MacUtil, MacOSXMinorVersion) {
|
||||
// Make sure that MacOSXMinorVersion() and MacOSXVersion() agree. The two have
|
||||
// their own distinct implementations, and the latter was checked against
|
||||
// sw_vers above.
|
||||
TEST(MacUtil, MacOSVersionNumber) {
|
||||
// Make sure that MacOSVersionNumber() and MacOSVersionComponents() agree. The
|
||||
// two have their own distinct implementations, and the latter was checked
|
||||
// against sw_vers above.
|
||||
int macos_version_number = MacOSVersionNumber();
|
||||
EXPECT_GE(macos_version_number, 10'00'00);
|
||||
EXPECT_LE(macos_version_number, 99'99'99);
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int bugfix;
|
||||
std::string build;
|
||||
bool server;
|
||||
std::string version_string;
|
||||
ASSERT_TRUE(
|
||||
MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string));
|
||||
ASSERT_TRUE(MacOSVersionComponents(
|
||||
&major, &minor, &bugfix, &build, &server, &version_string));
|
||||
|
||||
EXPECT_EQ(MacOSXMinorVersion(), minor);
|
||||
EXPECT_EQ(macos_version_number,
|
||||
major * 1'00'00 + minor * 1'00 +
|
||||
(macos_version_number >= 10'12'00 ? bugfix : 0));
|
||||
}
|
||||
|
||||
TEST(MacUtil, MacModelAndBoard) {
|
||||
|
47
util/mac/sysctl.cc
Normal file
47
util/mac/sysctl.cc
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2020 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 "util/mac/sysctl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
std::string ReadStringSysctlByName(const char* name, bool may_log_enoent) {
|
||||
size_t buf_len;
|
||||
if (sysctlbyname(name, nullptr, &buf_len, nullptr, 0) != 0) {
|
||||
PLOG_IF(WARNING, may_log_enoent || errno != ENOENT)
|
||||
<< "sysctlbyname (size) " << name;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
DCHECK_GE(buf_len, 1u);
|
||||
|
||||
std::string value(buf_len - 1, '\0');
|
||||
if (sysctlbyname(name, &value[0], &buf_len, nullptr, 0) != 0) {
|
||||
PLOG(WARNING) << "sysctlbyname " << name;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
DCHECK_EQ(value[buf_len - 1], '\0');
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
36
util/mac/sysctl.h
Normal file
36
util/mac/sysctl.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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_UTIL_MAC_SYSCTL_H_
|
||||
#define CRASHPAD_UTIL_MAC_SYSCTL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief Calls `sysctlbyname` to read a string.
|
||||
//!
|
||||
//! \param[in] name The string name of the sysctl to raed.
|
||||
//! \param[in] may_log_enoent If `true`, allows a warning to be logged if the
|
||||
//! sysctl is not found, indicated by `sysctlbyname` setting `errno` to
|
||||
//! `ENOENT`. If `false`, no warning will be logged if the sysctl is
|
||||
//! missing, and an empty string will be returned silently.
|
||||
//!
|
||||
//! \return The value of the sysctl read on success. On failure, an empty string
|
||||
//! with a warning logged, subject to \a may_log_enoent.
|
||||
std::string ReadStringSysctlByName(const char* name, bool may_log_enoent);
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_UTIL_MAC_SYSCTL_H_
|
35
util/mac/sysctl_test.cc
Normal file
35
util/mac/sysctl_test.cc
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2020 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 "util/mac/sysctl.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
TEST(Sysctl, ReadStringSysctlByName) {
|
||||
// kern.ostype is always provided by the kernel, and it’s a constant across
|
||||
// all versions, so it makes for a good test.
|
||||
EXPECT_EQ(ReadStringSysctlByName("kern.ostype", true), "Darwin");
|
||||
|
||||
// Names expected to not exist.
|
||||
EXPECT_TRUE(ReadStringSysctlByName("kern.scheisskopf", true).empty());
|
||||
EXPECT_TRUE(ReadStringSysctlByName("kern.sanders", false).empty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
@ -683,7 +683,7 @@ kern_return_t ExcServerSuccessfulReturnValue(exception_type_t exception,
|
||||
bool set_thread_state) {
|
||||
if (exception == EXC_CRASH
|
||||
#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_11
|
||||
&& MacOSXMinorVersion() >= 11
|
||||
&& MacOSVersionNumber() >= 10'11'00
|
||||
#endif
|
||||
) {
|
||||
return KERN_SUCCESS;
|
||||
|
@ -1210,7 +1210,7 @@ TEST(ExcServerVariants, ExcServerSuccessfulReturnValue) {
|
||||
const kern_return_t prefer_not_set_thread_state = KERN_SUCCESS;
|
||||
#else
|
||||
const kern_return_t prefer_not_set_thread_state =
|
||||
MacOSXMinorVersion() < 11 ? MACH_RCV_PORT_DIED : KERN_SUCCESS;
|
||||
MacOSVersionNumber() < 10'11'00 ? MACH_RCV_PORT_DIED : KERN_SUCCESS;
|
||||
#endif
|
||||
|
||||
const struct {
|
||||
|
@ -259,7 +259,8 @@ bool IsExceptionNonfatalResource(exception_type_t exception,
|
||||
// creation but can be made fatal by calling proc_rlimit_control() with
|
||||
// RLIMIT_CPU_USAGE_MONITOR as the second argument and CPUMON_MAKE_FATAL set
|
||||
// in the flags.
|
||||
if (MacOSXMinorVersion() >= 10) {
|
||||
if (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 ||
|
||||
MacOSVersionNumber() >= 10'10'00) {
|
||||
// In OS X 10.10, the exception code indicates whether the exception is
|
||||
// fatal. See 10.10 xnu-2782.1.97/osfmk/kern/thread.c
|
||||
// THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU__SENDING_EXC_RESOURCE().
|
||||
|
@ -269,7 +269,7 @@ TEST(ExceptionTypes, IsExceptionNonfatalResource) {
|
||||
EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR);
|
||||
EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid));
|
||||
|
||||
if (MacOSXMinorVersion() >= 10) {
|
||||
if (MacOSVersionNumber() >= 10'10'00) {
|
||||
// FLAVOR_CPU_MONITOR_FATAL was introduced in OS X 10.10.
|
||||
code = EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU,
|
||||
FLAVOR_CPU_MONITOR_FATAL);
|
||||
|
@ -50,7 +50,7 @@ exception_mask_t ExcMaskAll() {
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9
|
||||
const int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
#endif
|
||||
|
||||
// See 10.6.8 xnu-1504.15.3/osfmk/mach/exception_types.h. 10.7 uses the same
|
||||
@ -67,7 +67,7 @@ exception_mask_t ExcMaskAll() {
|
||||
EXC_MASK_RPC_ALERT |
|
||||
EXC_MASK_MACHINE;
|
||||
#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8
|
||||
if (mac_os_x_minor_version < 8) {
|
||||
if (macos_version_number < 10'08'00) {
|
||||
return kExcMaskAll_10_6;
|
||||
}
|
||||
#endif
|
||||
@ -77,7 +77,7 @@ exception_mask_t ExcMaskAll() {
|
||||
constexpr exception_mask_t kExcMaskAll_10_8 =
|
||||
kExcMaskAll_10_6 | EXC_MASK_RESOURCE;
|
||||
#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9
|
||||
if (mac_os_x_minor_version < 9) {
|
||||
if (macos_version_number < 10'09'00) {
|
||||
return kExcMaskAll_10_8;
|
||||
}
|
||||
#endif
|
||||
@ -97,7 +97,7 @@ exception_mask_t ExcMaskValid() {
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_11
|
||||
if (MacOSXMinorVersion() < 11) {
|
||||
if (MacOSVersionNumber() < 10'11'00) {
|
||||
return kExcMaskValid_10_6;
|
||||
}
|
||||
#endif
|
||||
|
@ -85,14 +85,14 @@ TEST(MachExtensions, ExcMaskAll) {
|
||||
EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE);
|
||||
EXPECT_TRUE(exc_mask_all & EXC_MASK_GUARD);
|
||||
#else // OS_IOS
|
||||
const int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
if (mac_os_x_minor_version >= 8) {
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
if (macos_version_number >= 10'08'00) {
|
||||
EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE);
|
||||
} else {
|
||||
EXPECT_FALSE(exc_mask_all & EXC_MASK_RESOURCE);
|
||||
}
|
||||
|
||||
if (mac_os_x_minor_version >= 9) {
|
||||
if (macos_version_number >= 10'09'00) {
|
||||
EXPECT_TRUE(exc_mask_all & EXC_MASK_GUARD);
|
||||
} else {
|
||||
EXPECT_FALSE(exc_mask_all & EXC_MASK_GUARD);
|
||||
@ -118,20 +118,20 @@ TEST(MachExtensions, ExcMaskValid) {
|
||||
EXPECT_TRUE(exc_mask_valid & EXC_MASK_GUARD);
|
||||
EXPECT_TRUE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
|
||||
#else // OS_IOS
|
||||
const int mac_os_x_minor_version = MacOSXMinorVersion();
|
||||
if (mac_os_x_minor_version >= 8) {
|
||||
const int macos_version_number = MacOSVersionNumber();
|
||||
if (macos_version_number >= 10'08'00) {
|
||||
EXPECT_TRUE(exc_mask_valid & EXC_MASK_RESOURCE);
|
||||
} else {
|
||||
EXPECT_FALSE(exc_mask_valid & EXC_MASK_RESOURCE);
|
||||
}
|
||||
|
||||
if (mac_os_x_minor_version >= 9) {
|
||||
if (macos_version_number >= 10'09'00) {
|
||||
EXPECT_TRUE(exc_mask_valid & EXC_MASK_GUARD);
|
||||
} else {
|
||||
EXPECT_FALSE(exc_mask_valid & EXC_MASK_GUARD);
|
||||
}
|
||||
|
||||
if (mac_os_x_minor_version >= 11) {
|
||||
if (macos_version_number >= 10'11'00) {
|
||||
EXPECT_TRUE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
|
||||
} else {
|
||||
EXPECT_FALSE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
|
||||
|
@ -102,6 +102,8 @@
|
||||
'mac/mac_util.h',
|
||||
'mac/service_management.cc',
|
||||
'mac/service_management.h',
|
||||
'mac/sysctl.cc',
|
||||
'mac/sysctl.h',
|
||||
'mac/xattr.cc',
|
||||
'mac/xattr.h',
|
||||
'mach/child_port.defs',
|
||||
|
@ -53,6 +53,7 @@
|
||||
'mac/launchd_test.mm',
|
||||
'mac/mac_util_test.mm',
|
||||
'mac/service_management_test.mm',
|
||||
'mac/sysctl_test.cc',
|
||||
'mac/xattr_test.cc',
|
||||
'mach/child_port_handshake_test.cc',
|
||||
'mach/child_port_server_test.cc',
|
||||
|
Loading…
x
Reference in New Issue
Block a user