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_EXCEPTION_PORTS_H_ |
| 16 #define CRASHPAD_UTIL_MACH_EXCEPTION_PORTS_H_ |
| 17 |
| 18 #include <mach/mach.h> |
| 19 |
| 20 #include <vector> |
| 21 |
| 22 #include "base/basictypes.h" |
| 23 |
| 24 namespace crashpad { |
| 25 |
| 26 //! \brief A better interface to `*_get_exception_ports()` and |
| 27 //! `*_set_exception_ports()`. |
| 28 //! |
| 29 //! The same generic interface can be used to operate on host, task, and thread |
| 30 //! exception ports. The “get” interface is superior to the system’s native |
| 31 //! interface because it keeps related data about a single exception handler |
| 32 //! together in one struct, rather than separating it into four parallel arrays. |
| 33 class ExceptionPorts { |
| 34 public: |
| 35 //! \brief Various entities which can have their own exception ports set. |
| 36 enum TargetType { |
| 37 //! \brief The host exception target. |
| 38 //! |
| 39 //! `host_get_exception_ports()` and `host_set_exception_ports()` will be |
| 40 //! used. If no target port is explicitly provided, `mach_host_self()` will |
| 41 //! be used as the target port. `mach_host_self()` is the only target port |
| 42 //! for this type that is expected to function properly. |
| 43 //! |
| 44 //! \note Operations on this target type are not expected to succeed as |
| 45 //! non-root, because `mach_host_self()` doesn’t return the privileged |
| 46 //! `host_priv` port to non-root users, and this is the target port |
| 47 //! that’s required for `host_get_exception_ports()` and |
| 48 //! `host_set_exception_ports()`. |
| 49 kTargetTypeHost = 0, |
| 50 |
| 51 //! \brief A task exception target. |
| 52 //! |
| 53 //! `task_get_exception_ports()` and `task_set_exception_ports()` will be |
| 54 //! used. If no target port is explicitly provided, `mach_task_self()` will |
| 55 //! be used as the target port. |
| 56 kTargetTypeTask, |
| 57 |
| 58 //! \brief A thread exception target. |
| 59 //! |
| 60 //! `thread_get_exception_ports()` and `thread_set_exception_ports()` will |
| 61 //! be used. If no target port is explicitly provided, `mach_thread_self()` |
| 62 //! will be used as the target port. |
| 63 kTargetTypeThread, |
| 64 }; |
| 65 |
| 66 //! \brief Information about a registered exception handler. |
| 67 struct ExceptionHandler { |
| 68 //! \brief A mask specifying the exception types to direct to \a port, |
| 69 //! containing `EXC_MASK_*` values. |
| 70 exception_mask_t mask; |
| 71 |
| 72 //! \brief A send right to a Mach port that will handle exceptions of the |
| 73 //! types indicated in \a mask. |
| 74 exception_handler_t port; |
| 75 |
| 76 //! \brief The “behavior” that the exception handler at \a port implements: |
| 77 //! `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or |
| 78 //! `EXCEPTION_STATE_IDENTITY`, possibly combined with |
| 79 //! `MACH_EXCEPTION_CODES`. |
| 80 exception_behavior_t behavior; |
| 81 |
| 82 //! \brief The thread state flavor that the exception handler at \a port |
| 83 //! will receive and possibly modify. This member has no effect for \a |
| 84 //! \a behavior values that indicate a “default” behavior. |
| 85 thread_state_flavor_t flavor; |
| 86 }; |
| 87 |
| 88 //! \brief Constructs an interface object to get or set exception ports on a |
| 89 //! host, task, or thread port. |
| 90 //! |
| 91 //! \param[in] target_type The type of target on which the exception ports are |
| 92 //! to be get or set: #kTargetTypeHost, #kTargetTypeTask, or or |
| 93 //! #kTargetTypeThread. The correct functions for |
| 94 //! `*_get_exception_ports()` and `*_set_exception_ports()` will be used. |
| 95 //! \param[in] target_port The target on which to call |
| 96 //! `*_get_exception_ports()` or `*_set_exception_ports()`. The target |
| 97 //! port must be a send right to a port of the type specified in \a |
| 98 //! target_type. In this case, ownership of \a target_port is not given to |
| 99 //! the new ExceptionPorts object. \a target_port may also be |
| 100 //! `MACH_PORT_NULL`, in which case `mach_host_self()`, |
| 101 //! `mach_task_self()`, or `mach_thread_self()` will be used as the target |
| 102 //! port depending on the value of \a target_type. In this case, ownership |
| 103 //! of the target port will be managed appropriately for \a target_type. |
| 104 ExceptionPorts(TargetType target_type, mach_port_t target_port); |
| 105 |
| 106 ~ExceptionPorts(); |
| 107 |
| 108 //! \brief Calls `*_get_exception_ports()` on the target. |
| 109 //! |
| 110 //! \param[in] mask The exception mask, containing the `EXC_MASK_*` values to |
| 111 //! be looked up and returned in \a handlers. |
| 112 //! \param[out] handlers The exception handlers registered for \a target_port |
| 113 //! to handle exceptions indicated in \a mask. The caller must take |
| 114 //! ownership of the \a port members of the returned ExceptionHandler |
| 115 //! objects. On failure, this argument is untouched. |
| 116 //! |
| 117 //! \return `true` if `*_get_exception_ports()` returned `KERN_SUCCESS`, with |
| 118 //! \a handlers set appropriately. `false` otherwise, with an appropriate |
| 119 //! message logged. |
| 120 bool GetExceptionPorts(exception_mask_t mask, |
| 121 std::vector<ExceptionHandler>* handlers) const; |
| 122 |
| 123 //! \brief Calls `*_set_exception_ports()` on the target. |
| 124 //! |
| 125 //! \param[in] mask A mask specifying the exception types to direct to \a |
| 126 //! port, containing `EXC_MASK_*` values. |
| 127 //! \param[in] port A send right to a Mach port that will handle exceptions |
| 128 //! sustained by \a target_port of the types indicated in \a mask. The |
| 129 //! send right is copied, not consumed, by this call. |
| 130 //! \param[in] behavior The “behavior” that the exception handler at \a port |
| 131 //! implements: `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or |
| 132 //! `EXCEPTION_STATE_IDENTITY`, possibly combined with |
| 133 //! `MACH_EXCEPTION_CODES`. |
| 134 //! \param[in] flavor The thread state flavor that the exception handler at \a |
| 135 //! port expects to receive and possibly modify. This argument has no |
| 136 //! effect for \a behavior values that indicate a “default” behavior. |
| 137 //! |
| 138 //! \return `true` if `*_set_exception_ports()` returned `KERN_SUCCESS`. |
| 139 //! `false` otherwise, with an appropriate message logged. |
| 140 bool SetExceptionPort(exception_mask_t mask, |
| 141 exception_handler_t port, |
| 142 exception_behavior_t behavior, |
| 143 thread_state_flavor_t flavor) const; |
| 144 |
| 145 //! \brief Returns a string identifying the target type. |
| 146 //! |
| 147 //! \return `"host"`, `"task"`, or `"thread"`, as appropriate. |
| 148 const char* TargetTypeName() const; |
| 149 |
| 150 private: |
| 151 typedef kern_return_t (*GetExceptionPortsType)(mach_port_t, |
| 152 exception_mask_t, |
| 153 exception_mask_array_t, |
| 154 mach_msg_type_number_t*, |
| 155 exception_handler_array_t, |
| 156 exception_behavior_array_t, |
| 157 exception_flavor_array_t); |
| 158 |
| 159 typedef kern_return_t (*SetExceptionPortsType)(mach_port_t, |
| 160 exception_mask_t, |
| 161 exception_handler_t, |
| 162 exception_behavior_t, |
| 163 thread_state_flavor_t); |
| 164 |
| 165 GetExceptionPortsType get_exception_ports_; |
| 166 SetExceptionPortsType set_exception_ports_; |
| 167 const char* target_name_; |
| 168 mach_port_t target_port_; |
| 169 |
| 170 // If true, target_port_ will be deallocated in the destructor. This will |
| 171 // always be false when the user provides a non-MACH_PORT_NULL target_port to |
| 172 // the constructor. It will also be false when target_type is kTargetTypeTask, |
| 173 // even with a MACH_PORT_NULL target_port, because it is incorrect to |
| 174 // deallocate the result of mach_task_self(). |
| 175 bool dealloc_target_port_; |
| 176 |
| 177 DISALLOW_COPY_AND_ASSIGN(ExceptionPorts); |
| 178 }; |
| 179 |
| 180 } // namespace crashpad |
| 181 |
| 182 #endif // CRASHPAD_UTIL_MACH_EXCEPTION_PORTS_H_ |
OLD | NEW |