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" |
20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
21 #include "snapshot/mac/process_types/internal.h" | 22 #include "snapshot/mac/process_types/internal.h" |
22 #include "util/mach/task_memory.h" | 23 #include "util/mach/task_memory.h" |
23 | 24 |
24 namespace crashpad { | 25 namespace crashpad { |
25 namespace { | 26 namespace { |
26 | 27 |
27 // Assign() is used by each flavor's ReadInto implementation to copy data from a | 28 // 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 // specific struct to a generic struct. For fundamental types, the assignment |
29 // operator suffices. For other types such as arrays, an explicit Assign | 30 // operator suffices. For other types such as arrays, an explicit Assign |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 } // namespace | 76 } // namespace |
76 } // namespace crashpad | 77 } // namespace crashpad |
77 | 78 |
78 // Implement the generic crashpad::process_types::struct_name ReadInto(), which | 79 // Implement the generic crashpad::process_types::struct_name ReadInto(), which |
79 // delegates to the templatized ReadIntoInternal(), which reads the specific | 80 // delegates to the templatized ReadIntoInternal(), which reads the specific |
80 // struct type from the remote process and genericizes it. Also implement | 81 // struct type from the remote process and genericizes it. Also implement |
81 // crashpad::process_types::internal::struct_name<> GenericizeInto(), which | 82 // crashpad::process_types::internal::struct_name<> GenericizeInto(), which |
82 // operates on each member in the struct. | 83 // operates on each member in the struct. |
83 #define PROCESS_TYPE_STRUCT_IMPLEMENT 1 | 84 #define PROCESS_TYPE_STRUCT_IMPLEMENT 1 |
84 | 85 |
85 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | 86 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ |
86 namespace crashpad { \ | 87 namespace crashpad { \ |
87 namespace process_types { \ | 88 namespace process_types { \ |
88 \ | 89 \ |
89 size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ | 90 /* static */ \ |
90 if (!process_reader->Is64Bit()) { \ | 91 size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ |
91 return internal::struct_name<internal::Traits32>::Size(); \ | 92 if (!process_reader->Is64Bit()) { \ |
92 } else { \ | 93 return internal::struct_name<internal::Traits32>::Size(); \ |
93 return internal::struct_name<internal::Traits64>::Size(); \ | 94 } else { \ |
94 } \ | 95 return internal::struct_name<internal::Traits64>::Size(); \ |
95 } \ | 96 } \ |
96 \ | 97 } \ |
97 bool struct_name::ReadInto(ProcessReader* process_reader, \ | 98 \ |
98 mach_vm_address_t address, \ | 99 /* static */ \ |
99 struct_name* generic) { \ | 100 size_t struct_name::ExpectedSizeForVersion(ProcessReader* process_reader, \ |
100 if (!process_reader->Is64Bit()) { \ | 101 uint64_t version) { \ |
101 return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \ | 102 if (!process_reader->Is64Bit()) { \ |
102 process_reader, address, generic); \ | 103 return internal::struct_name< \ |
103 } else { \ | 104 internal::Traits32>::ExpectedSizeForVersion(version); \ |
104 return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \ | 105 } else { \ |
105 process_reader, address, generic); \ | 106 return internal::struct_name< \ |
106 } \ | 107 internal::Traits64>::ExpectedSizeForVersion(version); \ |
107 } \ | 108 } \ |
108 \ | 109 } \ |
109 template <typename T> \ | 110 \ |
110 bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ | 111 /* static */ \ |
111 mach_vm_address_t address, \ | 112 bool struct_name::ReadInto(ProcessReader* process_reader, \ |
112 struct_name* generic) { \ | 113 mach_vm_address_t address, \ |
113 T specific; \ | 114 struct_name* generic) { \ |
114 if (!specific.Read(process_reader, address)) { \ | 115 if (!process_reader->Is64Bit()) { \ |
115 return false; \ | 116 return ReadIntoInternal<internal::struct_name<internal::Traits32> >( \ |
116 } \ | 117 process_reader, address, generic); \ |
117 specific.GenericizeInto(generic, &generic->size_); \ | 118 } else { \ |
118 return true; \ | 119 return ReadIntoInternal<internal::struct_name<internal::Traits64> >( \ |
119 } \ | 120 process_reader, address, generic); \ |
120 \ | 121 } \ |
121 namespace internal { \ | 122 } \ |
122 \ | 123 \ |
123 template <typename Traits> \ | 124 /* static */ \ |
124 void struct_name<Traits>::GenericizeInto( \ | 125 template <typename T> \ |
125 process_types::struct_name* generic, \ | 126 bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ |
126 size_t* specific_size) { \ | 127 mach_vm_address_t address, \ |
| 128 struct_name* generic) { \ |
| 129 T specific; \ |
| 130 if (!specific.Read(process_reader, address)) { \ |
| 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) { \ |
127 *specific_size = Size(); | 143 *specific_size = Size(); |
128 | 144 |
129 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ | 145 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ |
130 Assign(&generic->member_name, member_name); | 146 Assign(&generic->member_name, member_name); |
131 | 147 |
132 #define PROCESS_TYPE_STRUCT_END(struct_name) \ | 148 #define PROCESS_TYPE_STRUCT_END(struct_name) \ |
133 } \ | 149 } \ |
134 } /* namespace internal */ \ | 150 } /* namespace internal */ \ |
135 } /* namespace process_types */ \ | 151 } /* namespace process_types */ \ |
136 } /* namespace crashpad */ | 152 } /* namespace crashpad */ |
(...skipping 11 matching lines...) Expand all Loading... |
148 // some types may wish to provide custom readers. This can be done by guarding | 164 // 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 | 165 // such types’ proctype definitions against this macro and providing custom |
150 // implementations in snapshot/mac/process_types/custom.cc. | 166 // implementations in snapshot/mac/process_types/custom.cc. |
151 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 | 167 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 |
152 | 168 |
153 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | 169 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ |
154 namespace crashpad { \ | 170 namespace crashpad { \ |
155 namespace process_types { \ | 171 namespace process_types { \ |
156 namespace internal { \ | 172 namespace internal { \ |
157 \ | 173 \ |
| 174 /* static */ \ |
158 template <typename Traits> \ | 175 template <typename Traits> \ |
159 bool struct_name<Traits>::ReadInto(ProcessReader* process_reader, \ | 176 bool struct_name<Traits>::ReadInto(ProcessReader* process_reader, \ |
160 mach_vm_address_t address, \ | 177 mach_vm_address_t address, \ |
161 struct_name<Traits>* specific) { \ | 178 struct_name<Traits>* specific) { \ |
162 return process_reader->Memory()->Read( \ | 179 return process_reader->Memory()->Read( \ |
163 address, sizeof(*specific), specific); \ | 180 address, sizeof(*specific), specific); \ |
164 } \ | 181 } \ |
165 } /* namespace internal */ \ | 182 } /* namespace internal */ \ |
166 } /* namespace process_types */ \ | 183 } /* namespace process_types */ \ |
167 } /* namespace crashpad */ | 184 } /* namespace crashpad */ |
(...skipping 14 matching lines...) Expand all Loading... |
182 // as direct-access arrays. It would be incorrect to provide reader | 199 // as direct-access arrays. It would be incorrect to provide reader |
183 // implementations for such types. Types that wish to suppress array operations | 200 // implementations for such types. Types that wish to suppress array operations |
184 // can do so by guarding their proctype definitions against this macro. | 201 // can do so by guarding their proctype definitions against this macro. |
185 #define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1 | 202 #define PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY 1 |
186 | 203 |
187 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ | 204 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ |
188 namespace crashpad { \ | 205 namespace crashpad { \ |
189 namespace process_types { \ | 206 namespace process_types { \ |
190 namespace internal { \ | 207 namespace internal { \ |
191 \ | 208 \ |
| 209 /* static */ \ |
192 template <typename Traits> \ | 210 template <typename Traits> \ |
193 bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ | 211 bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ |
194 mach_vm_address_t address, \ | 212 mach_vm_address_t address, \ |
195 size_t count, \ | 213 size_t count, \ |
196 struct_name<Traits>* specific) { \ | 214 struct_name<Traits>* specific) { \ |
197 return process_reader->Memory()->Read( \ | 215 return process_reader->Memory()->Read( \ |
198 address, sizeof(struct_name<Traits> [count]), specific); \ | 216 address, sizeof(struct_name<Traits>[count]), specific); \ |
| 217 } \ |
| 218 \ |
| 219 /* static */ \ |
| 220 template <typename Traits> \ |
| 221 size_t struct_name<Traits>::ExpectedSizeForVersion(uint64_t version) { \ |
| 222 NOTREACHED(); \ |
| 223 return 0; \ |
199 } \ | 224 } \ |
200 } /* namespace internal */ \ | 225 } /* namespace internal */ \ |
201 \ | 226 \ |
| 227 /* static */ \ |
202 bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ | 228 bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ |
203 mach_vm_address_t address, \ | 229 mach_vm_address_t address, \ |
204 size_t count, \ | 230 size_t count, \ |
205 struct_name* generic) { \ | 231 struct_name* generic) { \ |
206 if (!process_reader->Is64Bit()) { \ | 232 if (!process_reader->Is64Bit()) { \ |
207 return ReadArrayIntoInternal< \ | 233 return ReadArrayIntoInternal< \ |
208 internal::struct_name<internal::Traits32> >( \ | 234 internal::struct_name<internal::Traits32> >( \ |
209 process_reader, address, count, generic); \ | 235 process_reader, address, count, generic); \ |
210 } else { \ | 236 } else { \ |
211 return ReadArrayIntoInternal< \ | 237 return ReadArrayIntoInternal< \ |
212 internal::struct_name<internal::Traits64> >( \ | 238 internal::struct_name<internal::Traits64> >( \ |
213 process_reader, address, count, generic); \ | 239 process_reader, address, count, generic); \ |
214 } \ | 240 } \ |
215 return true; \ | 241 return true; \ |
216 } \ | 242 } \ |
217 \ | 243 \ |
| 244 /* static */ \ |
218 template <typename T> \ | 245 template <typename T> \ |
219 bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader, \ | 246 bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader, \ |
220 mach_vm_address_t address, \ | 247 mach_vm_address_t address, \ |
221 size_t count, \ | 248 size_t count, \ |
222 struct_name* generic) { \ | 249 struct_name* generic) { \ |
223 scoped_ptr<T[]> specific(new T[count]); \ | 250 scoped_ptr<T[]> specific(new T[count]); \ |
224 if (!T::ReadArrayInto(process_reader, address, count, &specific[0])) { \ | 251 if (!T::ReadArrayInto(process_reader, address, count, &specific[0])) { \ |
225 return false; \ | 252 return false; \ |
226 } \ | 253 } \ |
227 for (size_t index = 0; index < count; ++index) { \ | 254 for (size_t index = 0; index < count; ++index) { \ |
228 specific[index].GenericizeInto(&generic[index], &generic[index].size_); \ | 255 specific[index].GenericizeInto(&generic[index], &generic[index].size_); \ |
229 } \ | 256 } \ |
230 return true; \ | 257 return true; \ |
231 } \ | 258 } \ |
232 } /* namespace process_types */ \ | 259 } /* namespace process_types */ \ |
233 } /* namespace crashpad */ | 260 } /* namespace crashpad */ |
234 | 261 |
235 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) | 262 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) |
236 | 263 |
237 #define PROCESS_TYPE_STRUCT_END(struct_name) | 264 #define PROCESS_TYPE_STRUCT_END(struct_name) |
238 | 265 |
239 #include "snapshot/mac/process_types/all.proctype" | 266 #include "snapshot/mac/process_types/all.proctype" |
240 | 267 |
241 #undef PROCESS_TYPE_STRUCT_BEGIN | 268 #undef PROCESS_TYPE_STRUCT_BEGIN |
242 #undef PROCESS_TYPE_STRUCT_MEMBER | 269 #undef PROCESS_TYPE_STRUCT_MEMBER |
243 #undef PROCESS_TYPE_STRUCT_END | 270 #undef PROCESS_TYPE_STRUCT_END |
244 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY | 271 #undef PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY |
OLD | NEW |