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/mach/exception_ports.h" | |
16 | |
17 #include "base/logging.h" | |
18 #include "base/mac/mach_logging.h" | |
19 | |
20 namespace crashpad { | |
21 | |
22 ExceptionPorts::ExceptionPorts(TargetType target_type, mach_port_t target_port) | |
23 : target_port_(target_port), dealloc_target_port_(false) { | |
24 switch (target_type) { | |
25 case kTargetTypeHost: | |
26 get_exception_ports_ = host_get_exception_ports; | |
27 set_exception_ports_ = host_set_exception_ports; | |
28 target_name_ = "host"; | |
29 if (target_port_ == MACH_PORT_NULL) { | |
30 target_port_ = mach_host_self(); | |
31 dealloc_target_port_ = true; | |
32 } | |
33 break; | |
34 | |
35 case kTargetTypeTask: | |
36 get_exception_ports_ = task_get_exception_ports; | |
37 set_exception_ports_ = task_set_exception_ports; | |
38 target_name_ = "task"; | |
39 if (target_port_ == MACH_PORT_NULL) { | |
40 target_port_ = mach_task_self(); | |
41 // Don’t deallocate mach_task_self(). | |
42 } | |
43 break; | |
44 | |
45 case kTargetTypeThread: | |
46 get_exception_ports_ = thread_get_exception_ports; | |
47 set_exception_ports_ = thread_set_exception_ports; | |
48 target_name_ = "thread"; | |
49 if (target_port_ == MACH_PORT_NULL) { | |
50 target_port_ = mach_thread_self(); | |
51 dealloc_target_port_ = true; | |
52 } | |
53 break; | |
54 | |
55 default: | |
56 NOTREACHED(); | |
57 get_exception_ports_ = NULL; | |
58 set_exception_ports_ = NULL; | |
59 target_name_ = NULL; | |
60 target_port_ = MACH_PORT_NULL; | |
61 break; | |
62 } | |
63 } | |
64 | |
65 ExceptionPorts::~ExceptionPorts() { | |
66 if (dealloc_target_port_) { | |
67 kern_return_t kr = mach_port_deallocate(mach_task_self(), target_port_); | |
68 if (kr != KERN_SUCCESS) { | |
69 MACH_LOG(ERROR, kr) << "mach_port_deallocate"; | |
Robert Sesek
2014/09/16 17:38:09
MACH_LOG_IF ?
| |
70 } | |
71 } | |
72 } | |
73 | |
74 kern_return_t ExceptionPorts::GetExceptionPorts( | |
75 exception_mask_t mask, | |
76 std::vector<ExceptionHandler>* handlers) const { | |
77 // <mach/mach_types.defs> says that these arrays have room for 32 elements, | |
78 // despite EXC_TYPES_COUNT only being as low as 11 (in the 10.6 SDK), and | |
79 // later operating system versions have defined more exception types. The | |
80 // generated task_get_exception_ports() in taskUser.c expects there to be room | |
81 // for 32. | |
82 const int kMaxPorts = 32; | |
83 | |
84 // task_get_exception_ports() doesn’t actually use the initial value of | |
85 // handler_count, but 10.9.4 | |
86 // xnu-2422.110.17/osfmk/man/task_get_exception_ports.html says it does. Humor | |
87 // the documentation. | |
88 mach_msg_type_number_t handler_count = kMaxPorts; | |
89 | |
90 exception_mask_t masks[kMaxPorts]; | |
91 exception_handler_t ports[kMaxPorts]; | |
92 exception_behavior_t behaviors[kMaxPorts]; | |
93 thread_state_flavor_t flavors[kMaxPorts]; | |
94 | |
95 kern_return_t kr = get_exception_ports_( | |
96 target_port_, mask, masks, &handler_count, ports, behaviors, flavors); | |
97 if (kr != KERN_SUCCESS) { | |
Robert Sesek
2014/09/16 17:38:09
In many other cases, you return bool and then log
| |
98 return kr; | |
99 } | |
100 | |
101 handlers->clear(); | |
102 for (mach_msg_type_number_t index = 0; index < handler_count; ++index) { | |
103 ExceptionHandler handler; | |
104 handler.mask = masks[index]; | |
105 handler.port = ports[index]; | |
106 handler.behavior = behaviors[index]; | |
107 handler.flavor = flavors[index]; | |
108 handlers->push_back(handler); | |
109 } | |
110 | |
111 return kr; | |
112 } | |
113 | |
114 kern_return_t ExceptionPorts::SetExceptionPort( | |
115 exception_mask_t mask, | |
116 exception_handler_t port, | |
117 exception_behavior_t behavior, | |
118 thread_state_flavor_t flavor) const { | |
119 return set_exception_ports_(target_port_, mask, port, behavior, flavor); | |
120 } | |
121 | |
122 const char* ExceptionPorts::TargetTypeName() const { | |
123 return target_name_; | |
124 } | |
125 | |
126 } // namespace crashpad | |
OLD | NEW |