Add ProcessTypes, its test, and many proctype definition files.

TEST=util_test ProcessTypes.DyldImagesSelf
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/501203002
This commit is contained in:
Mark Mentovai 2014-08-26 17:08:18 -04:00
parent 0cc86a24f9
commit 30589d87a9
13 changed files with 1240 additions and 0 deletions

244
util/mac/process_types.cc Normal file
View File

@ -0,0 +1,244 @@
// 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 "util/mac/process_types.h"
#include <string.h>
#include <uuid/uuid.h>
#include "base/memory/scoped_ptr.h"
#include "util/mac/process_types/internal.h"
#include "util/mach/task_memory.h"
namespace crashpad {
namespace {
// Assign() is used by each flavor's ReadInto implementation to copy data from a
// specific struct to a generic struct. For fundamental types, the assignment
// operator suffices. For other types such as arrays, an explicit Assign
// specialization is needed, typically performing a copy.
template <typename DestinationType, typename SourceType>
inline void Assign(DestinationType* destination, const SourceType& source) {
*destination = 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.
*destination = 0;
}
typedef char CharArray16[16];
template <>
inline void Assign<CharArray16, CharArray16>(CharArray16* destination,
const CharArray16& source) {
memcpy(destination, &source, sizeof(source));
}
typedef uint64_t UInt64Array16[16];
template <>
inline void Assign<UInt64Array16, UInt64Array16>(UInt64Array16* destination,
const UInt64Array16& source) {
memcpy(destination, &source, sizeof(source));
}
typedef uint32_t UInt32Array16[16];
template <>
inline void Assign<UInt64Array16, UInt32Array16>(UInt64Array16* destination,
const UInt32Array16& 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 typedef for unsigned char[16].
memcpy(destination, &source, sizeof(source));
}
} // namespace
} // namespace crashpad
// Implement the generic crashpad::process_types::struct_name ReadInto(), which
// delegates to the templatized ReadIntoInternal(), which reads the specific
// struct type from the remote process and genericizes it. Also implement
// crashpad::process_types::internal::struct_name<> GenericizeInto(), which
// operates on each member in the struct.
#define PROCESS_TYPE_STRUCT_IMPLEMENT 1
#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \
namespace crashpad { \
namespace process_types { \
\
size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \
if (!process_reader->Is64Bit()) { \
return internal::struct_name<internal::Traits32>::Size(); \
} else { \
return internal::struct_name<internal::Traits64>::Size(); \
} \
} \
\
bool struct_name::ReadInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name* generic) { \
if (!process_reader->Is64Bit()) { \
return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \
process_reader, address, generic); \
} else { \
return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \
process_reader, address, generic); \
} \
} \
\
template <typename T> \
bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name* generic) { \
T specific; \
if (!specific.Read(process_reader, address)) { \
return false; \
} \
specific.GenericizeInto(generic, &generic->size_); \
return true; \
} \
\
namespace internal { \
\
template <typename Traits> \
void struct_name<Traits>::GenericizeInto( \
process_types::struct_name* generic, \
size_t* specific_size) { \
*specific_size = Size();
#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \
Assign(&generic->member_name, member_name);
#define PROCESS_TYPE_STRUCT_END(struct_name) \
} \
} /* namespace internal */ \
} /* namespace process_types */ \
} /* namespace crashpad */
#include "util/mac/process_types/all.proctype"
#undef PROCESS_TYPE_STRUCT_BEGIN
#undef PROCESS_TYPE_STRUCT_MEMBER
#undef PROCESS_TYPE_STRUCT_END
#undef PROCESS_TYPE_STRUCT_IMPLEMENT
// Implement the specific crashpad::process_types::internal::struct_name<>
// ReadInto(). The default implementation simply reads the struct from the
// remote process. This is separated from other method implementations because
// some types may wish to provide custom readers. This can be done by guarding
// such types proctype definitions against this macro and providing custom
// implementations in util/mac/process_types/custom.cc.
#define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1
#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \
namespace crashpad { \
namespace process_types { \
namespace internal { \
\
template <typename Traits> \
bool struct_name<Traits>::ReadInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name<Traits>* specific) { \
return process_reader->Memory()->Read( \
address, sizeof(*specific), specific); \
} \
} /* namespace internal */ \
} /* namespace process_types */ \
} /* namespace crashpad */
#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)
#define PROCESS_TYPE_STRUCT_END(struct_name)
#include "util/mac/process_types/all.proctype"
#undef PROCESS_TYPE_STRUCT_BEGIN
#undef PROCESS_TYPE_STRUCT_MEMBER
#undef PROCESS_TYPE_STRUCT_END
#undef PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO
// Implement the array operations. These are separated from other method
// implementations because some types are variable-length and are never stored
// as direct-access arrays. It would be incorrect to provide reader
// implementations for such types. Types that wish to suppress array operations
// can do so by guarding their proctype definitions against this macro.
#define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1
#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \
namespace crashpad { \
namespace process_types { \
namespace internal { \
\
template <typename Traits> \
bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name<Traits>* specific) { \
return process_reader->Memory()->Read( \
address, sizeof(struct_name<Traits> [count]), specific); \
} \
} /* namespace internal */ \
\
bool struct_name::ReadArrayInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name* generic) { \
if (!process_reader->Is64Bit()) { \
return ReadArrayIntoInternal< \
internal::struct_name<internal::Traits32> >( \
process_reader, address, count, generic); \
} else { \
return ReadArrayIntoInternal< \
internal::struct_name<internal::Traits64> >( \
process_reader, address, count, generic); \
} \
return true; \
} \
\
template <typename T> \
bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name* generic) { \
scoped_ptr<T[]> specific(new T[count]); \
if (!T::ReadArrayInto(process_reader, address, count, &specific[0])) { \
return false; \
} \
for (size_t index = 0; index < count; ++index) { \
specific[index].GenericizeInto(&generic[index], &generic[index].size_); \
} \
return true; \
} \
} /* namespace process_types */ \
} /* namespace crashpad */
#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)
#define PROCESS_TYPE_STRUCT_END(struct_name)
#include "util/mac/process_types/all.proctype"
#undef PROCESS_TYPE_STRUCT_BEGIN
#undef PROCESS_TYPE_STRUCT_MEMBER
#undef PROCESS_TYPE_STRUCT_END
#undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY

