mac: Update the dyld_all_image_infos structure for 10.12

BUG=crashpad:120

Change-Id: I7b2df5f2de13517b2586569ce267bcb0ae845101
Reviewed-on: https://chromium-review.googlesource.com/353830
Reviewed-by: Robert Sesek <rsesek@chromium.org>
This commit is contained in:
Mark Mentovai 2016-06-17 22:03:01 -04:00
parent 495a64fcdb
commit c281e30f93
10 changed files with 133 additions and 52 deletions

View File

@ -47,4 +47,10 @@
#define MAC_OS_X_VERSION_10_11 101100
#endif
// 10.12 SDK
#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
#endif // CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_

View File

@ -444,6 +444,9 @@ void ProcessReader::InitializeModules() {
if (all_image_infos.version >= 2 && all_image_infos.dyldImageLoadAddress &&
image_info.imageLoadAddress == all_image_infos.dyldImageLoadAddress) {
found_dyld = true;
LOG(WARNING) << base::StringPrintf(
"found dylinker (%s) in dyld_all_image_infos::infoArray",
module.name.c_str());
LOG_IF(WARNING, file_type != MH_DYLINKER)
<< base::StringPrintf("dylinker (%s) has unexpected Mach-O type %d",

View File

@ -56,6 +56,8 @@ namespace crashpad {
namespace test {
namespace {
const char kDyldPath[] = "/usr/lib/dyld";
TEST(ProcessReader, SelfBasic) {
ProcessReader process_reader;
ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
@ -690,7 +692,7 @@ TEST(ProcessReader, SelfModules) {
EXPECT_EQ(ExpectCLKernels(), found_cl_kernels);
size_t index = modules.size() - 1;
EXPECT_EQ("/usr/lib/dyld", modules[index].name);
EXPECT_EQ(kDyldPath, modules[index].name);
// dyld didnt load itself either, so it couldnt record its timestamp, and it
// is also reported as 0.
@ -800,7 +802,7 @@ class ProcessReaderModulesChild final : public MachMultiprocess {
dyld_image_address =
reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index));
} else {
dyld_image_name = "/usr/lib/dyld";
dyld_image_name = kDyldPath;
dyld_image_address = reinterpret_cast<mach_vm_address_t>(
dyld_image_infos->dyldImageLoadAddress);
}

View File

@ -36,44 +36,39 @@ inline void Assign(DestinationType* destination, const SourceType& source) {
*destination = source;
}
template <typename Type>
inline void Assign(Type* destination, const Type& source) {
memcpy(destination, &source, sizeof(source));
}
template <>
inline void Assign<process_types::internal::Reserved64Only64,
process_types::internal::Reserved64Only32>(
process_types::internal::Reserved64Only64* destination,
const process_types::internal::Reserved64Only32& source) {
// Reserved64Only32 carries no data.
inline void Assign<process_types::internal::Reserved32_64Only64,
process_types::internal::Reserved32_64Only32>(
process_types::internal::Reserved32_64Only64* destination,
const process_types::internal::Reserved32_64Only32& source) {
// Reserved32_64Only32 carries no data.
*destination = 0;
}
using CharArray16 = char[16];
template <>
inline void Assign<CharArray16, CharArray16>(CharArray16* destination,
const CharArray16& source) {
memcpy(destination, &source, sizeof(source));
inline void Assign<process_types::internal::Reserved64_64Only64,
process_types::internal::Reserved64_64Only32>(
process_types::internal::Reserved64_64Only64* destination,
const process_types::internal::Reserved64_64Only32& source) {
// Reserved64_64Only32 carries no data.
*destination = 0;
}
using UInt64Array16 = uint64_t[16];
using UInt32Array10 = uint32_t[10];
using UInt64Array10 = uint64_t[10];
template <>
inline void Assign<UInt64Array16, UInt64Array16>(UInt64Array16* destination,
const UInt64Array16& source) {
memcpy(destination, &source, sizeof(source));
}
using UInt32Array16 = uint32_t[16];
template <>
inline void Assign<UInt64Array16, UInt32Array16>(UInt64Array16* destination,
const UInt32Array16& source) {
inline void Assign<UInt64Array10, UInt32Array10>(UInt64Array10* destination,
const UInt32Array10& source) {
for (size_t index = 0; index < arraysize(source); ++index) {
(*destination)[index] = source[index];
}
}
template <>
inline void Assign<uuid_t, uuid_t>(uuid_t* destination, const uuid_t& source) {
// uuid_t is a type alias for unsigned char[16].
memcpy(destination, &source, sizeof(source));
}
} // namespace
} // namespace crashpad

View File

@ -29,10 +29,12 @@ namespace internal {
// Some structure definitions differ in 32-bit and 64-bit environments by having
// additional “reserved” padding fields present only in the 64-bit environment.
// These Reserved64Only* types allow the process_types system to replicate these
// structures more precisely.
using Reserved64Only32 = char[0];
using Reserved64Only64 = uint32_t;
// These Reserved*_64Only* types allow the process_types system to replicate
// these structures more precisely.
using Reserved32_64Only32 = char[0];
using Reserved32_64Only64 = uint32_t;
using Reserved64_64Only32 = char[0];
using Reserved64_64Only64 = uint64_t;
} // namespace internal
} // namespace process_types
@ -61,7 +63,8 @@ DECLARE_PROCESS_TYPE_TRAITS_CLASS(Generic, 64)
using Pointer = internal::TraitsGeneric::Pointer; \
using IntPtr = internal::TraitsGeneric::IntPtr; \
using UIntPtr = internal::TraitsGeneric::UIntPtr; \
using Reserved64Only = internal::TraitsGeneric::Reserved64Only; \
using Reserved32_64Only = internal::TraitsGeneric::Reserved32_64Only; \
using Reserved64_64Only = internal::TraitsGeneric::Reserved64_64Only; \
\
/* Initializes an object with data read from |process_reader| at \
* |address|, properly genericized. */ \
@ -150,7 +153,8 @@ DECLARE_PROCESS_TYPE_TRAITS_CLASS(Generic, 64)
using Pointer = typename Traits::Pointer; \
using IntPtr = typename Traits::IntPtr; \
using UIntPtr = typename Traits::UIntPtr; \
using Reserved64Only = typename Traits::Reserved64Only; \
using Reserved32_64Only = typename Traits::Reserved32_64Only; \
using Reserved64_64Only = typename Traits::Reserved64_64Only; \
\
/* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \
* struct above. */ \

View File

@ -64,7 +64,7 @@ size_t dyld_all_image_infos<Traits>::ExpectedSizeForVersion(
return sizeof(dyld_all_image_infos<Traits>);
}
if (version >= 13) {
return offsetof(dyld_all_image_infos<Traits>, reserved);
return offsetof(dyld_all_image_infos<Traits>, infoArrayChangeTimestamp);
}
if (version >= 12) {
return offsetof(dyld_all_image_infos<Traits>, sharedCacheUUID);

View File

@ -61,7 +61,7 @@ PROCESS_TYPE_STRUCT_BEGIN(dyld_all_image_infos)
// of the process_types structure matches the genuine 64-bit structure. This
// is required because the alignment constraints on 64-bit types are more
// stringent in 64-bit mode.
PROCESS_TYPE_STRUCT_MEMBER(Reserved64Only, alignment)
PROCESS_TYPE_STRUCT_MEMBER(Reserved32_64Only, alignment)
// const mach_header*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldImageLoadAddress)
@ -80,31 +80,46 @@ PROCESS_TYPE_STRUCT_BEGIN(dyld_all_image_infos)
// Version 7 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, systemOrderFlag)
// Version 8 (Mac OS X 10.7)
// Version 8 (OS X 10.7)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, uuidArrayCount)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, uuidArray) // const dyld_uuid_info*
// Version 9 (Mac OS X 10.7)
// Version 9 (OS X 10.7)
// dyld_all_image_infos*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldAllImageInfosAddress)
// Version 10 (Mac OS X 10.7)
// Version 10 (OS X 10.7)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, initialImageCount)
// Version 11 (Mac OS X 10.7)
// Version 11 (OS X 10.7)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, errorKind)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, errorClientOfDylibPath) // const char*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, errorTargetDylibPath) // const char*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, errorSymbol) // const char*
// Version 12 (Mac OS X 10.7)
// Version 12 (OS X 10.7)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, sharedCacheSlide)
// Version 13 (Mac OS X 10.9)
// Version 13 (OS X 10.9)
PROCESS_TYPE_STRUCT_MEMBER(uint8_t, sharedCacheUUID, [16])
// Version 14 (Mac OS X 10.9)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, reserved, [16])
// Version 15 (macOS 10.12)
// This space is also allocated in version 14 (OS X 10.9) as part of the
// “reserved” member.
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, infoArrayChangeTimestamp)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, sharedCacheBaseAddress)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldPath) // const char*
// These should be considered mach_port_name_t when interacting with them from
// another Mach IPC namespace (process).
PROCESS_TYPE_STRUCT_MEMBER(mach_port_t, notifyPorts, [2])
// Version 14 (OS X 10.9)
// As of the 10.12 SDK, this is declared as reserved[10] for 64-bit platforms
// and reserved[12] for 32-bit platforms.
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, reserved, [10])
PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_10)
PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_11)
PROCESS_TYPE_STRUCT_END(dyld_all_image_infos)
#endif // ! PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO &&

View File

@ -36,7 +36,7 @@ PROCESS_TYPE_STRUCT_BEGIN(mach_header) // 64-bit: mach_header_64
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, ncmds)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, sizeofcmds)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, flags)
PROCESS_TYPE_STRUCT_MEMBER(Reserved64Only, reserved)
PROCESS_TYPE_STRUCT_MEMBER(Reserved32_64Only, reserved)
PROCESS_TYPE_STRUCT_END(mach_header)
PROCESS_TYPE_STRUCT_BEGIN(load_command)
@ -136,5 +136,5 @@ PROCESS_TYPE_STRUCT_BEGIN(section) // 64-bit: section_64
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, flags)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, reserved1)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, reserved2)
PROCESS_TYPE_STRUCT_MEMBER(Reserved64Only, reserved3)
PROCESS_TYPE_STRUCT_MEMBER(Reserved32_64Only, reserved3)
PROCESS_TYPE_STRUCT_END(section)

