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 |