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

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: reenable !locks test 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
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 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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698