183
util/mac/process_types.h Normal file
View File

@ -0,0 +1,183 @@
// 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_UTIL_MAC_PROCESS_TYPES_H_
#define CRASHPAD_UTIL_MAC_PROCESS_TYPES_H_
#include <mach/mach.h>
#include <mach-o/dyld_images.h>
#include <mach-o/loader.h>
#include <stdint.h>
#include <sys/types.h>
#include "util/mac/process_reader.h"
namespace crashpad {
namespace process_types {
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.
typedef char Reserved64Only32[0];
typedef uint32_t Reserved64Only64;
} // namespace internal
} // namespace process_types
} // namespace crashpad
#include "util/mac/process_types/traits.h"
// Creates the traits type crashpad::process_types::internal::TraitsGeneric.
DECLARE_PROCESS_TYPE_TRAITS_CLASS(Generic, 64)
#undef DECLARE_PROCESS_TYPE_TRAITS_CLASS
// Declare the crashpad::process_types::struct_name structs. These are the
// user-visible generic structs that callers will interact with. They read data
// from 32-bit or 64-bit processes by using the specific internal templatized
// structs below.
#define PROCESS_TYPE_STRUCT_DECLARE 1
#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \
namespace crashpad { \
namespace process_types { \
struct struct_name { \
public: \
typedef internal::TraitsGeneric::Long Long; \
typedef internal::TraitsGeneric::ULong ULong; \
typedef internal::TraitsGeneric::Pointer Pointer; \
typedef internal::TraitsGeneric::IntPtr IntPtr; \
typedef internal::TraitsGeneric::UIntPtr UIntPtr; \
typedef internal::TraitsGeneric::Reserved64Only Reserved64Only; \
\
/* Initializes an object with data read from |process_reader| at \
* |address|, properly genericized. */ \
bool Read(ProcessReader* process_reader, mach_vm_address_t address) { \
return ReadInto(process_reader, address, this); \
} \
\
/* Reads |count| objects from |process_reader| beginning at |address|, and \
* genericizes the objects. The caller must provide storage for |count| \
* objects in |generic|. */ \
static bool ReadArrayInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name* generic); \
\
/* Returns the size of the object that was read. This is the size of the \
* storage in the process that the data is read from, and is not the same \
* as the size of the generic struct. */ \
size_t Size() const { return size_; } \
\
/* Similar to Size(), but computes the expected size of a structure based \
* on the process bitness. This can be used prior to reading any data \
* from a process. */ \
static size_t ExpectedSize(ProcessReader* process_reader);
#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \
member_type member_name __VA_ARGS__;
#define PROCESS_TYPE_STRUCT_END(struct_name) \
private: \
/* The static form of Read(). Populates the struct at |generic|. */ \
static bool ReadInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name* generic); \
\
template <typename T> \
static bool ReadIntoInternal(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name* generic); \
template <typename T> \
static bool ReadArrayIntoInternal(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name* generic); \
size_t size_; \
}; \
} /* namespace process_types */ \
} /* namespace crashpad */
#include "util/mac/process_types/all.proctype"
#undef PROCESS_TYPE_STRUCT_BEGIN
#undef PROCESS_TYPE_STRUCT_MEMBER
#undef PROCESS_TYPE_STRUCT_END
#undef PROCESS_TYPE_STRUCT_DECLARE
// Declare the templatized crashpad::process_types::internal::struct_name<>
// structs. These are the 32-bit and 64-bit specific structs that describe the
// layout of objects in another process. This is repeated instead of being
// shared with the generic declaration above because both the generic and
// templatized specific structs need all of the struct members declared.
//
//
// GenericizeInto() translates a struct from the representation used in the
// remote process into the generic form.
#define PROCESS_TYPE_STRUCT_DECLARE_INTERNAL 1
#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \
namespace crashpad { \
namespace process_types { \
namespace internal { \
template <typename Traits> \
struct struct_name { \
public: \
typedef typename Traits::Long Long; \
typedef typename Traits::ULong ULong; \
typedef typename Traits::Pointer Pointer; \
typedef typename Traits::IntPtr IntPtr; \
typedef typename Traits::UIntPtr UIntPtr; \
typedef typename Traits::Reserved64Only Reserved64Only; \
\
/* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \
* struct above. */ \
bool Read(ProcessReader* process_reader, mach_vm_address_t address) { \
return ReadInto(process_reader, address, this); \
} \
static bool ReadArrayInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
size_t count, \
struct_name<Traits>* specific); \
static size_t Size() { return sizeof(struct_name<Traits>); } \
\
/* Translates a struct from the representation used in the remote process \
* into the generic form. */ \
void GenericizeInto(process_types::struct_name* generic, \
size_t* specific_size);
#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \
member_type member_name __VA_ARGS__;
#define PROCESS_TYPE_STRUCT_END(struct_name) \
private: \
/* ReadInto() is as in the generic user-visible struct above. */ \
static bool ReadInto(ProcessReader* process_reader, \
mach_vm_address_t address, \
struct_name<Traits>* specific); \
}; \
} /* namespace internal */ \
} /* namespace process_types */ \
} /* namespace crashpad */
#include "util/mac/process_types/all.proctype"
#undef PROCESS_TYPE_STRUCT_BEGIN
#undef PROCESS_TYPE_STRUCT_MEMBER
#undef PROCESS_TYPE_STRUCT_END
#undef PROCESS_TYPE_STRUCT_DECLARE_INTERNAL
#endif // CRASHPAD_UTIL_MAC_PROCESS_TYPES_H_

