| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 #include "util/mac/process_types.h" | |
| 16 | |
| 17 #include <string.h> | |
| 18 #include <uuid/uuid.h> | |
| 19 | |
| 20 #include "base/memory/scoped_ptr.h" | |
| 21 #include "util/mac/process_types/internal.h" | |
| 22 #include "util/mach/task_memory.h" | |
| 23 | |
| 24 namespace crashpad { | |
| 25 namespace { | |
| 26 | |
| 27 // Assign() is used by each flavor's ReadInto implementation to copy data from a | |
| 28 // specific struct to a generic struct. For fundamental types, the assignment | |
| 29 // operator suffices. For other types such as arrays, an explicit Assign | |
| 30 // specialization is needed, typically performing a copy. | |
| 31 | |
| 32 template <typename DestinationType, typename SourceType> | |
| 33 inline void Assign(DestinationType* destination, const SourceType& source) { | |
| 34 *destination = source; | |
| 35 } | |
| 36 | |
| 37 template <> | |
| 38 inline void Assign<process_types::internal::Reserved64Only64, | |
| 39 process_types::internal::Reserved64Only32>( | |
| 40 process_types::internal::Reserved64Only64* destination, | |
| 41 const process_types::internal::Reserved64Only32& source) { | |
| 42 // Reserved64Only32 carries no data. | |
| 43 *destination = 0; | |
| 44 } | |
| 45 | |
| 46 typedef char CharArray16[16]; | |
| 47 template <> | |
| 48 inline void Assign<CharArray16, CharArray16>(CharArray16* destination, | |
| 49 const CharArray16& source) { | |
| 50 memcpy(destination, &source, sizeof(source)); | |
| 51 } | |
| 52 | |
| 53 typedef uint64_t UInt64Array16[16]; | |
| 54 template <> | |
| 55 inline void Assign<UInt64Array16, UInt64Array16>(UInt64Array16* destination, | |
| 56 const UInt64Array16& source) { | |
| 57 memcpy(destination, &source, sizeof(source)); | |
| 58 } | |
| 59 | |
| 60 typedef uint32_t UInt32Array16[16]; | |
| 61 template <> | |
| 62 inline void Assign<UInt64Array16, UInt32Array16>(UInt64Array16* destination, | |
| 63 const UInt32Array16& source) { | |
| 64 for (size_t index = 0; index < arraysize(source); ++index) { | |
| 65 (*destination)[index] = source[index]; | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 template <> | |
| 70 inline void Assign<uuid_t, uuid_t>(uuid_t* destination, const uuid_t& source) { | |
| 71 // uuid_t is a typedef for unsigned char[16]. | |
| 72 memcpy(destination, &source, sizeof(source)); | |
| 73 } | |
| 74 | |
| 75 } // namespace | |
| 76 } // namespace crashpad | |
| 77 | |
| 78 // Implement the generic crashpad::process_types::struct_name ReadInto(), which | |
| 79 // delegates to the templatized ReadIntoInternal(), which reads the specific | |
| 80 // struct type from the remote process and genericizes it. Also implement | |
| 81 // crashpad::process_types::internal::struct_name<> GenericizeInto(), which | |
| 82 // operates on each member in the struct. | |
| 83 #define PROCESS_TYPE_STRUCT_IMPLEMENT 1 | |
| 84 | |
| 85 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | |
| 86 namespace crashpad { \ | |
| 87 namespace process_types { \ | |
| 88 \ | |
| 89 size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ | |
| 90 if (!process_reader->Is64Bit()) { \ | |
| 91 return internal::struct_name<internal::Traits32>::Size(); \ | |
| 92 } else { \ | |
| 93 return internal::struct_name<internal::Traits64>::Size(); \ | |
| 94 } \ | |
| 95 } \ | |
| 96 \ | |
| 97 bool struct_name::ReadInto(ProcessReader* process_reader, \ | |
| 98 mach_vm_address_t address, \ | |
| 99 struct_name* generic) { \ | |
| 100 if (!process_reader->Is64Bit()) { \ | |
| 101 return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \ | |
| 102 process_reader, address, generic); \ | |
| 103 } else { \ | |
| 104 return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \ | |
| 105 process_reader, address, generic); \ | |
| 106 } \ | |
| 107 } \ | |
| 108 \ | |
| 109 template <typename T> \ | |
| 110 bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ | |
| 111 mach_vm_address_t address, \ | |
| 112 struct_name* generic) { \ | |
| 113 T specific; \ | |
| 114 if (!specific.Read(process_reader, address)) { \ | |
| 115 return false; \ | |
| 116 } \ | |
| 117 specific.GenericizeInto(generic, &generic->size_); \ | |
| 118 return true; \ | |
| 119 } \ | |
| 120 \ | |
| 121 namespace internal { \ | |
| 122 \ | |
| 123 template <typename Traits> \ | |
| 124 void struct_name<Traits>::GenericizeInto( \ | |
| 125 process_types::struct_name* generic, \ | |
| 126 size_t* specific_size) { \ | |
| 127 *specific_size = Size(); | |
| 128 | |
| 129 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ | |
| 130 Assign(&generic->member_name, member_name); | |
| 131 | |
| 132 #define PROCESS_TYPE_STRUCT_END(struct_name) \ | |
| 133 } \ | |
| 134 } /* namespace internal */ \ | |
| 135 } /* namespace process_types */ \ | |
| 136 } /* namespace crashpad */ | |
| 137 | |
| 138 #include "util/mac/process_types/all.proctype" | |
| 139 | |
| 140 #undef PROCESS_TYPE_STRUCT_BEGIN | |
| 141 #undef PROCESS_TYPE_STRUCT_MEMBER | |
| 142 #undef PROCESS_TYPE_STRUCT_END | |
| 143 #undef PROCESS_TYPE_STRUCT_IMPLEMENT | |
| 144 | |
| 145 // Implement the specific crashpad::process_types::internal::struct_name<> | |
| 146 // ReadInto(). The default implementation simply reads the struct from the | |
| 147 // remote process. This is separated from other method implementations because | |
| 148 // some types may wish to provide custom readers. This can be done by guarding | |
| 149 // such types’ proctype definitions against this macro and providing custom | |
| 150 // implementations in util/mac/process_types/custom.cc. | |
| 151 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 | |
| 152 | |
| 153 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | |
| 154 namespace crashpad { \ | |
| 155 namespace process_types { \ | |
| 156 namespace internal { \ | |
| 157 \ | |
| 158 template <typename Traits> \ | |
| 159 bool struct_name<Traits>::ReadInto(ProcessReader* process_reader, \ | |
| 160 mach_vm_address_t address, \ | |
| 161 struct_name<Traits>* specific) { \ | |
| 162 return process_reader->Memory()->Read( \ | |
| 163 address, sizeof(*specific), specific); \ | |
| 164 } \ | |
| 165 } /* namespace internal */ \ | |
| 166 } /* namespace process_types */ \ | |
| 167 } /* namespace crashpad */ | |
| 168 | |
| 169 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) | |
| 170 | |
| 171 #define PROCESS_TYPE_STRUCT_END(struct_name) | |
| 172 | |
| 173 #include "util/mac/process_types/all.proctype" | |
| 174 | |
| 175 #undef PROCESS_TYPE_STRUCT_BEGIN | |
| 176 #undef PROCESS_TYPE_STRUCT_MEMBER | |
| 177 #undef PROCESS_TYPE_STRUCT_END | |
| 178 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO | |
| 179 | |
| 180 // Implement the array operations. These are separated from other method | |
| 181 // implementations because some types are variable-length and are never stored | |
| 182 // as direct-access arrays. It would be incorrect to provide reader | |
| 183 // implementations for such types. Types that wish to suppress array operations | |
| 184 // can do so by guarding their proctype definitions against this macro. | |
| 185 #define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1 | |
| 186 | |
| 187 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | |
| 188 namespace crashpad { \ | |
| 189 namespace process_types { \ | |
| 190 namespace internal { \ | |
| 191 \ | |
| 192 template <typename Traits> \ | |
| 193 bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ | |
| 194 mach_vm_address_t address, \ | |
| 195 size_t count, \ | |
| 196 struct_name<Traits>* specific) { \ | |
| 197 return process_reader->Memory()->Read( \ | |
| 198 address, sizeof(struct_name<Traits> [count]), specific); \ | |
| 199 } \ | |
| 200 } /* namespace internal */ \ | |
| 201 \ | |
| 202 bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ | |
| 203 mach_vm_address_t address, \ | |
| 204 size_t count, \ | |
| 205 struct_name* generic) { \ | |
| 206 if (!process_reader->Is64Bit()) { \ | |
| 207 return ReadArrayIntoInternal< \ | |
| 208 internal::struct_name<internal::Traits32> >( \ | |
| 209 process_reader, address, count, generic); \ | |
| 210 } else { \ | |
| 211 return ReadArrayIntoInternal< \ | |
| 212 internal::struct_name<internal::Traits64> >( \ | |
| 213 process_reader, address, count, generic); \ | |
| 214 } \ | |
| 215 return true; \ | |
| 216 } \ | |
| 217 \ | |
| 218 template <typename T> \ | |
| 219 bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader, \ | |
| 220 mach_vm_address_t address, \ | |
| 221 size_t count, \ | |
| 222 struct_name* generic) { \ | |
| 223 scoped_ptr<T[]> specific(new T[count]); \ | |
| 224 if (!T::ReadArrayInto(process_reader, address, count, &specific[0])) { \ | |
| 225 return false; \ | |
| 226 } \ | |
| 227 for (size_t index = 0; index < count; ++index) { \ | |
| 228 specific[index].GenericizeInto(&generic[index], &generic[index].size_); \ | |
| 229 } \ | |
| 230 return true; \ | |
| 231 } \ | |
| 232 } /* namespace process_types */ \ | |
| 233 } /* namespace crashpad */ | |
| 234 | |
| 235 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) | |
| 236 | |
| 237 #define PROCESS_TYPE_STRUCT_END(struct_name) | |
| 238 | |
| 239 #include "util/mac/process_types/all.proctype" | |
| 240 | |
| 241 #undef PROCESS_TYPE_STRUCT_BEGIN | |
| 242 #undef PROCESS_TYPE_STRUCT_MEMBER | |
| 243 #undef PROCESS_TYPE_STRUCT_END | |
| 244 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY | |
| OLD | NEW |