View File

@ -22,9 +22,9 @@
// DECLARE_PROCESS_TYPE_TRAITS_CLASS before #including this file again and after
// the last #include of this file.
//
// |Reserved| is used for padding fields that may be zero-length, and thus
// |Reserved*| are used for padding fields that may be zero-length, and thus
// __VA_ARGS__, which is intended to set the alignment of the 64-bit types, is
// not used for that type alias.
// not used for those type aliases.
#define DECLARE_PROCESS_TYPE_TRAITS_CLASS(traits_name, lp_bits, ...) \
namespace crashpad { \
namespace process_types { \
@ -35,7 +35,8 @@
using Pointer = uint##lp_bits##_t __VA_ARGS__; \
using IntPtr = int##lp_bits##_t __VA_ARGS__; \
using UIntPtr = uint##lp_bits##_t __VA_ARGS__; \
using Reserved64Only = Reserved64Only##lp_bits; \
using Reserved32_64Only = Reserved32_64Only##lp_bits; \
using Reserved64_64Only = Reserved64_64Only##lp_bits; \
}; \
} \
} \

View File

@ -47,7 +47,9 @@ TEST(ProcessTypes, DyldImagesSelf) {
const struct dyld_all_image_infos* self_image_infos =
_dyld_get_all_image_infos();
int mac_os_x_minor_version = MacOSXMinorVersion();
if (mac_os_x_minor_version >= 9) {
if (mac_os_x_minor_version >= 12) {
EXPECT_GE(self_image_infos->version, 15u);
} else if (mac_os_x_minor_version >= 9) {
EXPECT_GE(self_image_infos->version, 13u);
} else if (mac_os_x_minor_version >= 7) {
EXPECT_GE(self_image_infos->version, 8u);
@ -96,6 +98,24 @@ TEST(ProcessTypes, DyldImagesSelf) {
ProcessReader process_reader;
ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
const uint32_t kDyldAllImageInfosVersionInSDK = 15;
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
const uint32_t kDyldAllImageInfosVersionInSDK = 14;
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
const uint32_t kDyldAllImageInfosVersionInSDK = 12;
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
const uint32_t kDyldAllImageInfosVersionInSDK = 7;
#else
const uint32_t kDyldAllImageInfosVersionInSDK = 1;
#endif
// Make sure that the size of the structure as declared in the SDK matches the
// size expected for the version of the structure that the SDK describes.
EXPECT_EQ(sizeof(dyld_all_image_infos),
process_types::dyld_all_image_infos::ExpectedSizeForVersion(
&process_reader, kDyldAllImageInfosVersionInSDK));
process_types::dyld_all_image_infos proctype_image_infos;
ASSERT_TRUE(proctype_image_infos.Read(&process_reader,
dyld_info.all_image_info_addr));
@ -194,13 +214,46 @@ TEST(ProcessTypes, DyldImagesSelf) {
proctype_image_infos.sharedCacheUUID,
sizeof(self_image_infos->sharedCacheUUID)));
}
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
if (proctype_image_infos.version >= 15) {
EXPECT_EQ(self_image_infos->infoArrayChangeTimestamp,
proctype_image_infos.infoArrayChangeTimestamp);
EXPECT_EQ(self_image_infos->sharedCacheBaseAddress,
proctype_image_infos.sharedCacheBaseAddress);
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->dyldPath),
proctype_image_infos.dyldPath);
for (size_t index = 0;
index < arraysize(self_image_infos->notifyPorts);
++index) {
EXPECT_EQ(self_image_infos->notifyPorts[index],
proctype_image_infos.notifyPorts[index]) << "index " << index;
}
TEST_STRING(
process_reader, self_image_infos, proctype_image_infos, dyldPath);
}
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
// As dyld_all_image_infos has evolved over time, new fields were added to the
// reserved region. process_types::dyld_all_image_infos declares a recent
// version of the structure, but an older SDK may declare an older version
// whose |reserved| member appears at a different (smaller) offset than the
// process_types version. Its difficult to compare the reserved fields in
// these older SDKs, so only do it where the declarations match.
if (proctype_image_infos.version >= 14) {
for (size_t index = 0; index < arraysize(self_image_infos->reserved);
for (size_t index = 0;
index < arraysize(proctype_image_infos.reserved);
++index) {
EXPECT_EQ(implicit_cast<uint64_t>(self_image_infos->reserved[index]),
proctype_image_infos.reserved[index])
<< "index " << index;
}
#if defined(ARCH_CPU_64_BITS)
EXPECT_EQ(self_image_infos->reserved[10], proctype_image_infos.reserved_10);
EXPECT_EQ(self_image_infos->reserved[11], proctype_image_infos.reserved_11);
#endif
}
#endif
@ -213,7 +266,8 @@ TEST(ProcessTypes, DyldImagesSelf) {
proctype_image_info_vector.size(),
&proctype_image_info_vector[0]));
for (size_t index = 0; index < proctype_image_infos.infoArrayCount;
for (size_t index = 0;
index < proctype_image_infos.infoArrayCount;
++index) {
const dyld_image_info* self_image_info =
&self_image_infos->infoArray[index];
@ -245,7 +299,8 @@ TEST(ProcessTypes, DyldImagesSelf) {
proctype_uuid_info_vector.size(),
&proctype_uuid_info_vector[0]));
for (size_t index = 0; index < proctype_image_infos.uuidArrayCount;
for (size_t index = 0;
index < proctype_image_infos.uuidArrayCount;
++index) {
const dyld_uuid_info* self_uuid_info =
&self_image_infos->uuidArray[index];