View File

@ -0,0 +1,25 @@
// 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.
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types.cc to produce process type struct definitions and
// accessors.
#include "util/mac/process_types/crashreporterclient.proctype"
#include "util/mac/process_types/dyld_images.proctype"
#include "util/mac/process_types/loader.proctype"
#include "util/mac/process_types/nlist.proctype"

View File

@ -0,0 +1,40 @@
// 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.
// The name of this file was chosen based on
// http://llvm.org/svn/llvm-project/llvm/trunk/lib/Support/PrettyStackTrace.cpp.
// The name of the structure it describes was chosen based on that file as well
// as 10.9.2 cups-372.2/cups/backend/usb-darwin.c. That file also provided the
// names and types of the fields in the structure.
//
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types.cc to produce process type struct definitions and
// accessors.
// Client Mach-O images will contain a __DATA,__crash_info section formatted
// according to this structure.
PROCESS_TYPE_STRUCT_BEGIN(crashreporter_annotations_t)
// The only known version is 4.
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, version) // unsigned long
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, message) // char*
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, signature_string) // char*
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, backtrace) // char*
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, message2) // char*
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, thread)
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, dialog_mode) // unsigned int
PROCESS_TYPE_STRUCT_END(crashreporter_annotations_t)

View File

@ -0,0 +1,95 @@
// 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 "util/mac/process_types.h"
#include <string.h>
#include "util/mac/process_types/internal.h"
#include "util/mach/task_memory.h"
namespace crashpad {
namespace process_types {
namespace internal {
template <typename Traits>
bool dyld_all_image_infos<Traits>::ReadInto(
ProcessReader* process_reader,
mach_vm_address_t address,
dyld_all_image_infos<Traits>* specific) {
TaskMemory* task_memory = process_reader->Memory();
if (!task_memory->Read(
address, sizeof(specific->version), &specific->version)) {
return false;
}
mach_vm_size_t size;
if (specific->version >= 14) {
size = sizeof(dyld_all_image_infos<Traits>);
} else if (specific->version >= 13) {
size = offsetof(dyld_all_image_infos<Traits>, reserved);
} else if (specific->version >= 12) {
size = offsetof(dyld_all_image_infos<Traits>, sharedCacheUUID);
} else if (specific->version >= 11) {
size = offsetof(dyld_all_image_infos<Traits>, sharedCacheSlide);
} else if (specific->version >= 10) {
size = offsetof(dyld_all_image_infos<Traits>, errorKind);
} else if (specific->version >= 9) {
size = offsetof(dyld_all_image_infos<Traits>, initialImageCount);
} else if (specific->version >= 8) {
size = offsetof(dyld_all_image_infos<Traits>, dyldAllImageInfosAddress);
} else if (specific->version >= 7) {
size = offsetof(dyld_all_image_infos<Traits>, uuidArrayCount);
} else if (specific->version >= 6) {
size = offsetof(dyld_all_image_infos<Traits>, systemOrderFlag);
} else if (specific->version >= 5) {
size = offsetof(dyld_all_image_infos<Traits>, coreSymbolicationShmPage);
} else if (specific->version >= 3) {
size = offsetof(dyld_all_image_infos<Traits>, dyldVersion);
} else if (specific->version >= 2) {
size = offsetof(dyld_all_image_infos<Traits>, jitInfo);
} else if (specific->version >= 1) {
size = offsetof(dyld_all_image_infos<Traits>, libSystemInitialized);
} else {
size = offsetof(dyld_all_image_infos<Traits>, infoArrayCount);
}
if (!task_memory->Read(address, size, specific)) {
return false;
}
// Zero out the rest of the structure in case anything accesses fields without
// checking the version.
size_t remaining = sizeof(*specific) - size;
if (remaining > 0) {
char* start = reinterpret_cast<char*>(specific) + size;
memset(start, 0, remaining);
}
return true;
}
#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits) \
template bool dyld_all_image_infos<Traits##lp_bits>::ReadInto( \
ProcessReader*, \
mach_vm_address_t, \
dyld_all_image_infos<Traits##lp_bits>*);
#include "util/mac/process_types/flavors.h"
#undef PROCESS_TYPE_FLAVOR_TRAITS
} // namespace internal
} // namespace process_types
} // namespace crashpad

