OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "snapshot/minidump/process_snapshot_minidump.h" | 15 #include "snapshot/minidump/process_snapshot_minidump.h" |
16 | 16 |
| 17 #include <utility> |
| 18 |
| 19 #include "base/memory/scoped_ptr.h" |
17 #include "util/file/file_io.h" | 20 #include "util/file/file_io.h" |
18 #include "snapshot/minidump/minidump_simple_string_dictionary_reader.h" | 21 #include "snapshot/minidump/minidump_simple_string_dictionary_reader.h" |
19 | 22 |
20 namespace crashpad { | 23 namespace crashpad { |
21 | 24 |
22 ProcessSnapshotMinidump::ProcessSnapshotMinidump() | 25 ProcessSnapshotMinidump::ProcessSnapshotMinidump() |
23 : ProcessSnapshot(), | 26 : ProcessSnapshot(), |
24 header_(), | 27 header_(), |
25 stream_directory_(), | 28 stream_directory_(), |
26 stream_map_(), | 29 stream_map_(), |
| 30 modules_(), |
27 crashpad_info_(), | 31 crashpad_info_(), |
28 annotations_simple_map_(), | 32 annotations_simple_map_(), |
29 file_reader_(nullptr), | 33 file_reader_(nullptr), |
30 initialized_() { | 34 initialized_() { |
31 } | 35 } |
32 | 36 |
33 ProcessSnapshotMinidump::~ProcessSnapshotMinidump() { | 37 ProcessSnapshotMinidump::~ProcessSnapshotMinidump() { |
34 } | 38 } |
35 | 39 |
36 bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) { | 40 bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 if (stream_map_.find(stream_type) != stream_map_.end()) { | 77 if (stream_map_.find(stream_type) != stream_map_.end()) { |
74 LOG(ERROR) << "duplicate streams for type " << directory.StreamType; | 78 LOG(ERROR) << "duplicate streams for type " << directory.StreamType; |
75 return false; | 79 return false; |
76 } | 80 } |
77 | 81 |
78 stream_map_[stream_type] = &directory.Location; | 82 stream_map_[stream_type] = &directory.Location; |
79 } | 83 } |
80 | 84 |
81 INITIALIZATION_STATE_SET_VALID(initialized_); | 85 INITIALIZATION_STATE_SET_VALID(initialized_); |
82 | 86 |
83 InitializeCrashpadInfo(); | 87 if (!InitializeCrashpadInfo()) { |
| 88 return false; |
| 89 } |
84 | 90 |
85 return true; | 91 return InitializeModules(); |
86 } | 92 } |
87 | 93 |
88 pid_t ProcessSnapshotMinidump::ProcessID() const { | 94 pid_t ProcessSnapshotMinidump::ProcessID() const { |
89 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 95 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
90 NOTREACHED(); | 96 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
91 return 0; | 97 return 0; |
92 } | 98 } |
93 | 99 |
94 pid_t ProcessSnapshotMinidump::ParentProcessID() const { | 100 pid_t ProcessSnapshotMinidump::ParentProcessID() const { |
95 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 101 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
96 NOTREACHED(); | 102 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
97 return 0; | 103 return 0; |
98 } | 104 } |
99 | 105 |
100 void ProcessSnapshotMinidump::SnapshotTime(timeval* snapshot_time) const { | 106 void ProcessSnapshotMinidump::SnapshotTime(timeval* snapshot_time) const { |
101 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 107 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
102 NOTREACHED(); | 108 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
103 snapshot_time->tv_sec = 0; | 109 snapshot_time->tv_sec = 0; |
104 snapshot_time->tv_usec = 0; | 110 snapshot_time->tv_usec = 0; |
105 } | 111 } |
106 | 112 |
107 void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const { | 113 void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const { |
108 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 114 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
109 NOTREACHED(); | 115 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
110 start_time->tv_sec = 0; | 116 start_time->tv_sec = 0; |
111 start_time->tv_usec = 0; | 117 start_time->tv_usec = 0; |
112 } | 118 } |
113 | 119 |
114 void ProcessSnapshotMinidump::ProcessCPUTimes(timeval* user_time, | 120 void ProcessSnapshotMinidump::ProcessCPUTimes(timeval* user_time, |
115 timeval* system_time) const { | 121 timeval* system_time) const { |
116 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 122 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
117 NOTREACHED(); | 123 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
118 user_time->tv_sec = 0; | 124 user_time->tv_sec = 0; |
119 user_time->tv_usec = 0; | 125 user_time->tv_usec = 0; |
120 system_time->tv_sec = 0; | 126 system_time->tv_sec = 0; |
121 system_time->tv_usec = 0; | 127 system_time->tv_usec = 0; |
122 } | 128 } |
123 | 129 |
124 const std::map<std::string, std::string>& | 130 const std::map<std::string, std::string>& |
125 ProcessSnapshotMinidump::AnnotationsSimpleMap() const { | 131 ProcessSnapshotMinidump::AnnotationsSimpleMap() const { |
126 // TODO(mark): This method should not be const, although the interface | 132 // TODO(mark): This method should not be const, although the interface |
127 // currently imposes this requirement. Making it non-const would allow | 133 // currently imposes this requirement. Making it non-const would allow |
128 // annotations_simple_map_ to be lazily constructed: InitializeCrashpadInfo() | 134 // annotations_simple_map_ to be lazily constructed: InitializeCrashpadInfo() |
129 // could be called here, and from other locations that require it, rather than | 135 // could be called here, and from other locations that require it, rather than |
130 // calling it from Initialize(). | 136 // calling it from Initialize(). |
| 137 // https://code.google.com/p/crashpad/issues/detail?id=9 |
131 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 138 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
132 return annotations_simple_map_; | 139 return annotations_simple_map_; |
133 } | 140 } |
134 | 141 |
135 const SystemSnapshot* ProcessSnapshotMinidump::System() const { | 142 const SystemSnapshot* ProcessSnapshotMinidump::System() const { |
136 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 143 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
137 NOTREACHED(); | 144 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
138 return nullptr; | 145 return nullptr; |
139 } | 146 } |
140 | 147 |
141 std::vector<const ThreadSnapshot*> ProcessSnapshotMinidump::Threads() const { | 148 std::vector<const ThreadSnapshot*> ProcessSnapshotMinidump::Threads() const { |
142 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 149 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
143 NOTREACHED(); | 150 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
144 return std::vector<const ThreadSnapshot*>(); | 151 return std::vector<const ThreadSnapshot*>(); |
145 } | 152 } |
146 | 153 |
147 std::vector<const ModuleSnapshot*> ProcessSnapshotMinidump::Modules() const { | 154 std::vector<const ModuleSnapshot*> ProcessSnapshotMinidump::Modules() const { |
148 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 155 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
149 NOTREACHED(); | 156 std::vector<const ModuleSnapshot*> modules; |
150 return std::vector<const ModuleSnapshot*>(); | 157 for (internal::ModuleSnapshotMinidump* module : modules_) { |
| 158 modules.push_back(module); |
| 159 } |
| 160 return modules; |
151 } | 161 } |
152 | 162 |
153 const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const { | 163 const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const { |
154 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 164 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
155 NOTREACHED(); | 165 NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10 |
156 return nullptr; | 166 return nullptr; |
157 } | 167 } |
158 | 168 |
159 void ProcessSnapshotMinidump::InitializeCrashpadInfo() { | 169 bool ProcessSnapshotMinidump::InitializeCrashpadInfo() { |
160 const auto& it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo); | 170 const auto& stream_it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo); |
161 if (it == stream_map_.end()) { | 171 if (stream_it == stream_map_.end()) { |
162 return; | 172 return true; |
163 } | 173 } |
164 | 174 |
165 if (it->second->DataSize < sizeof(crashpad_info_)) { | 175 if (stream_it->second->DataSize < sizeof(crashpad_info_)) { |
166 LOG(ERROR) << "crashpad_info size mismatch"; | 176 LOG(ERROR) << "crashpad_info size mismatch"; |
167 return; | 177 return false; |
168 } | 178 } |
169 | 179 |
170 if (!file_reader_->SeekSet(it->second->Rva)) { | 180 if (!file_reader_->SeekSet(stream_it->second->Rva)) { |
171 return; | 181 return false; |
172 } | 182 } |
173 | 183 |
174 if (!file_reader_->ReadExactly(&crashpad_info_, sizeof(crashpad_info_))) { | 184 if (!file_reader_->ReadExactly(&crashpad_info_, sizeof(crashpad_info_))) { |
175 return; | 185 return false; |
176 } | 186 } |
177 | 187 |
178 if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) { | 188 if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) { |
179 LOG(ERROR) << "crashpad_info version mismatch"; | 189 LOG(ERROR) << "crashpad_info version mismatch"; |
180 return; | 190 return false; |
181 } | 191 } |
182 | 192 |
183 internal::ReadMinidumpSimpleStringDictionary( | 193 return internal::ReadMinidumpSimpleStringDictionary( |
184 file_reader_, | 194 file_reader_, |
185 crashpad_info_.simple_annotations, | 195 crashpad_info_.simple_annotations, |
186 &annotations_simple_map_); | 196 &annotations_simple_map_); |
187 } | 197 } |
188 | 198 |
| 199 bool ProcessSnapshotMinidump::InitializeModules() { |
| 200 const auto& stream_it = stream_map_.find(kMinidumpStreamTypeModuleList); |
| 201 if (stream_it == stream_map_.end()) { |
| 202 return true; |
| 203 } |
| 204 |
| 205 std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR> module_crashpad_info_links; |
| 206 if (!InitializeModulesCrashpadInfo(&module_crashpad_info_links)) { |
| 207 return false; |
| 208 } |
| 209 |
| 210 if (stream_it->second->DataSize < sizeof(MINIDUMP_MODULE_LIST)) { |
| 211 LOG(ERROR) << "module_list size mismatch"; |
| 212 return false; |
| 213 } |
| 214 |
| 215 if (!file_reader_->SeekSet(stream_it->second->Rva)) { |
| 216 return false; |
| 217 } |
| 218 |
| 219 uint32_t module_count; |
| 220 if (!file_reader_->ReadExactly(&module_count, sizeof(module_count))) { |
| 221 return false; |
| 222 } |
| 223 |
| 224 if (sizeof(MINIDUMP_MODULE_LIST) + module_count * sizeof(MINIDUMP_MODULE) != |
| 225 stream_it->second->DataSize) { |
| 226 LOG(ERROR) << "module_list size mismatch"; |
| 227 return false; |
| 228 } |
| 229 |
| 230 for (uint32_t module_index = 0; module_index < module_count; ++module_index) { |
| 231 const RVA module_rva = stream_it->second->Rva + sizeof(module_count) + |
| 232 module_index * sizeof(MINIDUMP_MODULE); |
| 233 |
| 234 const auto& module_crashpad_info_it = |
| 235 module_crashpad_info_links.find(module_index); |
| 236 const MINIDUMP_LOCATION_DESCRIPTOR* module_crashpad_info_location = |
| 237 module_crashpad_info_it != module_crashpad_info_links.end() |
| 238 ? &module_crashpad_info_it->second |
| 239 : nullptr; |
| 240 |
| 241 auto module = make_scoped_ptr(new internal::ModuleSnapshotMinidump()); |
| 242 if (!module->Initialize( |
| 243 file_reader_, module_rva, module_crashpad_info_location)) { |
| 244 return false; |
| 245 } |
| 246 |
| 247 modules_.push_back(module.release()); |
| 248 } |
| 249 |
| 250 return true; |
| 251 } |
| 252 |
| 253 bool ProcessSnapshotMinidump::InitializeModulesCrashpadInfo( |
| 254 std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR>* |
| 255 module_crashpad_info_links) { |
| 256 module_crashpad_info_links->clear(); |
| 257 |
| 258 if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) { |
| 259 return false; |
| 260 } |
| 261 |
| 262 if (crashpad_info_.module_list.Rva == 0) { |
| 263 return true; |
| 264 } |
| 265 |
| 266 if (crashpad_info_.module_list.DataSize < |
| 267 sizeof(MinidumpModuleCrashpadInfoList)) { |
| 268 LOG(ERROR) << "module_crashpad_info_list size mismatch"; |
| 269 return false; |
| 270 } |
| 271 |
| 272 if (!file_reader_->SeekSet(crashpad_info_.module_list.Rva)) { |
| 273 return false; |
| 274 } |
| 275 |
| 276 uint32_t crashpad_module_count; |
| 277 if (!file_reader_->ReadExactly(&crashpad_module_count, |
| 278 sizeof(crashpad_module_count))) { |
| 279 return false; |
| 280 } |
| 281 |
| 282 if (crashpad_info_.module_list.DataSize != |
| 283 sizeof(MinidumpModuleCrashpadInfoList) + |
| 284 crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink)) { |
| 285 LOG(ERROR) << "module_crashpad_info_list size mismatch"; |
| 286 return false; |
| 287 } |
| 288 |
| 289 scoped_ptr<MinidumpModuleCrashpadInfoLink[]> minidump_links( |
| 290 new MinidumpModuleCrashpadInfoLink[crashpad_module_count]); |
| 291 if (!file_reader_->ReadExactly( |
| 292 &minidump_links[0], |
| 293 crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink))) { |
| 294 return false; |
| 295 } |
| 296 |
| 297 for (uint32_t crashpad_module_index = 0; |
| 298 crashpad_module_index < crashpad_module_count; |
| 299 ++crashpad_module_index) { |
| 300 const MinidumpModuleCrashpadInfoLink& minidump_link = |
| 301 minidump_links[crashpad_module_index]; |
| 302 if (module_crashpad_info_links->find( |
| 303 minidump_link.minidump_module_list_index) != |
| 304 module_crashpad_info_links->end()) { |
| 305 LOG(WARNING) |
| 306 << "duplicate module_crashpad_info_list minidump_module_list_index " |
| 307 << minidump_link.minidump_module_list_index; |
| 308 return false; |
| 309 } else { |
| 310 module_crashpad_info_links->insert(std::make_pair( |
| 311 minidump_link.minidump_module_list_index, minidump_link.location)); |
| 312 } |
| 313 } |
| 314 |
| 315 return true; |
| 316 } |
| 317 |
189 } // namespace crashpad | 318 } // namespace crashpad |
OLD | NEW |