mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
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:
parent
0cc86a24f9
commit
30589d87a9
244
util/mac/process_types.cc
Normal file
244
util/mac/process_types.cc
Normal 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
183
util/mac/process_types.h
Normal 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_
|
25
util/mac/process_types/all.proctype
Normal file
25
util/mac/process_types/all.proctype
Normal 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"
|
40
util/mac/process_types/crashreporterclient.proctype
Normal file
40
util/mac/process_types/crashreporterclient.proctype
Normal 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)
|
95
util/mac/process_types/custom.cc
Normal file
95
util/mac/process_types/custom.cc
Normal 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
|
103
util/mac/process_types/dyld_images.proctype
Normal file
103
util/mac/process_types/dyld_images.proctype
Normal 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 system’s <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
|
||||
// structure’s 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
|
23
util/mac/process_types/flavors.h
Normal file
23
util/mac/process_types/flavors.h
Normal 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)
|
36
util/mac/process_types/internal.h
Normal file
36
util/mac/process_types/internal.h
Normal 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_
|
140
util/mac/process_types/loader.proctype
Normal file
140
util/mac/process_types/loader.proctype
Normal 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 system’s <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)
|
30
util/mac/process_types/nlist.proctype
Normal file
30
util/mac/process_types/nlist.proctype
Normal 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 system’s <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)
|
42
util/mac/process_types/traits.h
Normal file
42
util/mac/process_types/traits.h
Normal 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; \
|
||||
}; \
|
||||
} \
|
||||
} \
|
||||
}
|
267
util/mac/process_types_test.cc
Normal file
267
util/mac/process_types_test.cc
Normal 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
|
@ -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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user