View File

@ -0,0 +1,103 @@
// 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.
// This file corresponds to the systems <mach-o/dyld_images.h>.
//
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types.cc to produce process type struct definitions and
// accessors.
PROCESS_TYPE_STRUCT_BEGIN(dyld_image_info)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, imageLoadAddress) // const mach_header*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, imageFilePath) // const char*
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, imageFileModDate)
PROCESS_TYPE_STRUCT_END(dyld_image_info)
PROCESS_TYPE_STRUCT_BEGIN(dyld_uuid_info)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, imageLoadAddress) // const mach_header*
PROCESS_TYPE_STRUCT_MEMBER(uuid_t, imageUUID)
PROCESS_TYPE_STRUCT_END(dyld_uuid_info)
// dyld_all_image_infos is variable-length. Its length dictated by its |version|
// field which is always present. A custom implementation of the flavored
// ReadSpecificInto function that understands how to map this field to the
// structures actual size is provided in util/mac/process_types/custom.cc. No
// implementation of ReadArrayInto is provided because dyld_all_image_infos
// structs are singletons in a process and are never present in arrays, so the
// functionality is unnecessary.
#if !defined(PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO) && \
!defined(PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY)
PROCESS_TYPE_STRUCT_BEGIN(dyld_all_image_infos)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, version)
// Version 1 (Mac OS X 10.4)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, infoArrayCount)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, infoArray) // const dyld_image_info*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, notification) // function pointer
PROCESS_TYPE_STRUCT_MEMBER(bool, processDetachedFromSharedRegion)
// Version 2 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(bool, libSystemInitialized)
// const mach_header*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldImageLoadAddress)
// Version 3 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, jitInfo) // void*
// Version 5 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldVersion) // const char*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, errorMessage) // const char*
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, terminationFlags)
// Version 6 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(Pointer, coreSymbolicationShmPage) // void*
// Version 7 (Mac OS X 10.6)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, systemOrderFlag)
// Version 8 (Mac 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)
// dyld_all_image_infos*
PROCESS_TYPE_STRUCT_MEMBER(Pointer, dyldAllImageInfosAddress)
// Version 10 (Mac OS X 10.7)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, initialImageCount)
// Version 11 (Mac 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)
PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, sharedCacheSlide)
// Version 13 (Mac 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])
PROCESS_TYPE_STRUCT_END(dyld_all_image_infos)
#endif // ! PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO &&
// ! PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY

