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 "snapshot/mac/process_snapshot_mac.h"
16
17 #include <utility>
18
19 #include "base/logging.h"
20 #include "util/misc/tri_state.h"
21
22 namespace crashpad {
23
ProcessSnapshotMac()24 ProcessSnapshotMac::ProcessSnapshotMac()
25 : ProcessSnapshot(),
26 system_(),
27 threads_(),
28 modules_(),
29 exception_(),
30 process_reader_(),
31 report_id_(),
32 client_id_(),
33 annotations_simple_map_(),
34 snapshot_time_(),
35 initialized_() {
36 }
37
~ProcessSnapshotMac()38 ProcessSnapshotMac::~ProcessSnapshotMac() {
39 }
40
Initialize(task_t task)41 bool ProcessSnapshotMac::Initialize(task_t task) {
42 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
43
44 if (gettimeofday(&snapshot_time_, nullptr) != 0) {
45 PLOG(ERROR) << "gettimeofday";
46 return false;
47 }
48
49 if (!process_reader_.Initialize(task)) {
50 return false;
51 }
52
53 system_.Initialize(&process_reader_, &snapshot_time_);
54
55 InitializeThreads();
56 InitializeModules();
57
58 INITIALIZATION_STATE_SET_VALID(initialized_);
59 return true;
60 }
61
InitializeException(exception_behavior_t behavior,thread_t exception_thread,exception_type_t exception,const mach_exception_data_type_t * code,mach_msg_type_number_t code_count,thread_state_flavor_t flavor,ConstThreadState state,mach_msg_type_number_t state_count)62 bool ProcessSnapshotMac::InitializeException(
63 exception_behavior_t behavior,
64 thread_t exception_thread,
65 exception_type_t exception,
66 const mach_exception_data_type_t* code,
67 mach_msg_type_number_t code_count,
68 thread_state_flavor_t flavor,
69 ConstThreadState state,
70 mach_msg_type_number_t state_count) {
71 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
72 DCHECK(!exception_);
73
74 exception_.reset(new internal::ExceptionSnapshotMac());
75 if (!exception_->Initialize(&process_reader_,
76 behavior,
77 exception_thread,
78 exception,
79 code,
80 code_count,
81 flavor,
82 state,
83 state_count)) {
84 exception_.reset();
85 return false;
86 }
87
88 return true;
89 }
90
GetCrashpadOptions(CrashpadInfoClientOptions * options)91 void ProcessSnapshotMac::GetCrashpadOptions(
92 CrashpadInfoClientOptions* options) {
93 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
94
95 CrashpadInfoClientOptions local_options;
96
97 for (const auto& module : modules_) {
98 CrashpadInfoClientOptions module_options;
99 module->GetCrashpadOptions(&module_options);
100
101 if (local_options.crashpad_handler_behavior == TriState::kUnset) {
102 local_options.crashpad_handler_behavior =
103 module_options.crashpad_handler_behavior;
104 }
105 if (local_options.system_crash_reporter_forwarding == TriState::kUnset) {
106 local_options.system_crash_reporter_forwarding =
107 module_options.system_crash_reporter_forwarding;
108 }
109 if (local_options.gather_indirectly_referenced_memory == TriState::kUnset) {
110 local_options.gather_indirectly_referenced_memory =
111 module_options.gather_indirectly_referenced_memory;
112 local_options.indirectly_referenced_memory_cap =
113 module_options.indirectly_referenced_memory_cap;
114 }
115
116 // If non-default values have been found for all options, the loop can end
117 // early.
118 if (local_options.crashpad_handler_behavior != TriState::kUnset &&
119 local_options.system_crash_reporter_forwarding != TriState::kUnset &&
120 local_options.gather_indirectly_referenced_memory != TriState::kUnset) {
121 break;
122 }
123 }
124
125 *options = local_options;
126 }
127
ProcessID() const128 pid_t ProcessSnapshotMac::ProcessID() const {
129 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
130 return process_reader_.ProcessID();
131 }
132
ParentProcessID() const133 pid_t ProcessSnapshotMac::ParentProcessID() const {
134 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
135 return process_reader_.ParentProcessID();
136 }
137
SnapshotTime(timeval * snapshot_time) const138 void ProcessSnapshotMac::SnapshotTime(timeval* snapshot_time) const {
139 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
140 *snapshot_time = snapshot_time_;
141 }
142
ProcessStartTime(timeval * start_time) const143 void ProcessSnapshotMac::ProcessStartTime(timeval* start_time) const {
144 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
145 process_reader_.StartTime(start_time);
146 }
147
ProcessCPUTimes(timeval * user_time,timeval * system_time) const148 void ProcessSnapshotMac::ProcessCPUTimes(timeval* user_time,
149 timeval* system_time) const {
150 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
151 process_reader_.CPUTimes(user_time, system_time);
152 }
153
ReportID(UUID * report_id) const154 void ProcessSnapshotMac::ReportID(UUID* report_id) const {
155 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
156 *report_id = report_id_;
157 }
158
ClientID(UUID * client_id) const159 void ProcessSnapshotMac::ClientID(UUID* client_id) const {
160 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
161 *client_id = client_id_;
162 }
163
164 const std::map<std::string, std::string>&
AnnotationsSimpleMap() const165 ProcessSnapshotMac::AnnotationsSimpleMap() const {
166 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
167 return annotations_simple_map_;
168 }
169
System() const170 const SystemSnapshot* ProcessSnapshotMac::System() const {
171 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
172 return &system_;
173 }
174
Threads() const175 std::vector<const ThreadSnapshot*> ProcessSnapshotMac::Threads() const {
176 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
177 std::vector<const ThreadSnapshot*> threads;
178 for (const auto& thread : threads_) {
179 threads.push_back(thread.get());
180 }
181 return threads;
182 }
183
Modules() const184 std::vector<const ModuleSnapshot*> ProcessSnapshotMac::Modules() const {
185 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
186 std::vector<const ModuleSnapshot*> modules;
187 for (const auto& module : modules_) {
188 modules.push_back(module.get());
189 }
190 return modules;
191 }
192
UnloadedModules() const193 std::vector<UnloadedModuleSnapshot> ProcessSnapshotMac::UnloadedModules()
194 const {
195 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
196 return std::vector<UnloadedModuleSnapshot>();
197 }
198
Exception() const199 const ExceptionSnapshot* ProcessSnapshotMac::Exception() const {
200 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
201 return exception_.get();
202 }
203
MemoryMap() const204 std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotMac::MemoryMap()
205 const {
206 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
207 return std::vector<const MemoryMapRegionSnapshot*>();
208 }
209
Handles() const210 std::vector<HandleSnapshot> ProcessSnapshotMac::Handles() const {
211 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
212 return std::vector<HandleSnapshot>();
213 }
214
ExtraMemory() const215 std::vector<const MemorySnapshot*> ProcessSnapshotMac::ExtraMemory() const {
216 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
217 return std::vector<const MemorySnapshot*>();
218 }
219
Memory() const220 const ProcessMemory* ProcessSnapshotMac::Memory() const {
221 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
222 return process_reader_.Memory();
223 }
224
InitializeThreads()225 void ProcessSnapshotMac::InitializeThreads() {
226 const std::vector<ProcessReaderMac::Thread>& process_reader_threads =
227 process_reader_.Threads();
228 for (const ProcessReaderMac::Thread& process_reader_thread :
229 process_reader_threads) {
230 auto thread = std::make_unique<internal::ThreadSnapshotMac>();
231 if (thread->Initialize(&process_reader_, process_reader_thread)) {
232 threads_.push_back(std::move(thread));
233 }
234 }
235 }
236
InitializeModules()237 void ProcessSnapshotMac::InitializeModules() {
238 const std::vector<ProcessReaderMac::Module>& process_reader_modules =
239 process_reader_.Modules();
240 for (const ProcessReaderMac::Module& process_reader_module :
241 process_reader_modules) {
242 auto module = std::make_unique<internal::ModuleSnapshotMac>();
243 if (module->Initialize(&process_reader_, process_reader_module)) {
244 modules_.push_back(std::move(module));
245 }
246 }
247 }
248
249 } // namespace crashpad
250