| Index: third_party/crashpad/crashpad/snapshot/mac/process_types.cc
|
| diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0fc14f0e0b5e971b643bd98917a88688ae0bb028
|
| --- /dev/null
|
| +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
|
| @@ -0,0 +1,304 @@
|
| +// 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 "snapshot/mac/process_types.h"
|
| +
|
| +#include <string.h>
|
| +#include <uuid/uuid.h>
|
| +
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "snapshot/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;
|
| +}
|
| +
|
| +using CharArray16 = char[16];
|
| +template <>
|
| +inline void Assign<CharArray16, CharArray16>(CharArray16* destination,
|
| + const CharArray16& source) {
|
| + memcpy(destination, &source, sizeof(source));
|
| +}
|
| +
|
| +using UInt64Array16 = uint64_t[16];
|
| +template <>
|
| +inline void Assign<UInt64Array16, UInt64Array16>(UInt64Array16* destination,
|
| + const UInt64Array16& source) {
|
| + memcpy(destination, &source, sizeof(source));
|
| +}
|
| +
|
| +using UInt32Array16 = uint32_t[16];
|
| +template <>
|
| +inline void Assign<UInt64Array16, UInt32Array16>(UInt64Array16* destination,
|
| + const UInt32Array16& source) {
|
| + for (size_t index = 0; index < arraysize(source); ++index) {
|
| + (*destination)[index] = source[index];
|
| + }
|
| +}
|
| +
|
| +template <>
|
| +inline void Assign<uuid_t, uuid_t>(uuid_t* destination, const uuid_t& source) {
|
| + // uuid_t is a type alias for unsigned char[16].
|
| + memcpy(destination, &source, sizeof(source));
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace crashpad
|
| +
|
| +// 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 { \
|
| + \
|
| + /* static */ \
|
| + 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(); \
|
| + } \
|
| + } \
|
| + \
|
| + /* static */ \
|
| + 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); \
|
| + } \
|
| + } \
|
| + \
|
| + /* static */ \
|
| + 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_VERSIONED(struct_name, version_field)
|
| +
|
| +#define PROCESS_TYPE_STRUCT_END(struct_name) \
|
| + } \
|
| + } /* namespace internal */ \
|
| + } /* namespace process_types */ \
|
| + } /* namespace crashpad */
|
| +
|
| +#include "snapshot/mac/process_types/all.proctype"
|
| +
|
| +#undef PROCESS_TYPE_STRUCT_BEGIN
|
| +#undef PROCESS_TYPE_STRUCT_MEMBER
|
| +#undef PROCESS_TYPE_STRUCT_VERSIONED
|
| +#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 snapshot/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 { \
|
| + \
|
| + /* static */ \
|
| + 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_VERSIONED(struct_name, version_field)
|
| +
|
| +#define PROCESS_TYPE_STRUCT_END(struct_name)
|
| +
|
| +#include "snapshot/mac/process_types/all.proctype"
|
| +
|
| +#undef PROCESS_TYPE_STRUCT_BEGIN
|
| +#undef PROCESS_TYPE_STRUCT_MEMBER
|
| +#undef PROCESS_TYPE_STRUCT_VERSIONED
|
| +#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 { \
|
| + \
|
| + /* static */ \
|
| + 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 */ \
|
| + \
|
| + /* static */ \
|
| + 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; \
|
| + } \
|
| + \
|
| + /* static */ \
|
| + 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_VERSIONED(struct_name, version_field)
|
| +
|
| +#define PROCESS_TYPE_STRUCT_END(struct_name)
|
| +
|
| +#include "snapshot/mac/process_types/all.proctype"
|
| +
|
| +#undef PROCESS_TYPE_STRUCT_BEGIN
|
| +#undef PROCESS_TYPE_STRUCT_MEMBER
|
| +#undef PROCESS_TYPE_STRUCT_VERSIONED
|
| +#undef PROCESS_TYPE_STRUCT_END
|
| +#undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY
|
| +
|
| +// Implement the generic crashpad::process_types::struct_name
|
| +// ExpectedSizeForVersion(), which delegates to the templatized
|
| +// ExpectedSizeForVersion(), which returns the expected size of a versioned
|
| +// structure given a version parameter. This is only implemented for structures
|
| +// that use PROCESS_TYPE_STRUCT_VERSIONED(), and implementations of the internal
|
| +// templatized functions must be provided in
|
| +// snapshot/mac/process_types/custom.cc.
|
| +#define PROCESS_TYPE_STRUCT_IMPLEMENT_VERSIONED 1
|
| +
|
| +#define PROCESS_TYPE_STRUCT_BEGIN(struct_name)
|
| +
|
| +#define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)
|
| +
|
| +#define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \
|
| + namespace crashpad { \
|
| + namespace process_types { \
|
| + \
|
| + /* static */ \
|
| + size_t struct_name::ExpectedSizeForVersion( \
|
| + ProcessReader* process_reader, \
|
| + decltype(struct_name::version_field) version) { \
|
| + if (!process_reader->Is64Bit()) { \
|
| + return internal::struct_name< \
|
| + internal::Traits32>::ExpectedSizeForVersion(version); \
|
| + } else { \
|
| + return internal::struct_name< \
|
| + internal::Traits64>::ExpectedSizeForVersion(version); \
|
| + } \
|
| + } \
|
| + \
|
| + } /* namespace process_types */ \
|
| + } /* namespace crashpad */
|
| +
|
| +#define PROCESS_TYPE_STRUCT_END(struct_name)
|
| +
|
| +#include "snapshot/mac/process_types/all.proctype"
|
| +
|
| +#undef PROCESS_TYPE_STRUCT_BEGIN
|
| +#undef PROCESS_TYPE_STRUCT_MEMBER
|
| +#undef PROCESS_TYPE_STRUCT_VERSIONED
|
| +#undef PROCESS_TYPE_STRUCT_END
|
| +#undef PROCESS_TYPE_STRUCT_IMPLEMENT_VERSIONED
|
|
|