View File

@ -0,0 +1,23 @@
// 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.
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types/internal.h to produce process
// type flavor traits class declarations and by util/mac/process_types/custom.cc
// to provide explicit instantiation of flavored implementations.
PROCESS_TYPE_FLAVOR_TRAITS(32)
PROCESS_TYPE_FLAVOR_TRAITS(64)

View File

@ -0,0 +1,36 @@
// 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_UTIL_MAC_PROCESS_TYPES_INTERNAL_H_
#define CRASHPAD_UTIL_MAC_PROCESS_TYPES_INTERNAL_H_
#include "util/mac/process_types.h"
// Declare Traits32 and Traits64, flavor-specific traits classes. These are
// private traits classes not for use outside of process type internals.
// TraitsGeneric is declared in util/mac/process_types.h.
#include "util/mac/process_types/traits.h"
#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits) \
DECLARE_PROCESS_TYPE_TRAITS_CLASS( \
lp_bits, lp_bits, __attribute__((aligned(lp_bits / 8))))
#include "util/mac/process_types/flavors.h"
#undef PROCESS_TYPE_FLAVOR_TRAITS
#undef DECLARE_PROCESS_TYPE_TRAITS_CLASS
#endif // CRASHPAD_UTIL_MAC_PROCESS_TYPES_INTERNAL_H_

View File

@ -0,0 +1,140 @@
// 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.
// This file corresponds to the systems <mach-o/loader.h>.
//
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types.cc to produce process type struct definitions and
// accessors.
PROCESS_TYPE_STRUCT_BEGIN(mach_header) // 64-bit: mach_header_64
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, magic)
// cputype is really cpu_type_t, a typedef for integer_t, itself a typedef for
// int. It is currently reasonable to assume that int is int32_t.
PROCESS_TYPE_STRUCT_MEMBER(int32_t, cputype)
// cpusubtype is really cpu_subtype_t, a typedef for integer_t, itself a
// typedef for int. It is currently reasonable to assume that int is int32_t.
PROCESS_TYPE_STRUCT_MEMBER(int32_t, cpusubtype)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, filetype)
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_END(mach_header)
PROCESS_TYPE_STRUCT_BEGIN(load_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_END(load_command)
PROCESS_TYPE_STRUCT_BEGIN(segment_command) // 64-bit: segment_command_64
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
// This string is not necessarily NUL-terminated.
PROCESS_TYPE_STRUCT_MEMBER(char, segname, [16])
PROCESS_TYPE_STRUCT_MEMBER(ULong, vmaddr)
PROCESS_TYPE_STRUCT_MEMBER(ULong, vmsize)
PROCESS_TYPE_STRUCT_MEMBER(ULong, fileoff)
PROCESS_TYPE_STRUCT_MEMBER(ULong, filesize)
PROCESS_TYPE_STRUCT_MEMBER(vm_prot_t, maxprot)
PROCESS_TYPE_STRUCT_MEMBER(vm_prot_t, initprot)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nsects)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, flags)
PROCESS_TYPE_STRUCT_END(segment_command)
PROCESS_TYPE_STRUCT_BEGIN(dylib_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
// The following come from the dylib struct member of dylib_command.
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, dylib_name) // lc_str
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, dylib_timestamp)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, dylib_current_version)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, dylib_compatibility_version)
PROCESS_TYPE_STRUCT_END(dylib_command)
PROCESS_TYPE_STRUCT_BEGIN(dylinker_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, name) // lc_str
PROCESS_TYPE_STRUCT_END(dylinker_command)
PROCESS_TYPE_STRUCT_BEGIN(symtab_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, symoff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nsyms)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, stroff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, strsize)
PROCESS_TYPE_STRUCT_END(symtab_command)
PROCESS_TYPE_STRUCT_BEGIN(dysymtab_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, ilocalsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nlocalsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, iextdefsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nextdefsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, iundefsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nundefsym)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, tocoff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, ntoc)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, modtaboff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nmodtab)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, extrefsymoff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nextrefsyms)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, indirectsymoff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nindirectsyms)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, extreloff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nextrel)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, locreloff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nlocrel)
PROCESS_TYPE_STRUCT_END(dysymtab_command)
PROCESS_TYPE_STRUCT_BEGIN(uuid_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_MEMBER(uint8_t, uuid, [16])
PROCESS_TYPE_STRUCT_END(uuid_command)
PROCESS_TYPE_STRUCT_BEGIN(source_version_command)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmd)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, cmdsize)
PROCESS_TYPE_STRUCT_MEMBER(uint64_t, version)
PROCESS_TYPE_STRUCT_END(source_version_command)
PROCESS_TYPE_STRUCT_BEGIN(section) // 64-bit: section_64
// These strings are not necessarily NUL-terminated.
PROCESS_TYPE_STRUCT_MEMBER(char, sectname, [16])
PROCESS_TYPE_STRUCT_MEMBER(char, segname, [16])
PROCESS_TYPE_STRUCT_MEMBER(ULong, addr)
PROCESS_TYPE_STRUCT_MEMBER(ULong, size)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, offset)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, align)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, reloff)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, nreloc)
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_END(section)

