Chromium Code Reviews| Index: snapshot/win/process_snapshot_win.cc |
| diff --git a/snapshot/win/process_snapshot_win.cc b/snapshot/win/process_snapshot_win.cc |
| index 98e955c0e3d139e208f22c951b6d53e53f4f5445..30b40ed432e3b2cd2ab8e9e710eaa8dd7a1751e2 100644 |
| --- a/snapshot/win/process_snapshot_win.cc |
| +++ b/snapshot/win/process_snapshot_win.cc |
| @@ -43,8 +43,10 @@ ProcessSnapshotWin::ProcessSnapshotWin() |
| ProcessSnapshotWin::~ProcessSnapshotWin() { |
| } |
| -bool ProcessSnapshotWin::Initialize(HANDLE process, |
| - ProcessSuspensionState suspension_state) { |
| +bool ProcessSnapshotWin::Initialize( |
| + HANDLE process, |
| + ProcessSuspensionState suspension_state, |
| + WinVMAddress debug_critical_section_address) { |
| INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
| GetTimeOfDay(&snapshot_time_); |
| @@ -54,10 +56,13 @@ bool ProcessSnapshotWin::Initialize(HANDLE process, |
| system_.Initialize(&process_reader_); |
| - if (process_reader_.Is64Bit()) |
| - InitializePebData<process_types::internal::Traits64>(); |
| - else |
| - InitializePebData<process_types::internal::Traits32>(); |
| + if (process_reader_.Is64Bit()) { |
| + InitializePebData<process_types::internal::Traits64>( |
| + debug_critical_section_address); |
| + } else { |
| + InitializePebData<process_types::internal::Traits32>( |
| + debug_critical_section_address); |
| + } |
| InitializeThreads(); |
| InitializeModules(); |
| @@ -205,8 +210,8 @@ std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotWin::MemoryMap() |
| std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| std::vector<const MemorySnapshot*> extra_memory; |
| - for (const auto& peb_memory : peb_memory_) |
| - extra_memory.push_back(peb_memory); |
| + for (const auto& em : extra_memory_) |
| + extra_memory.push_back(em); |
| return extra_memory; |
| } |
| @@ -235,11 +240,12 @@ void ProcessSnapshotWin::InitializeModules() { |
| } |
| template <class Traits> |
| -void ProcessSnapshotWin::InitializePebData() { |
| +void ProcessSnapshotWin::InitializePebData( |
| + WinVMAddress debug_critical_section_address) { |
| WinVMAddress peb_address; |
| WinVMSize peb_size; |
| process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); |
| - AddMemorySnapshot(peb_address, peb_size, &peb_memory_); |
| + AddMemorySnapshot(peb_address, peb_size, &extra_memory_); |
| process_types::PEB<Traits> peb_data; |
| if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { |
| @@ -248,7 +254,7 @@ void ProcessSnapshotWin::InitializePebData() { |
| } |
| process_types::PEB_LDR_DATA<Traits> peb_ldr_data; |
| - AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &peb_memory_); |
| + AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_); |
| if (!process_reader_.ReadMemory( |
| peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { |
| LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; |
| @@ -257,17 +263,17 @@ void ProcessSnapshotWin::InitializePebData() { |
| AddMemorySnapshotForLdrLIST_ENTRY( |
| peb_ldr_data.InLoadOrderModuleList, |
| offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForLdrLIST_ENTRY( |
| peb_ldr_data.InMemoryOrderModuleList, |
| offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
| InMemoryOrderLinks), |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForLdrLIST_ENTRY( |
| peb_ldr_data.InInitializationOrderModuleList, |
| offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
| InInitializationOrderLinks), |
| - &peb_memory_); |
| + &extra_memory_); |
| } |
| process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; |
| @@ -278,27 +284,38 @@ void ProcessSnapshotWin::InitializePebData() { |
| return; |
| } |
| AddMemorySnapshot( |
| - peb_data.ProcessParameters, sizeof(process_parameters), &peb_memory_); |
| + peb_data.ProcessParameters, sizeof(process_parameters), &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING( |
| - process_parameters.CurrentDirectory.DosPath, &peb_memory_); |
| - AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, &peb_memory_); |
| + process_parameters.CurrentDirectory.DosPath, &extra_memory_); |
| + AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, |
| - &peb_memory_); |
| + &extra_memory_); |
| AddMemorySnapshot( |
| process_parameters.Environment, |
| DetermineSizeOfEnvironmentBlock(process_parameters.Environment), |
| - &peb_memory_); |
| + &extra_memory_); |
| + |
| + // Walk the loader lock which is directly referenced by the PEB. It may or may |
| + // not have a .DebugInfo list, but typically doesn't. If it does, then we may |
| + // walk the lock list more than once, but AddMemorySnapshot() will take care |
| + // of deduplicating the added regions. |
| + ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); |
| + |
| + // Traverse the locks with valid .DebugInfo if a starting point was supplied. |
| + if (debug_critical_section_address) |
| + ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); |
| } |
| void ProcessSnapshotWin::AddMemorySnapshot( |
| @@ -399,4 +416,54 @@ WinVMSize ProcessSnapshotWin::DetermineSizeOfEnvironmentBlock( |
| return env_block.size() * sizeof(env_block[0]); |
| } |
| +template <class Traits> |
| +void ProcessSnapshotWin::ReadLocks( |
| + WinVMAddress start, |
| + PointerVector<internal::MemorySnapshotWin>* into) { |
| + // We're walking the RTL_CRITICAL_SECTION_DEBUG ProcessLocksList, but starting |
| + // from an actual RTL_CRITICAL_SECTION, so start by getting to the first |
| + // RTL_CRITICAL_SECTION_DEBUG. |
| + |
| + process_types::RTL_CRITICAL_SECTION<Traits> critical_section; |
| + if (!process_reader_.ReadMemory( |
| + start, sizeof(critical_section), &critical_section)) { |
| + LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION"; |
| + return; |
| + } |
| + |
| + const decltype(critical_section.DebugInfo) kInvalid = |
| + static_cast<decltype(critical_section.DebugInfo)>(-1); |
| + if (critical_section.DebugInfo == kInvalid) |
| + return; |
| + |
| + WinVMAddress current = critical_section.DebugInfo; |
| + do { |
| + // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. |
| + process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; |
| + if (!process_reader_.ReadMemory( |
| + current, sizeof(critical_section_debug), &critical_section_debug)) { |
| + LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; |
| + return; |
| + } |
| + |
| + // Add both RTL_CRITICAL_SECTION and RTL_CRITICAL_SECTION_DEBUG to the extra |
| + // memory to be saved. |
| + AddMemorySnapshot(current, |
| + sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>), |
| + into); |
| + AddMemorySnapshot(critical_section_debug.CriticalSection, |
| + sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), |
| + into); |
| + |
| + if (critical_section_debug.ProcessLocksList.Flink == 0) |
|
Mark Mentovai
2015/10/15 00:14:56
You’ve only followed the Flinks, so you won’t catc
scottmg
2015/10/15 18:22:23
Done. It seems to be a circular list, but I can't
|
| + break; |
| + |
| + // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking |
| + // ProcessLocksList.Flink. |
| + current = critical_section_debug.ProcessLocksList.Flink - |
| + offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, |
| + ProcessLocksList); |
| + } while (current != critical_section.DebugInfo && current != kInvalid); |
| +} |
| + |
| } // namespace crashpad |