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 #ifndef CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ | |
16 #define CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ | |
17 | |
18 #include <mach/mach.h> | |
19 | |
20 #include "util/mach/mach_message_server.h" | |
21 | |
22 namespace crashpad { | |
23 | |
24 // Routines to provide a single unified front-end to the interfaces in | |
25 // <mach/exc.defs> and <mach/mach_exc.defs>. The two interfaces are identical, | |
26 // except that the latter allows for 64-bit exception codes, and is requested by | |
27 // setting the MACH_EXCEPTION_CODES behavior bit associated with an exception | |
28 // port. | |
29 | |
30 //! \brief A server interface for the `exc` Mach subsystem. | |
31 class ExcServer : public MachMessageServer::Interface { | |
32 public: | |
33 //! \brief An interface that the different request messages that are a part of | |
34 //! the `exc` Mach subsystem can be dispatched to. | |
35 class Interface { | |
36 public: | |
37 //! \brief Handles exceptions raised by `exception_raise()`. | |
38 //! | |
39 //! This behaves equivalently to a `catch_exception_raise()` function used | |
40 //! with `exc_server()`. | |
41 //! | |
42 //! \param[out] destroy_request `true` if the request message is to be | |
43 //! destroyed even when this method returns success. See | |
44 //! MachMessageServer::Interface. | |
45 virtual kern_return_t CatchExceptionRaise( | |
46 exception_handler_t exception_port, | |
47 thread_t thread, | |
48 task_t task, | |
49 exception_type_t exception, | |
50 const exception_data_type_t* code, | |
51 mach_msg_type_number_t code_count, | |
52 bool* destroy_request) = 0; | |
53 | |
54 //! \brief Handles exceptions raised by `exception_raise_state()`. | |
55 //! | |
56 //! This behaves equivalently to a `catch_exception_raise_state()` function | |
57 //! used with `exc_server()`. | |
58 virtual kern_return_t CatchExceptionRaiseState( | |
59 exception_handler_t exception_port, | |
60 exception_type_t exception, | |
61 const exception_data_type_t* code, | |
62 mach_msg_type_number_t code_count, | |
63 thread_state_flavor_t* flavor, | |
64 const natural_t* old_state, | |
65 mach_msg_type_number_t old_state_count, | |
66 thread_state_t new_state, | |
67 mach_msg_type_number_t* new_state_count) = 0; | |
Robert Sesek
2014/09/10 16:44:41
No destroy_request?
Mark Mentovai
2014/09/10 20:12:56
rsesek wrote:
| |
68 | |
69 //! \brief Handles exceptions raised by `exception_raise_state_identity()`. | |
70 //! | |
71 //! This behaves equivalently to a `catch_exception_raise_state_identity()` | |
72 //! function used with `exc_server()`. | |
73 //! | |
74 //! \param[out] destroy_request `true` if the request message is to be | |
75 //! destroyed even when this method returns success. See | |
76 //! MachMessageServer::Interface. | |
77 virtual kern_return_t CatchExceptionRaiseStateIdentity( | |
78 exception_handler_t exception_port, | |
79 thread_t thread, | |
80 task_t task, | |
81 exception_type_t exception, | |
82 const exception_data_type_t* code, | |
83 mach_msg_type_number_t code_count, | |
84 thread_state_flavor_t* flavor, | |
85 const natural_t* old_state, | |
86 mach_msg_type_number_t old_state_count, | |
87 thread_state_t new_state, | |
88 mach_msg_type_number_t* new_state_count, | |
89 bool* destroy_request) = 0; | |
90 | |
91 protected: | |
92 ~Interface() {} | |
93 }; | |
94 | |
95 explicit ExcServer(Interface* interface); | |
96 | |
97 // MachMessageServer::Interface: | |
98 | |
99 virtual bool MachMessageServerFunction( | |
100 mach_msg_header_t* in_header, | |
101 mach_msg_header_t* out_header, | |
102 bool* destroy_complex_request) override; | |
103 | |
104 virtual mach_msg_size_t MachMessageServerRequestSize() override; | |
105 virtual mach_msg_size_t MachMessageServerReplySize() override; | |
106 | |
107 private: | |
108 Interface* interface_; // weak | |
109 }; | |
110 | |
111 //! \brief A server interface for the `mach_exc` Mach subsystem. | |
112 class MachExcServer : public MachMessageServer::Interface { | |
113 public: | |
114 //! \brief An interface that the different request messages that are a part of | |
115 //! the `mach_exc` Mach subsystem can be dispatched to. | |
116 class Interface { | |
117 public: | |
118 //! \brief Handles exceptions raised by `mach_exception_raise()`. | |
119 //! | |
120 //! This behaves equivalently to a `catch_mach_exception_raise()` function | |
121 //! used with `mach_exc_server()`. | |
122 //! | |
123 //! \param[out] destroy_request `true` if the request message is to be | |
124 //! destroyed even when this method returns success. See | |
125 //! MachMessageServer::Interface. | |
126 virtual kern_return_t CatchMachExceptionRaise( | |
127 exception_handler_t exception_port, | |
128 thread_t thread, | |
129 task_t task, | |
130 exception_type_t exception, | |
131 const mach_exception_data_type_t* code, | |
132 mach_msg_type_number_t code_count, | |
133 bool* destroy_request) = 0; | |
134 | |
135 //! \brief Handles exceptions raised by `mach_exception_raise_state()`. | |
136 //! | |
137 //! This behaves equivalently to a `catch_mach_exception_raise_state()` | |
138 //! function used with `mach_exc_server()`. | |
139 virtual kern_return_t CatchMachExceptionRaiseState( | |
140 exception_handler_t exception_port, | |
141 exception_type_t exception, | |
142 const mach_exception_data_type_t* code, | |
143 mach_msg_type_number_t code_count, | |
144 thread_state_flavor_t* flavor, | |
145 const natural_t* old_state, | |
146 mach_msg_type_number_t old_state_count, | |
147 thread_state_t new_state, | |
148 mach_msg_type_number_t* new_state_count) = 0; | |
149 | |
150 //! \brief Handles exceptions raised by | |
151 //! `mach_exception_raise_state_identity()`. | |
152 //! | |
153 //! This behaves equivalently to a | |
154 //! `catch_mach_exception_raise_state_identity()` function used with | |
155 //! `mach_exc_server()`. | |
156 //! | |
157 //! \param[out] destroy_request `true` if the request message is to be | |
158 //! destroyed even when this method returns success. See | |
159 //! MachMessageServer::Interface. | |
160 virtual kern_return_t CatchMachExceptionRaiseStateIdentity( | |
161 exception_handler_t exception_port, | |
162 thread_t thread, | |
163 task_t task, | |
164 exception_type_t exception, | |
165 const mach_exception_data_type_t* code, | |
166 mach_msg_type_number_t code_count, | |
167 thread_state_flavor_t* flavor, | |
168 const natural_t* old_state, | |
169 mach_msg_type_number_t old_state_count, | |
170 thread_state_t new_state, | |
171 mach_msg_type_number_t* new_state_count, | |
172 bool* destroy_request) = 0; | |
173 | |
174 protected: | |
175 ~Interface() {} | |
176 }; | |
177 | |
178 explicit MachExcServer(Interface* interface); | |
179 | |
180 // MachMessageServer::Interface: | |
181 | |
182 virtual bool MachMessageServerFunction( | |
183 mach_msg_header_t* in_header, | |
184 mach_msg_header_t* out_header, | |
185 bool* destroy_complex_request) override; | |
186 | |
187 virtual mach_msg_size_t MachMessageServerRequestSize() override; | |
188 virtual mach_msg_size_t MachMessageServerReplySize() override; | |
189 | |
190 private: | |
191 Interface* interface_; // weak | |
192 }; | |
193 | |
194 //! \brief A server interface for the `exc` Mach subsystem, simplified to have | |
195 //! only a single interface method needing implementation. | |
196 class SimplifiedExcServer : public ExcServer, public ExcServer::Interface { | |
197 public: | |
198 //! \brief An interface that the different request messages that are a part of | |
199 //! the `exc` Mach subsystem can be dispatched to. | |
200 class Interface { | |
201 public: | |
202 //! \brief Handles exceptions raised by `exception_raise()`, | |
203 //! `exception_raise_state()`, and `exception_raise_state_identity()`. | |
204 //! | |
205 //! For convenience in implementation, these different “behaviors” of | |
206 //! exception messages are all mapped to a single interface method. The | |
207 //! exception’s original “behavior” is specified in the \a behavior | |
208 //! parameter. Only parameters that were supplied in the request message | |
209 //! are populated, other parameters are set to reasonable default values. | |
210 //! | |
211 //! The meanings of most parameters are identical to that of | |
212 //! ExcServer::Interface::CatchExceptionRaiseStateIdentity(). | |
213 //! | |
214 //! \param[in] behavior `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or | |
215 //! `EXCEPTION_STATE_IDENTITY`, identifying which exception request | |
216 //! message was processed and thus which other parameters are valid. | |
217 virtual kern_return_t CatchException( | |
218 exception_behavior_t behavior, | |
219 exception_handler_t exception_port, | |
220 thread_t thread, | |
221 task_t task, | |
222 exception_type_t exception, | |
223 const exception_data_type_t* code, | |
224 mach_msg_type_number_t code_count, | |
225 thread_state_flavor_t* flavor, | |
226 const natural_t* old_state, | |
227 mach_msg_type_number_t old_state_count, | |
228 thread_state_t new_state, | |
229 mach_msg_type_number_t* new_state_count, | |
230 bool* destroy_complex_request) = 0; | |
231 | |
232 protected: | |
233 ~Interface() {} | |
234 }; | |
235 | |
236 explicit SimplifiedExcServer(Interface* interface); | |
237 | |
238 // ExcServer::Interface: | |
239 | |
240 virtual kern_return_t CatchExceptionRaise( | |
241 exception_handler_t exception_port, | |
242 thread_t thread, | |
243 task_t task, | |
244 exception_type_t exception, | |
245 const exception_data_type_t* code, | |
246 mach_msg_type_number_t code_count, | |
247 bool* destroy_request) override; | |
248 virtual kern_return_t CatchExceptionRaiseState( | |
249 exception_handler_t exception_port, | |
250 exception_type_t exception, | |
251 const exception_data_type_t* code, | |
252 mach_msg_type_number_t code_count, | |
253 thread_state_flavor_t* flavor, | |
254 const natural_t* old_state, | |
255 mach_msg_type_number_t old_state_count, | |
256 thread_state_t new_state, | |
257 mach_msg_type_number_t* new_state_count) override; | |
258 virtual kern_return_t CatchExceptionRaiseStateIdentity( | |
259 exception_handler_t exception_port, | |
260 thread_t thread, | |
261 task_t task, | |
262 exception_type_t exception, | |
263 const exception_data_type_t* code, | |
264 mach_msg_type_number_t code_count, | |
265 thread_state_flavor_t* flavor, | |
266 const natural_t* old_state, | |
267 mach_msg_type_number_t old_state_count, | |
268 thread_state_t new_state, | |
269 mach_msg_type_number_t* new_state_count, | |
270 bool* destroy_request) override; | |
271 | |
272 private: | |
273 Interface* interface_; // weak | |
274 }; | |
275 | |
276 //! \brief A server interface for the `mach_exc` Mach subsystem, simplified to | |
277 //! have only a single interface method needing implementation. | |
278 class SimplifiedMachExcServer : public MachExcServer, | |
Robert Sesek
2014/09/10 16:44:41
Do you really need to present all of these interfa
Mark Mentovai
2014/09/10 20:12:56
rsesek wrote:
| |
279 public MachExcServer::Interface { | |
280 public: | |
281 //! \brief An interface that the different request messages that are a part of | |
282 //! the `mach_exc` Mach subsystem can be dispatched to. | |
283 class Interface { | |
284 public: | |
285 //! \brief Handles exceptions raised by `mach_exception_raise()`, | |
286 //! `mach_exception_raise_state()`, and | |
287 //! `mach_exception_raise_state_identity()`. | |
288 //! | |
289 //! When used with UniversalMachExcServer, this also handles exceptions | |
290 //! raised by `exception_raise()`, `exception_raise_state()`, and | |
291 //! `exception_raise_state_identity()`. | |
292 //! | |
293 //! For convenience in implementation, these different “behaviors” of | |
294 //! exception messages are all mapped to a single interface method. The | |
295 //! exception’s original “behavior” is specified in the \a behavior | |
296 //! parameter. Only parameters that were supplied in the request message | |
297 //! are populated, other parameters are set to reasonable default values. | |
298 //! | |
299 //! The meanings of most parameters are identical to that of | |
300 //! MachExcServer::Interface::CatchMachExceptionRaiseStateIdentity(). | |
301 //! | |
302 //! \param[in] behavior `MACH_EXCEPTION_CODES | EXCEPTION_DEFAULT`, | |
303 //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE`, or | |
304 //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY`, identifying which | |
305 //! exception request message was processed and thus which other | |
306 //! parameters are valid. When used with UniversalMachExcServer, \a | |
307 //! behavior can also be `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or | |
308 //! `EXCEPTION_STATE_IDENTITY`. | |
309 virtual kern_return_t CatchMachException( | |
310 exception_behavior_t behavior, | |
311 exception_handler_t exception_port, | |
312 thread_t thread, | |
313 task_t task, | |
314 exception_type_t exception, | |
315 const mach_exception_data_type_t* code, | |
316 mach_msg_type_number_t code_count, | |
317 thread_state_flavor_t* flavor, | |
318 const natural_t* old_state, | |
319 mach_msg_type_number_t old_state_count, | |
320 thread_state_t new_state, | |
321 mach_msg_type_number_t* new_state_count, | |
322 bool* destroy_complex_request) = 0; | |
323 | |
324 protected: | |
325 ~Interface() {} | |
326 }; | |
327 | |
328 explicit SimplifiedMachExcServer(Interface* interface); | |
329 | |
330 // MachExcServer::Interface: | |
331 | |
332 virtual kern_return_t CatchMachExceptionRaise( | |
333 exception_handler_t exception_port, | |
334 thread_t thread, | |
335 task_t task, | |
336 exception_type_t exception, | |
337 const mach_exception_data_type_t* code, | |
338 mach_msg_type_number_t code_count, | |
339 bool* destroy_request) override; | |
340 virtual kern_return_t CatchMachExceptionRaiseState( | |
341 exception_handler_t exception_port, | |
342 exception_type_t exception, | |
343 const mach_exception_data_type_t* code, | |
344 mach_msg_type_number_t code_count, | |
345 thread_state_flavor_t* flavor, | |
346 const natural_t* old_state, | |
347 mach_msg_type_number_t old_state_count, | |
348 thread_state_t new_state, | |
349 mach_msg_type_number_t* new_state_count) override; | |
350 virtual kern_return_t CatchMachExceptionRaiseStateIdentity( | |
351 exception_handler_t exception_port, | |
352 thread_t thread, | |
353 task_t task, | |
354 exception_type_t exception, | |
355 const mach_exception_data_type_t* code, | |
356 mach_msg_type_number_t code_count, | |
357 thread_state_flavor_t* flavor, | |
358 const natural_t* old_state, | |
359 mach_msg_type_number_t old_state_count, | |
360 thread_state_t new_state, | |
361 mach_msg_type_number_t* new_state_count, | |
362 bool* destroy_request) override; | |
363 | |
364 private: | |
365 Interface* interface_; // weak | |
366 }; | |
367 | |
368 //! \brief A server interface for the `exc` and `mach_exc` Mach subsystems, | |
369 //! unified to handle exceptions delivered to either subsystem, and | |
370 //! simplified to have only a single interface method needing | |
371 //! implementation. | |
372 //! | |
373 //! UniversalMachExcServer operates by translating messages received in the | |
374 //! `exc` subsystem to a variant that is compatible with the `mach_exc` | |
375 //! subsystem. This involves changing the format of \a code, the exception code | |
376 //! field, from `exception_data_type_t` to `mach_exception_data_type_t`. | |
377 //! This is achieved by implementing SimplifiedExcServer::Interface and having | |
378 //! it forward translated messages to SimplifiedMachExcServer::Interface, which | |
379 //! is left unimplemented here so that users of this class can provide their own | |
380 //! implementations. | |
381 class UniversalMachExcServer : public MachMessageServer::Interface, | |
382 public SimplifiedExcServer::Interface, | |
383 public SimplifiedMachExcServer::Interface { | |
384 public: | |
385 UniversalMachExcServer(); | |
386 | |
387 // MachMessageServer::Interface: | |
388 | |
389 virtual bool MachMessageServerFunction( | |
390 mach_msg_header_t* in_header, | |
391 mach_msg_header_t* out_header, | |
392 bool* destroy_complex_request) override; | |
393 | |
394 virtual mach_msg_size_t MachMessageServerRequestSize() override; | |
395 virtual mach_msg_size_t MachMessageServerReplySize() override; | |
396 | |
397 // SimplifiedExcServer::Interface: | |
398 | |
399 virtual kern_return_t CatchException( | |
400 exception_behavior_t behavior, | |
401 exception_handler_t exception_port, | |
402 thread_t thread, | |
403 task_t task, | |
404 exception_type_t exception, | |
405 const exception_data_type_t* code, | |
406 mach_msg_type_number_t code_count, | |
407 thread_state_flavor_t* flavor, | |
408 const natural_t* old_state, | |
409 mach_msg_type_number_t old_state_count, | |
410 thread_state_t new_state, | |
411 mach_msg_type_number_t* new_state_count, | |
412 bool* destroy_complex_request) override; | |
413 | |
414 private: | |
415 SimplifiedExcServer exc_server_; | |
416 SimplifiedMachExcServer mach_exc_server_; | |
417 }; | |
418 | |
419 } // namespace crashpad | |
420 | |
421 #endif // CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ | |
OLD | NEW |