| 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 430 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; | |
| 453 int walk_count = 0; | |
| 454 | |
| 455 // Typically, this seems to be a circular list, but it's not clear that it | 451 // Typically, this seems to be a circular list, but it's not clear that it |
| 456 // always is, so follow Blink fields back to the head (or where we started) | 452 // always is, so follow Blink fields back to the head (or where we started) |
| 457 // before following Flink to capture memory. | 453 // before following Flink to capture memory. |
| 458 do { | 454 do { |
| 459 last_good_address = current_address; | 455 last_good_address = current_address; |
| 460 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | 456 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
| 461 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | 457 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
| 462 if (!process_reader_.ReadMemory(current_address, | 458 if (!process_reader_.ReadMemory(current_address, |
| 463 sizeof(critical_section_debug), | 459 sizeof(critical_section_debug), |
| 464 &critical_section_debug)) { | 460 &critical_section_debug)) { |
| 465 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; | 461 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; |
| 466 return; | 462 return; |
| 467 } | 463 } |
| 468 | 464 |
| 469 if (critical_section_debug.ProcessLocksList.Blink == 0) { | 465 if (critical_section_debug.ProcessLocksList.Blink == 0) { |
| 470 // At the head of the list. | 466 // At the head of the list. |
| 471 break; | 467 break; |
| 472 } | 468 } |
| 473 | 469 |
| 474 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking | 470 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking |
| 475 // ProcessLocksList.Blink. | 471 // ProcessLocksList.Blink. |
| 476 current_address = | 472 current_address = |
| 477 critical_section_debug.ProcessLocksList.Blink - | 473 critical_section_debug.ProcessLocksList.Blink - |
| 478 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | 474 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
| 479 ProcessLocksList); | 475 ProcessLocksList); |
| 480 walk_count++; | |
| 481 if (walk_count == kMaxWalkLength) | |
| 482 break; | |
| 483 } while (current_address != start_address_backward && | 476 } while (current_address != start_address_backward && |
| 484 current_address != kInvalid); | 477 current_address != kInvalid); |
| 485 | 478 |
| 486 if (current_address == kInvalid) { | 479 if (current_address == kInvalid) { |
| 487 // Unexpectedly encountered a bad record, so step back one. | 480 // Unexpectedly encountered a bad record, so step back one. |
| 488 current_address = last_good_address; | 481 current_address = last_good_address; |
| 489 } | 482 } |
| 490 | 483 |
| 491 walk_count = 0; | |
| 492 | |
| 493 const WinVMAddress start_address_forward = current_address; | 484 const WinVMAddress start_address_forward = current_address; |
| 494 | 485 |
| 495 // current_address is now the head of the list, walk Flink to add the whole | 486 // current_address is now the head of the list, walk Flink to add the whole |
| 496 // list. | 487 // list. |
| 497 do { | 488 do { |
| 498 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | 489 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
| 499 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | 490 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
| 500 if (!process_reader_.ReadMemory(current_address, | 491 if (!process_reader_.ReadMemory(current_address, |
| 501 sizeof(critical_section_debug), | 492 sizeof(critical_section_debug), |
| 502 &critical_section_debug)) { | 493 &critical_section_debug)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 515 | 506 |
| 516 if (critical_section_debug.ProcessLocksList.Flink == 0) | 507 if (critical_section_debug.ProcessLocksList.Flink == 0) |
| 517 break; | 508 break; |
| 518 | 509 |
| 519 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking | 510 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking |
| 520 // ProcessLocksList.Flink. | 511 // ProcessLocksList.Flink. |
| 521 current_address = | 512 current_address = |
| 522 critical_section_debug.ProcessLocksList.Flink - | 513 critical_section_debug.ProcessLocksList.Flink - |
| 523 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | 514 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
| 524 ProcessLocksList); | 515 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; | |
| 531 } while (current_address != start_address_forward && | 516 } while (current_address != start_address_forward && |
| 532 current_address != kInvalid); | 517 current_address != kInvalid); |
| 533 } | 518 } |
| 534 | 519 |
| 535 } // namespace crashpad | 520 } // namespace crashpad |
| OLD | NEW |