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, |
(...skipping 23 matching lines...) Expand all Loading... | |
34 report_id_(), | 34 report_id_(), |
35 client_id_(), | 35 client_id_(), |
36 annotations_simple_map_(), | 36 annotations_simple_map_(), |
37 snapshot_time_(), | 37 snapshot_time_(), |
38 initialized_() { | 38 initialized_() { |
39 } | 39 } |
40 | 40 |
41 ProcessSnapshotWin::~ProcessSnapshotWin() { | 41 ProcessSnapshotWin::~ProcessSnapshotWin() { |
42 } | 42 } |
43 | 43 |
44 bool ProcessSnapshotWin::Initialize(HANDLE process, | 44 bool ProcessSnapshotWin::Initialize( |
45 ProcessSuspensionState suspension_state) { | 45 HANDLE process, |
46 ProcessSuspensionState suspension_state, | |
47 WinVMAddress debug_critical_section_address) { | |
46 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 48 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
47 | 49 |
48 GetTimeOfDay(&snapshot_time_); | 50 GetTimeOfDay(&snapshot_time_); |
49 | 51 |
50 if (!process_reader_.Initialize(process, suspension_state)) | 52 if (!process_reader_.Initialize(process, suspension_state)) |
51 return false; | 53 return false; |
52 | 54 |
53 system_.Initialize(&process_reader_); | 55 system_.Initialize(&process_reader_); |
54 | 56 |
55 if (process_reader_.Is64Bit()) | 57 if (process_reader_.Is64Bit()) { |
56 InitializePebData<process_types::internal::Traits64>(); | 58 InitializePebData<process_types::internal::Traits64>( |
57 else | 59 debug_critical_section_address); |
58 InitializePebData<process_types::internal::Traits32>(); | 60 } else { |
61 InitializePebData<process_types::internal::Traits32>( | |
62 debug_critical_section_address); | |
63 } | |
59 | 64 |
60 InitializeThreads(); | 65 InitializeThreads(); |
61 InitializeModules(); | 66 InitializeModules(); |
62 | 67 |
63 INITIALIZATION_STATE_SET_VALID(initialized_); | 68 INITIALIZATION_STATE_SET_VALID(initialized_); |
64 return true; | 69 return true; |
65 } | 70 } |
66 | 71 |
67 bool ProcessSnapshotWin::InitializeException( | 72 bool ProcessSnapshotWin::InitializeException( |
68 WinVMAddress exception_information_address) { | 73 WinVMAddress exception_information_address) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 return modules; | 188 return modules; |
184 } | 189 } |
185 | 190 |
186 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { | 191 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { |
187 return exception_.get(); | 192 return exception_.get(); |
188 } | 193 } |
189 | 194 |
190 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { | 195 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { |
191 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 196 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
192 std::vector<const MemorySnapshot*> extra_memory; | 197 std::vector<const MemorySnapshot*> extra_memory; |
193 for (const auto& peb_memory : peb_memory_) | 198 for (const auto& em : extra_memory_) |
194 extra_memory.push_back(peb_memory); | 199 extra_memory.push_back(em); |
195 return extra_memory; | 200 return extra_memory; |
196 } | 201 } |
197 | 202 |
198 void ProcessSnapshotWin::InitializeThreads() { | 203 void ProcessSnapshotWin::InitializeThreads() { |
199 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = | 204 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = |
200 process_reader_.Threads(); | 205 process_reader_.Threads(); |
201 for (const ProcessReaderWin::Thread& process_reader_thread : | 206 for (const ProcessReaderWin::Thread& process_reader_thread : |
202 process_reader_threads) { | 207 process_reader_threads) { |
203 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); | 208 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); |
204 if (thread->Initialize(&process_reader_, process_reader_thread)) { | 209 if (thread->Initialize(&process_reader_, process_reader_thread)) { |
205 threads_.push_back(thread.release()); | 210 threads_.push_back(thread.release()); |
206 } | 211 } |
207 } | 212 } |
208 } | 213 } |
209 | 214 |
210 void ProcessSnapshotWin::InitializeModules() { | 215 void ProcessSnapshotWin::InitializeModules() { |
211 const std::vector<ProcessInfo::Module>& process_reader_modules = | 216 const std::vector<ProcessInfo::Module>& process_reader_modules = |
212 process_reader_.Modules(); | 217 process_reader_.Modules(); |
213 for (const ProcessInfo::Module& process_reader_module : | 218 for (const ProcessInfo::Module& process_reader_module : |
214 process_reader_modules) { | 219 process_reader_modules) { |
215 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); | 220 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); |
216 if (module->Initialize(&process_reader_, process_reader_module)) { | 221 if (module->Initialize(&process_reader_, process_reader_module)) { |
217 modules_.push_back(module.release()); | 222 modules_.push_back(module.release()); |
218 } | 223 } |
219 } | 224 } |
220 } | 225 } |
221 | 226 |
222 template <class Traits> | 227 template <class Traits> |
223 void ProcessSnapshotWin::InitializePebData() { | 228 void ProcessSnapshotWin::InitializePebData( |
229 WinVMAddress debug_critical_section_address) { | |
224 WinVMAddress peb_address; | 230 WinVMAddress peb_address; |
225 WinVMSize peb_size; | 231 WinVMSize peb_size; |
226 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); | 232 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); |
227 AddMemorySnapshot(peb_address, peb_size, &peb_memory_); | 233 AddMemorySnapshot(peb_address, peb_size, &extra_memory_); |
228 | 234 |
229 process_types::PEB<Traits> peb_data; | 235 process_types::PEB<Traits> peb_data; |
230 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { | 236 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { |
231 LOG(ERROR) << "ReadMemory PEB"; | 237 LOG(ERROR) << "ReadMemory PEB"; |
232 return; | 238 return; |
233 } | 239 } |
234 | 240 |
235 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; | 241 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; |
236 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &peb_memory_); | 242 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_); |
237 if (!process_reader_.ReadMemory( | 243 if (!process_reader_.ReadMemory( |
238 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { | 244 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { |
239 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; | 245 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; |
240 } else { | 246 } else { |
241 // Walk the LDR structure to retrieve its pointed-to data. | 247 // Walk the LDR structure to retrieve its pointed-to data. |
242 AddMemorySnapshotForLdrLIST_ENTRY( | 248 AddMemorySnapshotForLdrLIST_ENTRY( |
243 peb_ldr_data.InLoadOrderModuleList, | 249 peb_ldr_data.InLoadOrderModuleList, |
244 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), | 250 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), |
245 &peb_memory_); | 251 &extra_memory_); |
246 AddMemorySnapshotForLdrLIST_ENTRY( | 252 AddMemorySnapshotForLdrLIST_ENTRY( |
247 peb_ldr_data.InMemoryOrderModuleList, | 253 peb_ldr_data.InMemoryOrderModuleList, |
248 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 254 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
249 InMemoryOrderLinks), | 255 InMemoryOrderLinks), |
250 &peb_memory_); | 256 &extra_memory_); |
251 AddMemorySnapshotForLdrLIST_ENTRY( | 257 AddMemorySnapshotForLdrLIST_ENTRY( |
252 peb_ldr_data.InInitializationOrderModuleList, | 258 peb_ldr_data.InInitializationOrderModuleList, |
253 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 259 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
254 InInitializationOrderLinks), | 260 InInitializationOrderLinks), |
255 &peb_memory_); | 261 &extra_memory_); |
256 } | 262 } |
257 | 263 |
258 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; | 264 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; |
259 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, | 265 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, |
260 sizeof(process_parameters), | 266 sizeof(process_parameters), |
261 &process_parameters)) { | 267 &process_parameters)) { |
262 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; | 268 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; |
263 return; | 269 return; |
264 } | 270 } |
265 AddMemorySnapshot( | 271 AddMemorySnapshot( |
266 peb_data.ProcessParameters, sizeof(process_parameters), &peb_memory_); | 272 peb_data.ProcessParameters, sizeof(process_parameters), &extra_memory_); |
267 | 273 |
268 AddMemorySnapshotForUNICODE_STRING( | 274 AddMemorySnapshotForUNICODE_STRING( |
269 process_parameters.CurrentDirectory.DosPath, &peb_memory_); | 275 process_parameters.CurrentDirectory.DosPath, &extra_memory_); |
270 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, &peb_memory_); | 276 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, |
277 &extra_memory_); | |
271 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, | 278 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, |
272 &peb_memory_); | 279 &extra_memory_); |
273 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, | 280 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, |
274 &peb_memory_); | 281 &extra_memory_); |
275 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, | 282 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, |
276 &peb_memory_); | 283 &extra_memory_); |
277 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, | 284 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, |
278 &peb_memory_); | 285 &extra_memory_); |
279 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, | 286 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, |
280 &peb_memory_); | 287 &extra_memory_); |
281 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, | 288 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, |
282 &peb_memory_); | 289 &extra_memory_); |
283 AddMemorySnapshot( | 290 AddMemorySnapshot( |
284 process_parameters.Environment, | 291 process_parameters.Environment, |
285 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), | 292 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), |
286 &peb_memory_); | 293 &extra_memory_); |
294 | |
295 // Walk the loader lock which is directly referenced by the PEB. It may or may | |
296 // not have a .DebugInfo list, but typically doesn't. If it does, then we may | |
297 // walk the lock list more than once, but AddMemorySnapshot() will take care | |
298 // of deduplicating the added regions. | |
299 ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); | |
300 | |
301 // Traverse the locks with valid .DebugInfo if a starting point was supplied. | |
302 if (debug_critical_section_address) | |
303 ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); | |
287 } | 304 } |
288 | 305 |
289 void ProcessSnapshotWin::AddMemorySnapshot( | 306 void ProcessSnapshotWin::AddMemorySnapshot( |
290 WinVMAddress address, | 307 WinVMAddress address, |
291 WinVMSize size, | 308 WinVMSize size, |
292 PointerVector<internal::MemorySnapshotWin>* into) { | 309 PointerVector<internal::MemorySnapshotWin>* into) { |
293 if (size == 0) | 310 if (size == 0) |
294 return; | 311 return; |
295 | 312 |
296 // Ensure that the entire range is readable. TODO(scottmg): Consider | 313 // Ensure that the entire range is readable. TODO(scottmg): Consider |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 env_block.resize( | 394 env_block.resize( |
378 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); | 395 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); |
379 const wchar_t terminator[] = { 0, 0 }; | 396 const wchar_t terminator[] = { 0, 0 }; |
380 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); | 397 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); |
381 if (at != std::wstring::npos) | 398 if (at != std::wstring::npos) |
382 env_block.resize(at + arraysize(terminator)); | 399 env_block.resize(at + arraysize(terminator)); |
383 | 400 |
384 return env_block.size() * sizeof(env_block[0]); | 401 return env_block.size() * sizeof(env_block[0]); |
385 } | 402 } |
386 | 403 |
404 template <class Traits> | |
405 void ProcessSnapshotWin::ReadLocks( | |
406 WinVMAddress start, | |
407 PointerVector<internal::MemorySnapshotWin>* into) { | |
408 // We're walking the RTL_CRITICAL_SECTION_DEBUG ProcessLocksList, but starting | |
409 // from an actual RTL_CRITICAL_SECTION, so start by getting to the first | |
410 // RTL_CRITICAL_SECTION_DEBUG. | |
411 | |
412 process_types::RTL_CRITICAL_SECTION<Traits> critical_section; | |
413 if (!process_reader_.ReadMemory( | |
414 start, sizeof(critical_section), &critical_section)) { | |
415 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION"; | |
416 return; | |
417 } | |
418 | |
419 const decltype(critical_section.DebugInfo) kInvalid = | |
420 static_cast<decltype(critical_section.DebugInfo)>(-1); | |
421 if (critical_section.DebugInfo == kInvalid) | |
422 return; | |
423 | |
424 WinVMAddress current = critical_section.DebugInfo; | |
425 do { | |
426 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | |
427 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | |
428 if (!process_reader_.ReadMemory( | |
429 current, sizeof(critical_section_debug), &critical_section_debug)) { | |
430 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; | |
431 return; | |
432 } | |
433 | |
434 // Add both RTL_CRITICAL_SECTION_DEBUG and RTL_CRITICAL_SECTION_DEBUG to the | |
Mark Mentovai
2015/10/12 14:08:59
One of these shouldn’t be _DEBUG.
| |
435 // extra memory to be saved. | |
436 AddMemorySnapshot(current, | |
437 sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>), | |
438 into); | |
439 AddMemorySnapshot(critical_section_debug.CriticalSection, | |
440 sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), | |
441 into); | |
442 | |
443 if (critical_section_debug.ProcessLocksList.Flink == 0) | |
444 break; | |
445 | |
446 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking | |
447 // ProcessLocksList.Flink. | |
448 current = critical_section_debug.ProcessLocksList.Flink - | |
449 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | |
450 ProcessLocksList); | |
451 } while (current != critical_section.DebugInfo && current != kInvalid); | |
452 } | |
453 | |
387 } // namespace crashpad | 454 } // namespace crashpad |
OLD | NEW |