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 25 matching lines...) Expand all Loading... |
36 report_id_(), | 36 report_id_(), |
37 client_id_(), | 37 client_id_(), |
38 annotations_simple_map_(), | 38 annotations_simple_map_(), |
39 snapshot_time_(), | 39 snapshot_time_(), |
40 initialized_() { | 40 initialized_() { |
41 } | 41 } |
42 | 42 |
43 ProcessSnapshotWin::~ProcessSnapshotWin() { | 43 ProcessSnapshotWin::~ProcessSnapshotWin() { |
44 } | 44 } |
45 | 45 |
46 bool ProcessSnapshotWin::Initialize(HANDLE process, | 46 bool ProcessSnapshotWin::Initialize( |
47 ProcessSuspensionState suspension_state) { | 47 HANDLE process, |
| 48 ProcessSuspensionState suspension_state, |
| 49 WinVMAddress debug_critical_section_address) { |
48 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 50 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
49 | 51 |
50 GetTimeOfDay(&snapshot_time_); | 52 GetTimeOfDay(&snapshot_time_); |
51 | 53 |
52 if (!process_reader_.Initialize(process, suspension_state)) | 54 if (!process_reader_.Initialize(process, suspension_state)) |
53 return false; | 55 return false; |
54 | 56 |
55 system_.Initialize(&process_reader_); | 57 system_.Initialize(&process_reader_); |
56 | 58 |
57 if (process_reader_.Is64Bit()) | 59 if (process_reader_.Is64Bit()) { |
58 InitializePebData<process_types::internal::Traits64>(); | 60 InitializePebData<process_types::internal::Traits64>( |
59 else | 61 debug_critical_section_address); |
60 InitializePebData<process_types::internal::Traits32>(); | 62 } else { |
| 63 InitializePebData<process_types::internal::Traits32>( |
| 64 debug_critical_section_address); |
| 65 } |
61 | 66 |
62 InitializeThreads(); | 67 InitializeThreads(); |
63 InitializeModules(); | 68 InitializeModules(); |
64 | 69 |
65 for (const MEMORY_BASIC_INFORMATION64& mbi : | 70 for (const MEMORY_BASIC_INFORMATION64& mbi : |
66 process_reader_.GetProcessInfo().MemoryInfo()) { | 71 process_reader_.GetProcessInfo().MemoryInfo()) { |
67 memory_map_.push_back(new internal::MemoryMapRegionSnapshotWin(mbi)); | 72 memory_map_.push_back(new internal::MemoryMapRegionSnapshotWin(mbi)); |
68 } | 73 } |
69 | 74 |
70 INITIALIZATION_STATE_SET_VALID(initialized_); | 75 INITIALIZATION_STATE_SET_VALID(initialized_); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 const { | 203 const { |
199 std::vector<const MemoryMapRegionSnapshot*> memory_map; | 204 std::vector<const MemoryMapRegionSnapshot*> memory_map; |
200 for (const auto& item : memory_map_) | 205 for (const auto& item : memory_map_) |
201 memory_map.push_back(item); | 206 memory_map.push_back(item); |
202 return memory_map; | 207 return memory_map; |
203 } | 208 } |
204 | 209 |
205 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { | 210 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { |
206 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 211 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
207 std::vector<const MemorySnapshot*> extra_memory; | 212 std::vector<const MemorySnapshot*> extra_memory; |
208 for (const auto& peb_memory : peb_memory_) | 213 for (const auto& em : extra_memory_) |
209 extra_memory.push_back(peb_memory); | 214 extra_memory.push_back(em); |
210 return extra_memory; | 215 return extra_memory; |
211 } | 216 } |
212 | 217 |
213 void ProcessSnapshotWin::InitializeThreads() { | 218 void ProcessSnapshotWin::InitializeThreads() { |
214 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = | 219 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = |
215 process_reader_.Threads(); | 220 process_reader_.Threads(); |
216 for (const ProcessReaderWin::Thread& process_reader_thread : | 221 for (const ProcessReaderWin::Thread& process_reader_thread : |
217 process_reader_threads) { | 222 process_reader_threads) { |
218 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); | 223 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); |
219 if (thread->Initialize(&process_reader_, process_reader_thread)) { | 224 if (thread->Initialize(&process_reader_, process_reader_thread)) { |
220 threads_.push_back(thread.release()); | 225 threads_.push_back(thread.release()); |
221 } | 226 } |
222 } | 227 } |
223 } | 228 } |
224 | 229 |
225 void ProcessSnapshotWin::InitializeModules() { | 230 void ProcessSnapshotWin::InitializeModules() { |
226 const std::vector<ProcessInfo::Module>& process_reader_modules = | 231 const std::vector<ProcessInfo::Module>& process_reader_modules = |
227 process_reader_.Modules(); | 232 process_reader_.Modules(); |
228 for (const ProcessInfo::Module& process_reader_module : | 233 for (const ProcessInfo::Module& process_reader_module : |
229 process_reader_modules) { | 234 process_reader_modules) { |
230 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); | 235 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); |
231 if (module->Initialize(&process_reader_, process_reader_module)) { | 236 if (module->Initialize(&process_reader_, process_reader_module)) { |
232 modules_.push_back(module.release()); | 237 modules_.push_back(module.release()); |
233 } | 238 } |
234 } | 239 } |
235 } | 240 } |
236 | 241 |
237 template <class Traits> | 242 template <class Traits> |
238 void ProcessSnapshotWin::InitializePebData() { | 243 void ProcessSnapshotWin::InitializePebData( |
| 244 WinVMAddress debug_critical_section_address) { |
239 WinVMAddress peb_address; | 245 WinVMAddress peb_address; |
240 WinVMSize peb_size; | 246 WinVMSize peb_size; |
241 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); | 247 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); |
242 AddMemorySnapshot(peb_address, peb_size, &peb_memory_); | 248 AddMemorySnapshot(peb_address, peb_size, &extra_memory_); |
243 | 249 |
244 process_types::PEB<Traits> peb_data; | 250 process_types::PEB<Traits> peb_data; |
245 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { | 251 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { |
246 LOG(ERROR) << "ReadMemory PEB"; | 252 LOG(ERROR) << "ReadMemory PEB"; |
247 return; | 253 return; |
248 } | 254 } |
249 | 255 |
250 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; | 256 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; |
251 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &peb_memory_); | 257 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_); |
252 if (!process_reader_.ReadMemory( | 258 if (!process_reader_.ReadMemory( |
253 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { | 259 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { |
254 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; | 260 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; |
255 } else { | 261 } else { |
256 // Walk the LDR structure to retrieve its pointed-to data. | 262 // Walk the LDR structure to retrieve its pointed-to data. |
257 AddMemorySnapshotForLdrLIST_ENTRY( | 263 AddMemorySnapshotForLdrLIST_ENTRY( |
258 peb_ldr_data.InLoadOrderModuleList, | 264 peb_ldr_data.InLoadOrderModuleList, |
259 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), | 265 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), |
260 &peb_memory_); | 266 &extra_memory_); |
261 AddMemorySnapshotForLdrLIST_ENTRY( | 267 AddMemorySnapshotForLdrLIST_ENTRY( |
262 peb_ldr_data.InMemoryOrderModuleList, | 268 peb_ldr_data.InMemoryOrderModuleList, |
263 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 269 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
264 InMemoryOrderLinks), | 270 InMemoryOrderLinks), |
265 &peb_memory_); | 271 &extra_memory_); |
266 AddMemorySnapshotForLdrLIST_ENTRY( | 272 AddMemorySnapshotForLdrLIST_ENTRY( |
267 peb_ldr_data.InInitializationOrderModuleList, | 273 peb_ldr_data.InInitializationOrderModuleList, |
268 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 274 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
269 InInitializationOrderLinks), | 275 InInitializationOrderLinks), |
270 &peb_memory_); | 276 &extra_memory_); |
271 } | 277 } |
272 | 278 |
273 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; | 279 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; |
274 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, | 280 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, |
275 sizeof(process_parameters), | 281 sizeof(process_parameters), |
276 &process_parameters)) { | 282 &process_parameters)) { |
277 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; | 283 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; |
278 return; | 284 return; |
279 } | 285 } |
280 AddMemorySnapshot( | 286 AddMemorySnapshot( |
281 peb_data.ProcessParameters, sizeof(process_parameters), &peb_memory_); | 287 peb_data.ProcessParameters, sizeof(process_parameters), &extra_memory_); |
282 | 288 |
283 AddMemorySnapshotForUNICODE_STRING( | 289 AddMemorySnapshotForUNICODE_STRING( |
284 process_parameters.CurrentDirectory.DosPath, &peb_memory_); | 290 process_parameters.CurrentDirectory.DosPath, &extra_memory_); |
285 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, &peb_memory_); | 291 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, |
| 292 &extra_memory_); |
286 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, | 293 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, |
287 &peb_memory_); | 294 &extra_memory_); |
288 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, | 295 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, |
289 &peb_memory_); | 296 &extra_memory_); |
290 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, | 297 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, |
291 &peb_memory_); | 298 &extra_memory_); |
292 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, | 299 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, |
293 &peb_memory_); | 300 &extra_memory_); |
294 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, | 301 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, |
295 &peb_memory_); | 302 &extra_memory_); |
296 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, | 303 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, |
297 &peb_memory_); | 304 &extra_memory_); |
298 AddMemorySnapshot( | 305 AddMemorySnapshot( |
299 process_parameters.Environment, | 306 process_parameters.Environment, |
300 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), | 307 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), |
301 &peb_memory_); | 308 &extra_memory_); |
| 309 |
| 310 // Walk the loader lock which is directly referenced by the PEB. It may or may |
| 311 // not have a .DebugInfo list, but doesn't on more recent OSs (it does on |
| 312 // Vista). If it does, then we may walk the lock list more than once, but |
| 313 // AddMemorySnapshot() will take care of deduplicating the added regions. |
| 314 ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); |
| 315 |
| 316 // Traverse the locks with valid .DebugInfo if a starting point was supplied. |
| 317 if (debug_critical_section_address) |
| 318 ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); |
302 } | 319 } |
303 | 320 |
304 void ProcessSnapshotWin::AddMemorySnapshot( | 321 void ProcessSnapshotWin::AddMemorySnapshot( |
305 WinVMAddress address, | 322 WinVMAddress address, |
306 WinVMSize size, | 323 WinVMSize size, |
307 PointerVector<internal::MemorySnapshotWin>* into) { | 324 PointerVector<internal::MemorySnapshotWin>* into) { |
308 if (size == 0) | 325 if (size == 0) |
309 return; | 326 return; |
310 | 327 |
311 // Ensure that the entire range is readable. TODO(scottmg): Consider | 328 // Ensure that the entire range is readable. TODO(scottmg): Consider |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 env_block.resize( | 409 env_block.resize( |
393 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); | 410 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); |
394 const wchar_t terminator[] = { 0, 0 }; | 411 const wchar_t terminator[] = { 0, 0 }; |
395 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); | 412 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); |
396 if (at != std::wstring::npos) | 413 if (at != std::wstring::npos) |
397 env_block.resize(at + arraysize(terminator)); | 414 env_block.resize(at + arraysize(terminator)); |
398 | 415 |
399 return env_block.size() * sizeof(env_block[0]); | 416 return env_block.size() * sizeof(env_block[0]); |
400 } | 417 } |
401 | 418 |
| 419 template <class Traits> |
| 420 void ProcessSnapshotWin::ReadLocks( |
| 421 WinVMAddress start, |
| 422 PointerVector<internal::MemorySnapshotWin>* into) { |
| 423 // We're walking the RTL_CRITICAL_SECTION_DEBUG ProcessLocksList, but starting |
| 424 // from an actual RTL_CRITICAL_SECTION, so start by getting to the first |
| 425 // RTL_CRITICAL_SECTION_DEBUG. |
| 426 |
| 427 process_types::RTL_CRITICAL_SECTION<Traits> critical_section; |
| 428 if (!process_reader_.ReadMemory( |
| 429 start, sizeof(critical_section), &critical_section)) { |
| 430 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION"; |
| 431 return; |
| 432 } |
| 433 |
| 434 const decltype(critical_section.DebugInfo) kInvalid = |
| 435 static_cast<decltype(critical_section.DebugInfo)>(-1); |
| 436 if (critical_section.DebugInfo == kInvalid) |
| 437 return; |
| 438 |
| 439 const WinVMAddress start_address_backward = critical_section.DebugInfo; |
| 440 WinVMAddress current_address = start_address_backward; |
| 441 WinVMAddress last_good_address; |
| 442 |
| 443 // Typically, this seems to be a circular list, but it's not clear that it |
| 444 // always is, so follow Blink fields back to the head (or where we started) |
| 445 // before following Flink to capture memory. |
| 446 do { |
| 447 last_good_address = current_address; |
| 448 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
| 449 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
| 450 if (!process_reader_.ReadMemory(current_address, |
| 451 sizeof(critical_section_debug), |
| 452 &critical_section_debug)) { |
| 453 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; |
| 454 return; |
| 455 } |
| 456 |
| 457 if (critical_section_debug.ProcessLocksList.Blink == 0) { |
| 458 // At the head of the list. |
| 459 break; |
| 460 } |
| 461 |
| 462 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking |
| 463 // ProcessLocksList.Blink. |
| 464 current_address = |
| 465 critical_section_debug.ProcessLocksList.Blink - |
| 466 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
| 467 ProcessLocksList); |
| 468 } while (current_address != start_address_backward && |
| 469 current_address != kInvalid); |
| 470 |
| 471 if (current_address == kInvalid) { |
| 472 // Unexpectedly encountered a bad record, so step back one. |
| 473 current_address = last_good_address; |
| 474 } |
| 475 |
| 476 const WinVMAddress start_address_forward = current_address; |
| 477 |
| 478 // current_address is now the head of the list, walk Flink to add the whole |
| 479 // list. |
| 480 do { |
| 481 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
| 482 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
| 483 if (!process_reader_.ReadMemory(current_address, |
| 484 sizeof(critical_section_debug), |
| 485 &critical_section_debug)) { |
| 486 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; |
| 487 return; |
| 488 } |
| 489 |
| 490 // Add both RTL_CRITICAL_SECTION_DEBUG and RTL_CRITICAL_SECTION to the extra |
| 491 // memory to be saved. |
| 492 AddMemorySnapshot(current_address, |
| 493 sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>), |
| 494 into); |
| 495 AddMemorySnapshot(critical_section_debug.CriticalSection, |
| 496 sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), |
| 497 into); |
| 498 |
| 499 if (critical_section_debug.ProcessLocksList.Flink == 0) |
| 500 break; |
| 501 |
| 502 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking |
| 503 // ProcessLocksList.Flink. |
| 504 current_address = |
| 505 critical_section_debug.ProcessLocksList.Flink - |
| 506 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
| 507 ProcessLocksList); |
| 508 } while (current_address != start_address_forward && |
| 509 current_address != kInvalid); |
| 510 } |
| 511 |
402 } // namespace crashpad | 512 } // namespace crashpad |
OLD | NEW |