Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(550)

Side by Side Diff: snapshot/win/process_snapshot_win.cc

Issue 1392093003: win: Capture some CRITICAL_SECTION debugging data (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: . Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « snapshot/win/process_snapshot_win.h ('k') | snapshot/win/process_snapshot_win_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 doesn't on more recent OSs (it does on
312 // Vista). If it does, then we may walk the lock list more than once, but
313 // AddMemorySnapshot() will take care 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
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 const WinVMAddress start_address_backward = critical_section.DebugInfo;
440 WinVMAddress current_address = start_address_backward;
441 WinVMAddress last_good_address;
442
443 // Typically, this seems to be a circular list, but it's not clear that it
444 // always is, so follow Blink fields back to the head (or where we started)
445 // before following Flink to capture memory.
446 do {
447 last_good_address = current_address;
448 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList.
449 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug;
450 if (!process_reader_.ReadMemory(current_address,
451 sizeof(critical_section_debug),
452 &critical_section_debug)) {
453 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG";
454 return;
455 }
456
457 if (critical_section_debug.ProcessLocksList.Blink == 0) {
458 // At the head of the list.
459 break;
460 }
461
462 // Move to the previous RTL_CRITICAL_SECTION_DEBUG by walking
463 // ProcessLocksList.Blink.
464 current_address =
465 critical_section_debug.ProcessLocksList.Blink -
466 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>,
467 ProcessLocksList);
468 } while (current_address != start_address_backward &&
469 current_address != kInvalid);
470
471 if (current_address == kInvalid) {
472 // Unexpectedly encountered a bad record, so step back one.
473 current_address = last_good_address;
474 }
475
476 const WinVMAddress start_address_forward = current_address;
477
478 // current_address is now the head of the list, walk Flink to add the whole
479 // list.
480 do {
481 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList.
482 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug;
483 if (!process_reader_.ReadMemory(current_address,
484 sizeof(critical_section_debug),
485 &critical_section_debug)) {
486 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG";
487 return;
488 }
489
490 // Add both RTL_CRITICAL_SECTION_DEBUG and RTL_CRITICAL_SECTION to the extra
491 // memory to be saved.
492 AddMemorySnapshot(current_address,
493 sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>),
494 into);
495 AddMemorySnapshot(critical_section_debug.CriticalSection,
496 sizeof(process_types::RTL_CRITICAL_SECTION<Traits>),
497 into);
498
499 if (critical_section_debug.ProcessLocksList.Flink == 0)
500 break;
501
502 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking
503 // ProcessLocksList.Flink.
504 current_address =
505 critical_section_debug.ProcessLocksList.Flink -
506 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>,
507 ProcessLocksList);
508 } while (current_address != start_address_forward &&
509 current_address != kInvalid);
510 }
511
402 } // namespace crashpad 512 } // namespace crashpad
OLDNEW
« no previous file with comments | « snapshot/win/process_snapshot_win.h ('k') | snapshot/win/process_snapshot_win_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698