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 |