Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Unified Diff: util/mac/process_types.cc

Issue 501203002: Add ProcessTypes, its test, and many proctype definition files (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « util/mac/process_types.h ('k') | util/mac/process_types/all.proctype » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: util/mac/process_types.cc
diff --git a/util/mac/process_types.cc b/util/mac/process_types.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e7e858bf822756427eafd28eafbeff609275bf14
--- /dev/null
+++ b/util/mac/process_types.cc
@@ -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
« no previous file with comments | « util/mac/process_types.h ('k') | util/mac/process_types/all.proctype » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698