View File

@ -0,0 +1,30 @@
// 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.
// This file corresponds to the systems <mach-o/nlist.h>.
//
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types.cc to produce process type struct definitions and
// accessors.
PROCESS_TYPE_STRUCT_BEGIN(nlist)
PROCESS_TYPE_STRUCT_MEMBER(uint32_t, n_strx) // n_un.n_strx
PROCESS_TYPE_STRUCT_MEMBER(uint8_t, n_type)
PROCESS_TYPE_STRUCT_MEMBER(uint8_t, n_sect)
PROCESS_TYPE_STRUCT_MEMBER(uint16_t, n_desc) // 32-bit: int16_t
PROCESS_TYPE_STRUCT_MEMBER(ULong, n_value)
PROCESS_TYPE_STRUCT_END(nlist)

View File

@ -0,0 +1,42 @@
// 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.
// This file is intended to be included multiple times in the same translation
// unit, so #include guards are intentionally absent.
//
// This file is included by util/mac/process_types.h and
// util/mac/process_types/internal.h to produce traits class definitions.
// Things that #include this file should #undef
// 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
// __VA_ARGS__, which is intended to set the alignment of the 64-bit types, is
// not used for that typedef.
#define DECLARE_PROCESS_TYPE_TRAITS_CLASS(traits_name, lp_bits, ...) \
namespace crashpad { \
namespace process_types { \
namespace internal { \
struct Traits##traits_name { \
typedef int##lp_bits##_t Long __VA_ARGS__; \
typedef uint##lp_bits##_t ULong __VA_ARGS__; \
typedef uint##lp_bits##_t Pointer __VA_ARGS__; \
typedef int##lp_bits##_t IntPtr __VA_ARGS__; \
typedef uint##lp_bits##_t UIntPtr __VA_ARGS__; \
typedef Reserved64Only##lp_bits Reserved64Only; \
}; \
} \
} \
}

View File

