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 |