| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "snapshot/mac/process_types.h" | 15 #include "snapshot/mac/process_types.h" |
| 16 | 16 |
| 17 #include <string.h> | 17 #include <string.h> |
| 18 #include <uuid/uuid.h> | 18 #include <uuid/uuid.h> |
| 19 | 19 |
| 20 #include "base/logging.h" | |
| 21 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
| 22 #include "snapshot/mac/process_types/internal.h" | 21 #include "snapshot/mac/process_types/internal.h" |
| 23 #include "util/mach/task_memory.h" | 22 #include "util/mach/task_memory.h" |
| 24 | 23 |
| 25 namespace crashpad { | 24 namespace crashpad { |
| 26 namespace { | 25 namespace { |
| 27 | 26 |
| 28 // Assign() is used by each flavor's ReadInto implementation to copy data from a | 27 // Assign() is used by each flavor's ReadInto implementation to copy data from a |
| 29 // specific struct to a generic struct. For fundamental types, the assignment | 28 // specific struct to a generic struct. For fundamental types, the assignment |
| 30 // operator suffices. For other types such as arrays, an explicit Assign | 29 // operator suffices. For other types such as arrays, an explicit Assign |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 } // namespace | 75 } // namespace |
| 77 } // namespace crashpad | 76 } // namespace crashpad |
| 78 | 77 |
| 79 // Implement the generic crashpad::process_types::struct_name ReadInto(), which | 78 // Implement the generic crashpad::process_types::struct_name ReadInto(), which |
| 80 // delegates to the templatized ReadIntoInternal(), which reads the specific | 79 // delegates to the templatized ReadIntoInternal(), which reads the specific |
| 81 // struct type from the remote process and genericizes it. Also implement | 80 // struct type from the remote process and genericizes it. Also implement |
| 82 // crashpad::process_types::internal::struct_name<> GenericizeInto(), which | 81 // crashpad::process_types::internal::struct_name<> GenericizeInto(), which |
| 83 // operates on each member in the struct. | 82 // operates on each member in the struct. |
| 84 #define PROCESS_TYPE_STRUCT_IMPLEMENT 1 | 83 #define PROCESS_TYPE_STRUCT_IMPLEMENT 1 |
| 85 | 84 |
| 86 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | 85 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ |
| 87 namespace crashpad { \ | 86 namespace crashpad { \ |
| 88 namespace process_types { \ | 87 namespace process_types { \ |
| 89 \ | 88 \ |
| 90 /* static */ \ | 89 /* static */ \ |
| 91 size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ | 90 size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ |
| 92 if (!process_reader->Is64Bit()) { \ | 91 if (!process_reader->Is64Bit()) { \ |
| 93 return internal::struct_name<internal::Traits32>::Size(); \ | 92 return internal::struct_name<internal::Traits32>::Size(); \ |
| 94 } else { \ | 93 } else { \ |
| 95 return internal::struct_name<internal::Traits64>::Size(); \ | 94 return internal::struct_name<internal::Traits64>::Size(); \ |
| 96 } \ | 95 } \ |
| 97 } \ | 96 } \ |
| 98 \ | 97 \ |
| 99 /* static */ \ | 98 /* static */ \ |
| 100 size_t struct_name::ExpectedSizeForVersion(ProcessReader* process_reader, \ | 99 bool struct_name::ReadInto(ProcessReader* process_reader, \ |
| 101 uint64_t version) { \ | 100 mach_vm_address_t address, \ |
| 102 if (!process_reader->Is64Bit()) { \ | 101 struct_name* generic) { \ |
| 103 return internal::struct_name< \ | 102 if (!process_reader->Is64Bit()) { \ |
| 104 internal::Traits32>::ExpectedSizeForVersion(version); \ | 103 return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \ |
| 105 } else { \ | 104 process_reader, address, generic); \ |
| 106 return internal::struct_name< \ | 105 } else { \ |
| 107 internal::Traits64>::ExpectedSizeForVersion(version); \ | 106 return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \ |
| 108 } \ | 107 process_reader, address, generic); \ |
| 109 } \ | 108 } \ |
| 110 \ | 109 } \ |
| 111 /* static */ \ | 110 \ |
| 112 bool struct_name::ReadInto(ProcessReader* process_reader, \ | 111 /* static */ \ |
| 113 mach_vm_address_t address, \ | 112 template <typename T> \ |
| 114 struct_name* generic) { \ | 113 bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ |
| 115 if (!process_reader->Is64Bit()) { \ | 114 mach_vm_address_t address, \ |
| 116 return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \ | 115 struct_name* generic) { \ |
| 117 process_reader, address, generic); \ | 116 T specific; \ |
| 118 } else { \ | 117 if (!specific.Read(process_reader, address)) { \ |
| 119 return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \ | 118 return false; \ |
| 120 process_reader, address, generic); \ | 119 } \ |
| 121 } \ | 120 specific.GenericizeInto(generic, &generic->size_); \ |
| 122 } \ | 121 return true; \ |
| 123 \ | 122 } \ |
| 124 /* static */ \ | 123 \ |
| 125 template <typename T> \ | 124 namespace internal { \ |
| 126 bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ | 125 \ |
| 127 mach_vm_address_t address, \ | 126 template <typename Traits> \ |
| 128 struct_name* generic) { \ | 127 void struct_name<Traits>::GenericizeInto( \ |
| 129 T specific; \ | 128 process_types::struct_name* generic, \ |
| 130 if (!specific.Read(process_reader, address)) { \ | 129 size_t* specific_size) { \ |
| 131 return false; \ | |
| 132 } \ | |
| 133 specific.GenericizeInto(generic, &generic->size_); \ | |
| 134 return true; \ | |
| 135 } \ | |
| 136 \ | |
| 137 namespace internal { \ | |
| 138 \ | |
| 139 template <typename Traits> \ | |
| 140 void struct_name<Traits>::GenericizeInto( \ | |
| 141 process_types::struct_name* generic, \ | |
| 142 size_t* specific_size) { \ | |
| 143 *specific_size = Size(); | 130 *specific_size = Size(); |
| 144 | 131 |
| 145 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ | 132 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ |
| 146 Assign(&generic->member_name, member_name); | 133 Assign(&generic->member_name, member_name); |
| 147 | 134 |
| 135 #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) |
| 136 |
| 148 #define PROCESS_TYPE_STRUCT_END(struct_name) \ | 137 #define PROCESS_TYPE_STRUCT_END(struct_name) \ |
| 149 } \ | 138 } \ |
| 150 } /* namespace internal */ \ | 139 } /* namespace internal */ \ |
| 151 } /* namespace process_types */ \ | 140 } /* namespace process_types */ \ |
| 152 } /* namespace crashpad */ | 141 } /* namespace crashpad */ |
| 153 | 142 |
| 154 #include "snapshot/mac/process_types/all.proctype" | 143 #include "snapshot/mac/process_types/all.proctype" |
| 155 | 144 |
| 156 #undef PROCESS_TYPE_STRUCT_BEGIN | 145 #undef PROCESS_TYPE_STRUCT_BEGIN |
| 157 #undef PROCESS_TYPE_STRUCT_MEMBER | 146 #undef PROCESS_TYPE_STRUCT_MEMBER |
| 147 #undef PROCESS_TYPE_STRUCT_VERSIONED |
| 158 #undef PROCESS_TYPE_STRUCT_END | 148 #undef PROCESS_TYPE_STRUCT_END |
| 159 #undef PROCESS_TYPE_STRUCT_IMPLEMENT | 149 #undef PROCESS_TYPE_STRUCT_IMPLEMENT |
| 160 | 150 |
| 161 // Implement the specific crashpad::process_types::internal::struct_name<> | 151 // Implement the specific crashpad::process_types::internal::struct_name<> |
| 162 // ReadInto(). The default implementation simply reads the struct from the | 152 // ReadInto(). The default implementation simply reads the struct from the |
| 163 // remote process. This is separated from other method implementations because | 153 // remote process. This is separated from other method implementations because |
| 164 // some types may wish to provide custom readers. This can be done by guarding | 154 // some types may wish to provide custom readers. This can be done by guarding |
| 165 // such types’ proctype definitions against this macro and providing custom | 155 // such types’ proctype definitions against this macro and providing custom |
| 166 // implementations in snapshot/mac/process_types/custom.cc. | 156 // implementations in snapshot/mac/process_types/custom.cc. |
| 167 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 | 157 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 178 struct_name<Traits>* specific) { \ | 168 struct_name<Traits>* specific) { \ |
| 179 return process_reader->Memory()->Read( \ | 169 return process_reader->Memory()->Read( \ |
| 180 address, sizeof(*specific), specific); \ | 170 address, sizeof(*specific), specific); \ |
| 181 } \ | 171 } \ |
| 182 } /* namespace internal */ \ | 172 } /* namespace internal */ \ |
| 183 } /* namespace process_types */ \ | 173 } /* namespace process_types */ \ |
| 184 } /* namespace crashpad */ | 174 } /* namespace crashpad */ |
| 185 | 175 |
| 186 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) | 176 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) |
| 187 | 177 |
| 178 #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) |
| 179 |
| 188 #define PROCESS_TYPE_STRUCT_END(struct_name) | 180 #define PROCESS_TYPE_STRUCT_END(struct_name) |
| 189 | 181 |
| 190 #include "snapshot/mac/process_types/all.proctype" | 182 #include "snapshot/mac/process_types/all.proctype" |
| 191 | 183 |
| 192 #undef PROCESS_TYPE_STRUCT_BEGIN | 184 #undef PROCESS_TYPE_STRUCT_BEGIN |
| 193 #undef PROCESS_TYPE_STRUCT_MEMBER | 185 #undef PROCESS_TYPE_STRUCT_MEMBER |
| 186 #undef PROCESS_TYPE_STRUCT_VERSIONED |
| 194 #undef PROCESS_TYPE_STRUCT_END | 187 #undef PROCESS_TYPE_STRUCT_END |
| 195 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO | 188 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO |
| 196 | 189 |
| 197 // Implement the array operations. These are separated from other method | 190 // Implement the array operations. These are separated from other method |
| 198 // implementations because some types are variable-length and are never stored | 191 // implementations because some types are variable-length and are never stored |
| 199 // as direct-access arrays. It would be incorrect to provide reader | 192 // as direct-access arrays. It would be incorrect to provide reader |
| 200 // implementations for such types. Types that wish to suppress array operations | 193 // implementations for such types. Types that wish to suppress array operations |
| 201 // can do so by guarding their proctype definitions against this macro. | 194 // can do so by guarding their proctype definitions against this macro. |
| 202 #define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1 | 195 #define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1 |
| 203 | 196 |
| 204 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | 197 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ |
| 205 namespace crashpad { \ | 198 namespace crashpad { \ |
| 206 namespace process_types { \ | 199 namespace process_types { \ |
| 207 namespace internal { \ | 200 namespace internal { \ |
| 208 \ | 201 \ |
| 209 /* static */ \ | 202 /* static */ \ |
| 210 template <typename Traits> \ | 203 template <typename Traits> \ |
| 211 bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ | 204 bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ |
| 212 mach_vm_address_t address, \ | 205 mach_vm_address_t address, \ |
| 213 size_t count, \ | 206 size_t count, \ |
| 214 struct_name<Traits>* specific) { \ | 207 struct_name<Traits>* specific) { \ |
| 215 return process_reader->Memory()->Read( \ | 208 return process_reader->Memory()->Read( \ |
| 216 address, sizeof(struct_name<Traits>[count]), specific); \ | 209 address, sizeof(struct_name<Traits>[count]), specific); \ |
| 217 } \ | 210 } \ |
| 218 \ | 211 \ |
| 219 /* static */ \ | |
| 220 template <typename Traits> \ | |
| 221 size_t struct_name<Traits>::ExpectedSizeForVersion(uint64_t version) { \ | |
| 222 NOTREACHED(); \ | |
| 223 return 0; \ | |
| 224 } \ | |
| 225 } /* namespace internal */ \ | 212 } /* namespace internal */ \ |
| 226 \ | 213 \ |
| 227 /* static */ \ | 214 /* static */ \ |
| 228 bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ | 215 bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ |
| 229 mach_vm_address_t address, \ | 216 mach_vm_address_t address, \ |
| 230 size_t count, \ | 217 size_t count, \ |
| 231 struct_name* generic) { \ | 218 struct_name* generic) { \ |
| 232 if (!process_reader->Is64Bit()) { \ | 219 if (!process_reader->Is64Bit()) { \ |
| 233 return ReadArrayIntoInternal< \ | 220 return ReadArrayIntoInternal< \ |
| 234 internal::struct_name<internal::Traits32> >( \ | 221 internal::struct_name<internal::Traits32> >( \ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 254 for (size_t index = 0; index < count; ++index) { \ | 241 for (size_t index = 0; index < count; ++index) { \ |
| 255 specific[index].GenericizeInto(&generic[index], &generic[index].size_); \ | 242 specific[index].GenericizeInto(&generic[index], &generic[index].size_); \ |
| 256 } \ | 243 } \ |
| 257 return true; \ | 244 return true; \ |
| 258 } \ | 245 } \ |
| 259 } /* namespace process_types */ \ | 246 } /* namespace process_types */ \ |
| 260 } /* namespace crashpad */ | 247 } /* namespace crashpad */ |
| 261 | 248 |
| 262 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) | 249 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) |
| 263 | 250 |
| 251 #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) |
| 252 |
| 264 #define PROCESS_TYPE_STRUCT_END(struct_name) | 253 #define PROCESS_TYPE_STRUCT_END(struct_name) |
| 265 | 254 |
| 266 #include "snapshot/mac/process_types/all.proctype" | 255 #include "snapshot/mac/process_types/all.proctype" |
| 267 | 256 |
| 268 #undef PROCESS_TYPE_STRUCT_BEGIN | 257 #undef PROCESS_TYPE_STRUCT_BEGIN |
| 269 #undef PROCESS_TYPE_STRUCT_MEMBER | 258 #undef PROCESS_TYPE_STRUCT_MEMBER |
| 259 #undef PROCESS_TYPE_STRUCT_VERSIONED |
| 270 #undef PROCESS_TYPE_STRUCT_END | 260 #undef PROCESS_TYPE_STRUCT_END |
| 271 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY | 261 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY |
| 262 |
| 263 // Implement the generic crashpad::process_types::struct_name |
| 264 // ExpectedSizeForVersion(), which delegates to the templatized |
| 265 // ExpectedSizeForVersion(), which returns the expected size of a versioned |
| 266 // structure given a version parameter. This is only implemented for structures |
| 267 // that use PROCESS_TYPE_STRUCT_VERSIONED(), and implementations of the internal |
| 268 // templatized functions must be provided in |
| 269 // snapshot/mac/process_types/custom.cc. |
| 270 #define PROCESS_TYPE_STRUCT_IMPLEMENT_VERSIONED 1 |
| 271 |
| 272 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) |
| 273 |
| 274 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) |
| 275 |
| 276 #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \ |
| 277 namespace crashpad { \ |
| 278 namespace process_types { \ |
| 279 \ |
| 280 /* static */ \ |
| 281 size_t struct_name::ExpectedSizeForVersion( \ |
| 282 ProcessReader* process_reader, \ |
| 283 decltype(struct_name::version_field) version) { \ |
| 284 if (!process_reader->Is64Bit()) { \ |
| 285 return internal::struct_name< \ |
| 286 internal::Traits32>::ExpectedSizeForVersion(version); \ |
| 287 } else { \ |
| 288 return internal::struct_name< \ |
| 289 internal::Traits64>::ExpectedSizeForVersion(version); \ |
| 290 } \ |
| 291 } \ |
| 292 \ |
| 293 } /* namespace process_types */ \ |
| 294 } /* namespace crashpad */ |
| 295 |
| 296 #define PROCESS_TYPE_STRUCT_END(struct_name) |
| 297 |
| 298 #include "snapshot/mac/process_types/all.proctype" |
| 299 |
| 300 #undef PROCESS_TYPE_STRUCT_BEGIN |
| 301 #undef PROCESS_TYPE_STRUCT_MEMBER |
| 302 #undef PROCESS_TYPE_STRUCT_VERSIONED |
| 303 #undef PROCESS_TYPE_STRUCT_END |
| 304 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_VERSIONED |
| OLD | NEW |