@ -0,0 +1,267 @@
// 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 "util/mac/process_types.h"
#include <AvailabilityMacros.h>
#include <mach/mach.h>
#include <string.h>
#include <vector>
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
#include "util/mac/mac_util.h"
extern "C" {
const struct dyld_all_image_infos* _dyld_get_all_image_infos();
} // extern "C"
namespace {
using namespace crashpad;
#define TEST_STRING(process_reader, self_view, proctype_view, field) \
do { \
if (self_view->field) { \
std::string proctype_string; \
ASSERT_TRUE(process_reader.Memory()->ReadCString(proctype_view.field, \
&proctype_string)); \
EXPECT_EQ(self_view->field, proctype_string); \
} \
} while (false)
TEST(ProcessTypes, DyldImagesSelf) {
// Get the in-process view of dyld_all_image_infos, and check it for sanity.
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) {
EXPECT_GE(self_image_infos->version, 13u);
} else if (mac_os_x_minor_version >= 7) {
EXPECT_GE(self_image_infos->version, 8u);
} else if (mac_os_x_minor_version >= 6) {
EXPECT_GE(self_image_infos->version, 2u);
} else {
EXPECT_GE(self_image_infos->version, 1u);
}
EXPECT_GT(self_image_infos->infoArrayCount, 1u);
if (self_image_infos->version >= 2) {
EXPECT_TRUE(self_image_infos->libSystemInitialized);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (self_image_infos->version >= 9) {
EXPECT_EQ(self_image_infos, self_image_infos->dyldAllImageInfosAddress);
}
#endif
// Get the out-of-process view of dyld_all_image_infos, and work with it
// through the process_types interface.
task_dyld_info_data_t dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
kern_return_t kr = task_info(mach_task_self(),
TASK_DYLD_INFO,
reinterpret_cast<task_info_t>(&dyld_info),
&count);
ASSERT_EQ(KERN_SUCCESS, kr);
EXPECT_EQ(reinterpret_cast<mach_vm_address_t>(self_image_infos),
dyld_info.all_image_info_addr);
EXPECT_GT(dyld_info.all_image_info_size, 1u);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
#if !defined(ARCH_CPU_64_BITS)
EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_32, dyld_info.all_image_info_format);
#else
EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_64, dyld_info.all_image_info_format);
#endif
#endif
ProcessReader process_reader;
ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
process_types::dyld_all_image_infos proctype_image_infos;
ASSERT_TRUE(proctype_image_infos.Read(&process_reader,
dyld_info.all_image_info_addr));
ASSERT_EQ(self_image_infos->version, proctype_image_infos.version);
if (proctype_image_infos.version >= 1) {
EXPECT_EQ(self_image_infos->infoArrayCount,
proctype_image_infos.infoArrayCount);
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->infoArray),
proctype_image_infos.infoArray);
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->notification),
proctype_image_infos.notification);
EXPECT_EQ(self_image_infos->processDetachedFromSharedRegion,
proctype_image_infos.processDetachedFromSharedRegion);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
if (proctype_image_infos.version >= 2) {
EXPECT_EQ(self_image_infos->libSystemInitialized,
proctype_image_infos.libSystemInitialized);
EXPECT_EQ(
reinterpret_cast<uint64_t>(self_image_infos->dyldImageLoadAddress),
proctype_image_infos.dyldImageLoadAddress);
}
if (proctype_image_infos.version >= 3) {
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->jitInfo),
proctype_image_infos.jitInfo);
}
if (proctype_image_infos.version >= 5) {
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->dyldVersion),
proctype_image_infos.dyldVersion);
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorMessage),
proctype_image_infos.errorMessage);
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->terminationFlags),
proctype_image_infos.terminationFlags);
TEST_STRING(
process_reader, self_image_infos, proctype_image_infos, dyldVersion);
TEST_STRING(
process_reader, self_image_infos, proctype_image_infos, errorMessage);
}
if (proctype_image_infos.version >= 6) {
EXPECT_EQ(
reinterpret_cast<uint64_t>(self_image_infos->coreSymbolicationShmPage),
proctype_image_infos.coreSymbolicationShmPage);
}
if (proctype_image_infos.version >= 7) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->systemOrderFlag),
proctype_image_infos.systemOrderFlag);
}
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (proctype_image_infos.version >= 8) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->uuidArrayCount),
proctype_image_infos.uuidArrayCount);
}
if (proctype_image_infos.version >= 9) {
EXPECT_EQ(
reinterpret_cast<uint64_t>(self_image_infos->dyldAllImageInfosAddress),
proctype_image_infos.dyldAllImageInfosAddress);
}
if (proctype_image_infos.version >= 10) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->initialImageCount),
proctype_image_infos.initialImageCount);
}
if (proctype_image_infos.version >= 11) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->errorKind),
proctype_image_infos.errorKind);
EXPECT_EQ(
reinterpret_cast<uint64_t>(self_image_infos->errorClientOfDylibPath),
proctype_image_infos.errorClientOfDylibPath);
EXPECT_EQ(
reinterpret_cast<uint64_t>(self_image_infos->errorTargetDylibPath),
proctype_image_infos.errorTargetDylibPath);
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorSymbol),
proctype_image_infos.errorSymbol);
TEST_STRING(process_reader,
self_image_infos,
proctype_image_infos,
errorClientOfDylibPath);
TEST_STRING(process_reader,
self_image_infos,
proctype_image_infos,
errorTargetDylibPath);
TEST_STRING(
process_reader, self_image_infos, proctype_image_infos, errorSymbol);
}
if (proctype_image_infos.version >= 12) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->sharedCacheSlide),
proctype_image_infos.sharedCacheSlide);
}
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
if (proctype_image_infos.version >= 13) {
EXPECT_EQ(0,
memcmp(self_image_infos->sharedCacheUUID,
proctype_image_infos.sharedCacheUUID,
sizeof(self_image_infos->sharedCacheUUID)));
}
if (proctype_image_infos.version >= 14) {
for (size_t index = 0; index < arraysize(self_image_infos->reserved);
++index) {
EXPECT_EQ(static_cast<uint64_t>(self_image_infos->reserved[index]),
proctype_image_infos.reserved[index])
<< "index " << index;
}
}
#endif
if (proctype_image_infos.version >= 1) {
std::vector<process_types::dyld_image_info> proctype_image_info_vector(
proctype_image_infos.infoArrayCount);
ASSERT_TRUE(process_types::dyld_image_info::ReadArrayInto(
&process_reader,
proctype_image_infos.infoArray,
proctype_image_info_vector.size(),
&proctype_image_info_vector[0]));
for (size_t index = 0; index < proctype_image_infos.infoArrayCount;
++index) {
const dyld_image_info* self_image_info =
&self_image_infos->infoArray[index];
const process_types::dyld_image_info& proctype_image_info =
proctype_image_info_vector[index];
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageLoadAddress),
proctype_image_info.imageLoadAddress)
<< "index " << index;
EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageFilePath),
proctype_image_info.imageFilePath)
<< "index " << index;
EXPECT_EQ(static_cast<uint64_t>(self_image_info->imageFileModDate),
proctype_image_info.imageFileModDate)
<< "index " << index;
TEST_STRING(
process_reader, self_image_info, proctype_image_info, imageFilePath);
}
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (proctype_image_infos.version >= 8) {
std::vector<process_types::dyld_uuid_info> proctype_uuid_info_vector(
proctype_image_infos.uuidArrayCount);
ASSERT_TRUE(process_types::dyld_uuid_info::ReadArrayInto(
&process_reader,
proctype_image_infos.uuidArray,
proctype_uuid_info_vector.size(),
&proctype_uuid_info_vector[0]));
for (size_t index = 0; index < proctype_image_infos.uuidArrayCount;
++index) {
const dyld_uuid_info* self_uuid_info =
&self_image_infos->uuidArray[index];
const process_types::dyld_uuid_info& proctype_uuid_info =
proctype_uuid_info_vector[index];
EXPECT_EQ(reinterpret_cast<uint64_t>(self_uuid_info->imageLoadAddress),
proctype_uuid_info.imageLoadAddress)
<< "index " << index;
EXPECT_EQ(0,
memcmp(self_uuid_info->imageUUID,
proctype_uuid_info.imageUUID,
sizeof(self_uuid_info->imageUUID)))
<< "index " << index;
}
}
#endif
}
} // namespace

View File

@ -40,6 +40,17 @@
'mac/service_management.h',
'mac/process_reader.cc',
'mac/process_reader.h',
'mac/process_types.cc',
'mac/process_types.h',
'mac/process_types/all.proctype',
'mac/process_types/crashreporterclient.proctype',
'mac/process_types/custom.cc',
'mac/process_types/dyld_images.proctype',
'mac/process_types/flavors.h',
'mac/process_types/internal.h',
'mac/process_types/loader.proctype',
'mac/process_types/nlist.proctype',
'mac/process_types/traits.h',
'mach/bootstrap.cc',
'mach/bootstrap.h',
'mach/task_memory.cc',
@ -108,6 +119,7 @@
'mac/launchd_test.mm',
'mac/mac_util_test.mm',
'mac/process_reader_test.cc',
'mac/process_types_test.cc',
'mac/service_management_test.mm',
'mach/bootstrap_test.cc',
'mach/task_memory_test.cc',