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 typically doesn't. If it does, then we may | |
312 // walk the lock list more than once, but AddMemorySnapshot() will take care | |
313 // 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 WinVMAddress current = critical_section.DebugInfo; | |
440 do { | |
441 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | |
442 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | |
443 if (!process_reader_.ReadMemory( | |
444 current, sizeof(critical_section_debug), &critical_section_debug)) { | |
445 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; | |
446 return; | |
447 } | |
448 | |
449 // Add both RTL_CRITICAL_SECTION and RTL_CRITICAL_SECTION_DEBUG to the extra | |
450 // memory to be saved. | |
451 AddMemorySnapshot(current, | |
452 sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>), | |
453 into); | |
454 AddMemorySnapshot(critical_section_debug.CriticalSection, | |
455 sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), | |
456 into); | |
457 | |
458 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
| |
459 break; | |
460 | |
461 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking | |
462 // ProcessLocksList.Flink. | |
463 current = critical_section_debug.ProcessLocksList.Flink - | |
464 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | |
465 ProcessLocksList); | |
466 } while (current != critical_section.DebugInfo && current != kInvalid); | |
467 } | |
468 | |
402 } // namespace crashpad | 469 } // namespace crashpad |
OLD | NEW |