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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 &extra_memory_); | 323 &extra_memory_); |
324 AddMemorySnapshot( | 324 AddMemorySnapshot( |
325 process_parameters.Environment, | 325 process_parameters.Environment, |
326 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), | 326 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), |
327 &extra_memory_); | 327 &extra_memory_); |
328 | 328 |
329 // Walk the loader lock which is directly referenced by the PEB. It may or may | 329 // Walk the loader lock which is directly referenced by the PEB. It may or may |
330 // not have a .DebugInfo list, but doesn't on more recent OSs (it does on | 330 // not have a .DebugInfo list, but doesn't on more recent OSs (it does on |
331 // Vista). If it does, then we may walk the lock list more than once, but | 331 // Vista). If it does, then we may walk the lock list more than once, but |
332 // AddMemorySnapshot() will take care of deduplicating the added regions. | 332 // AddMemorySnapshot() will take care of deduplicating the added regions. |
333 ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); | 333 ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); |
Mark Mentovai
2015/11/30 18:32:06
If we really only care about the loader lock, mayb
| |
334 | 334 |
335 // Traverse the locks with valid .DebugInfo if a starting point was supplied. | 335 // Traverse the locks with valid .DebugInfo if a starting point was supplied. |
336 if (debug_critical_section_address) | 336 if (debug_critical_section_address) |
337 ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); | 337 ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); |
338 } | 338 } |
339 | 339 |
340 void ProcessSnapshotWin::AddMemorySnapshot( | 340 void ProcessSnapshotWin::AddMemorySnapshot( |
341 WinVMAddress address, | 341 WinVMAddress address, |
342 WinVMSize size, | 342 WinVMSize size, |
343 PointerVector<internal::MemorySnapshotWin>* into) { | 343 PointerVector<internal::MemorySnapshotWin>* into) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 | 441 |
442 const decltype(critical_section.DebugInfo) kInvalid = | 442 const decltype(critical_section.DebugInfo) kInvalid = |
443 static_cast<decltype(critical_section.DebugInfo)>(-1); | 443 static_cast<decltype(critical_section.DebugInfo)>(-1); |
444 if (critical_section.DebugInfo == kInvalid) | 444 if (critical_section.DebugInfo == kInvalid) |
445 return; | 445 return; |
446 | 446 |
447 const WinVMAddress start_address_backward = critical_section.DebugInfo; | 447 const WinVMAddress start_address_backward = critical_section.DebugInfo; |
448 WinVMAddress current_address = start_address_backward; | 448 WinVMAddress current_address = start_address_backward; |
449 WinVMAddress last_good_address; | 449 WinVMAddress last_good_address; |
450 | 450 |
451 // Cap the list of locks we capture arbitrarily so we don't walk forever. | |
452 const int kMaxWalkLength = 100; | |
Mark Mentovai
2015/11/30 18:32:06
…and maybe we should just grab the loader lock her
| |
453 int walk_count = 0; | |
454 | |
451 // Typically, this seems to be a circular list, but it's not clear that it | 455 // Typically, this seems to be a circular list, but it's not clear that it |
452 // always is, so follow Blink fields back to the head (or where we started) | 456 // always is, so follow Blink fields back to the head (or where we started) |
453 // before following Flink to capture memory. | 457 // before following Flink to capture memory. |
454 do { | 458 do { |
455 last_good_address = current_address; | 459 last_good_address = current_address; |
456 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | 460 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
457 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | 461 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
458 if (!process_reader_.ReadMemory(current_address, | 462 if (!process_reader_.ReadMemory(current_address, |
459 sizeof(critical_section_debug), | 463 sizeof(critical_section_debug), |
460 &critical_section_debug)) { | 464 &critical_section_debug)) { |
461 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; | 465 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; |
462 return; | 466 return; |
463 } | 467 } |
464 | 468 |
465 if (critical_section_debug.ProcessLocksList.Blink == 0) { | 469 if (critical_section_debug.ProcessLocksList.Blink == 0) { |
466 // At the head of the list. | 470 // At the head of the list. |
467 break; | 471 break; |
468 } | 472 } |
469 | 473 |
470 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking | 474 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking |
471 // ProcessLocksList.Blink. | 475 // ProcessLocksList.Blink. |
472 current_address = | 476 current_address = |
473 critical_section_debug.ProcessLocksList.Blink - | 477 critical_section_debug.ProcessLocksList.Blink - |
474 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | 478 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
475 ProcessLocksList); | 479 ProcessLocksList); |
480 walk_count++; | |
481 if (walk_count == kMaxWalkLength) | |
482 break; | |
476 } while (current_address != start_address_backward && | 483 } while (current_address != start_address_backward && |
477 current_address != kInvalid); | 484 current_address != kInvalid); |
478 | 485 |
479 if (current_address == kInvalid) { | 486 if (current_address == kInvalid) { |
480 // Unexpectedly encountered a bad record, so step back one. | 487 // Unexpectedly encountered a bad record, so step back one. |
481 current_address = last_good_address; | 488 current_address = last_good_address; |
482 } | 489 } |
483 | 490 |
491 walk_count = 0; | |
492 | |
484 const WinVMAddress start_address_forward = current_address; | 493 const WinVMAddress start_address_forward = current_address; |
485 | 494 |
486 // current_address is now the head of the list, walk Flink to add the whole | 495 // current_address is now the head of the list, walk Flink to add the whole |
487 // list. | 496 // list. |
488 do { | 497 do { |
489 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | 498 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
490 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | 499 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
491 if (!process_reader_.ReadMemory(current_address, | 500 if (!process_reader_.ReadMemory(current_address, |
492 sizeof(critical_section_debug), | 501 sizeof(critical_section_debug), |
493 &critical_section_debug)) { | 502 &critical_section_debug)) { |
(...skipping 12 matching lines...) Expand all Loading... | |
506 | 515 |
507 if (critical_section_debug.ProcessLocksList.Flink == 0) | 516 if (critical_section_debug.ProcessLocksList.Flink == 0) |
508 break; | 517 break; |
509 | 518 |
510 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking | 519 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking |
511 // ProcessLocksList.Flink. | 520 // ProcessLocksList.Flink. |
512 current_address = | 521 current_address = |
513 critical_section_debug.ProcessLocksList.Flink - | 522 critical_section_debug.ProcessLocksList.Flink - |
514 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | 523 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
515 ProcessLocksList); | 524 ProcessLocksList); |
525 walk_count++; | |
526 // Walk twice as far on the forward walk, so that if we started at an | |
527 // important one (for example the Loader Lock), we get it, and ones that | |
528 // were presumably allocated temporally near it. | |
529 if (walk_count == kMaxWalkLength * 2) | |
530 break; | |
516 } while (current_address != start_address_forward && | 531 } while (current_address != start_address_forward && |
517 current_address != kInvalid); | 532 current_address != kInvalid); |
518 } | 533 } |
519 | 534 |
520 } // namespace crashpad | 535 } // namespace crashpad |
OLD | NEW |