Chromium Code Reviews| 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 23 matching lines...) Expand all Loading... | |
| 34 report_id_(), | 34 report_id_(), |
| 35 client_id_(), | 35 client_id_(), |
| 36 annotations_simple_map_(), | 36 annotations_simple_map_(), |
| 37 snapshot_time_(), | 37 snapshot_time_(), |
| 38 initialized_() { | 38 initialized_() { |
| 39 } | 39 } |
| 40 | 40 |
| 41 ProcessSnapshotWin::~ProcessSnapshotWin() { | 41 ProcessSnapshotWin::~ProcessSnapshotWin() { |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool ProcessSnapshotWin::Initialize(HANDLE process, | 44 bool ProcessSnapshotWin::Initialize( |
| 45 ProcessSuspensionState suspension_state) { | 45 HANDLE process, |
| 46 ProcessSuspensionState suspension_state, | |
| 47 WinVMAddress debug_critical_section_address) { | |
| 46 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 48 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
| 47 | 49 |
| 48 GetTimeOfDay(&snapshot_time_); | 50 GetTimeOfDay(&snapshot_time_); |
| 49 | 51 |
| 50 if (!process_reader_.Initialize(process, suspension_state)) | 52 if (!process_reader_.Initialize(process, suspension_state)) |
| 51 return false; | 53 return false; |
| 52 | 54 |
| 53 system_.Initialize(&process_reader_); | 55 system_.Initialize(&process_reader_); |
| 54 | 56 |
| 55 if (process_reader_.Is64Bit()) | 57 if (process_reader_.Is64Bit()) { |
| 56 InitializePebData<process_types::internal::Traits64>(); | 58 InitializePebData<process_types::internal::Traits64>( |
| 57 else | 59 debug_critical_section_address); |
| 58 InitializePebData<process_types::internal::Traits32>(); | 60 } else { |
| 61 InitializePebData<process_types::internal::Traits32>( | |
| 62 debug_critical_section_address); | |
| 63 } | |
| 59 | 64 |
| 60 InitializeThreads(); | 65 InitializeThreads(); |
| 61 InitializeModules(); | 66 InitializeModules(); |
| 62 | 67 |
| 63 INITIALIZATION_STATE_SET_VALID(initialized_); | 68 INITIALIZATION_STATE_SET_VALID(initialized_); |
| 64 return true; | 69 return true; |
| 65 } | 70 } |
| 66 | 71 |
| 67 bool ProcessSnapshotWin::InitializeException( | 72 bool ProcessSnapshotWin::InitializeException( |
| 68 WinVMAddress exception_information_address) { | 73 WinVMAddress exception_information_address) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 return modules; | 188 return modules; |
| 184 } | 189 } |
| 185 | 190 |
| 186 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { | 191 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { |
| 187 return exception_.get(); | 192 return exception_.get(); |
| 188 } | 193 } |
| 189 | 194 |
| 190 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { | 195 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { |
| 191 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 196 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 192 std::vector<const MemorySnapshot*> extra_memory; | 197 std::vector<const MemorySnapshot*> extra_memory; |
| 193 for (const auto& peb_memory : peb_memory_) | 198 for (const auto& em : extra_memory_) |
| 194 extra_memory.push_back(peb_memory); | 199 extra_memory.push_back(em); |
| 195 return extra_memory; | 200 return extra_memory; |
| 196 } | 201 } |
| 197 | 202 |
| 198 void ProcessSnapshotWin::InitializeThreads() { | 203 void ProcessSnapshotWin::InitializeThreads() { |
| 199 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = | 204 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = |
| 200 process_reader_.Threads(); | 205 process_reader_.Threads(); |
| 201 for (const ProcessReaderWin::Thread& process_reader_thread : | 206 for (const ProcessReaderWin::Thread& process_reader_thread : |
| 202 process_reader_threads) { | 207 process_reader_threads) { |
| 203 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); | 208 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); |
| 204 if (thread->Initialize(&process_reader_, process_reader_thread)) { | 209 if (thread->Initialize(&process_reader_, process_reader_thread)) { |
| 205 threads_.push_back(thread.release()); | 210 threads_.push_back(thread.release()); |
| 206 } | 211 } |
| 207 } | 212 } |
| 208 } | 213 } |
| 209 | 214 |
| 210 void ProcessSnapshotWin::InitializeModules() { | 215 void ProcessSnapshotWin::InitializeModules() { |
| 211 const std::vector<ProcessInfo::Module>& process_reader_modules = | 216 const std::vector<ProcessInfo::Module>& process_reader_modules = |
| 212 process_reader_.Modules(); | 217 process_reader_.Modules(); |
| 213 for (const ProcessInfo::Module& process_reader_module : | 218 for (const ProcessInfo::Module& process_reader_module : |
| 214 process_reader_modules) { | 219 process_reader_modules) { |
| 215 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); | 220 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); |
| 216 if (module->Initialize(&process_reader_, process_reader_module)) { | 221 if (module->Initialize(&process_reader_, process_reader_module)) { |
| 217 modules_.push_back(module.release()); | 222 modules_.push_back(module.release()); |
| 218 } | 223 } |
| 219 } | 224 } |
| 220 } | 225 } |
| 221 | 226 |
| 222 template <class Traits> | 227 template <class Traits> |
| 223 void ProcessSnapshotWin::InitializePebData() { | 228 void ProcessSnapshotWin::InitializePebData( |
| 229 WinVMAddress debug_critical_section_address) { | |
| 224 WinVMAddress peb_address; | 230 WinVMAddress peb_address; |
| 225 WinVMSize peb_size; | 231 WinVMSize peb_size; |
| 226 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); | 232 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); |
| 227 AddMemorySnapshot(peb_address, peb_size, &peb_memory_); | 233 AddMemorySnapshot(peb_address, peb_size, &extra_memory_); |
| 228 | 234 |
| 229 process_types::PEB<Traits> peb_data; | 235 process_types::PEB<Traits> peb_data; |
| 230 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { | 236 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) { |
| 231 LOG(ERROR) << "ReadMemory PEB"; | 237 LOG(ERROR) << "ReadMemory PEB"; |
| 232 return; | 238 return; |
| 233 } | 239 } |
| 234 | 240 |
| 235 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; | 241 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; |
| 236 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &peb_memory_); | 242 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_); |
| 237 if (!process_reader_.ReadMemory( | 243 if (!process_reader_.ReadMemory( |
| 238 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { | 244 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) { |
| 239 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; | 245 LOG(ERROR) << "ReadMemory PEB_LDR_DATA"; |
| 240 } else { | 246 } else { |
| 241 // Walk the LDR structure to retrieve its pointed-to data. | 247 // Walk the LDR structure to retrieve its pointed-to data. |
| 242 AddMemorySnapshotForLdrLIST_ENTRY( | 248 AddMemorySnapshotForLdrLIST_ENTRY( |
| 243 peb_ldr_data.InLoadOrderModuleList, | 249 peb_ldr_data.InLoadOrderModuleList, |
| 244 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), | 250 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks), |
| 245 &peb_memory_); | 251 &extra_memory_); |
| 246 AddMemorySnapshotForLdrLIST_ENTRY( | 252 AddMemorySnapshotForLdrLIST_ENTRY( |
| 247 peb_ldr_data.InMemoryOrderModuleList, | 253 peb_ldr_data.InMemoryOrderModuleList, |
| 248 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 254 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
| 249 InMemoryOrderLinks), | 255 InMemoryOrderLinks), |
| 250 &peb_memory_); | 256 &extra_memory_); |
| 251 AddMemorySnapshotForLdrLIST_ENTRY( | 257 AddMemorySnapshotForLdrLIST_ENTRY( |
| 252 peb_ldr_data.InInitializationOrderModuleList, | 258 peb_ldr_data.InInitializationOrderModuleList, |
| 253 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, | 259 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, |
| 254 InInitializationOrderLinks), | 260 InInitializationOrderLinks), |
| 255 &peb_memory_); | 261 &extra_memory_); |
| 256 } | 262 } |
| 257 | 263 |
| 258 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; | 264 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; |
| 259 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, | 265 if (!process_reader_.ReadMemory(peb_data.ProcessParameters, |
| 260 sizeof(process_parameters), | 266 sizeof(process_parameters), |
| 261 &process_parameters)) { | 267 &process_parameters)) { |
| 262 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; | 268 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS"; |
| 263 return; | 269 return; |
| 264 } | 270 } |
| 265 AddMemorySnapshot( | 271 AddMemorySnapshot( |
| 266 peb_data.ProcessParameters, sizeof(process_parameters), &peb_memory_); | 272 peb_data.ProcessParameters, sizeof(process_parameters), &extra_memory_); |
| 267 | 273 |
| 268 AddMemorySnapshotForUNICODE_STRING( | 274 AddMemorySnapshotForUNICODE_STRING( |
| 269 process_parameters.CurrentDirectory.DosPath, &peb_memory_); | 275 process_parameters.CurrentDirectory.DosPath, &extra_memory_); |
| 270 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, &peb_memory_); | 276 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, |
| 277 &extra_memory_); | |
| 271 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, | 278 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName, |
| 272 &peb_memory_); | 279 &extra_memory_); |
| 273 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, | 280 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine, |
| 274 &peb_memory_); | 281 &extra_memory_); |
| 275 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, | 282 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle, |
| 276 &peb_memory_); | 283 &extra_memory_); |
| 277 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, | 284 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo, |
| 278 &peb_memory_); | 285 &extra_memory_); |
| 279 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, | 286 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo, |
| 280 &peb_memory_); | 287 &extra_memory_); |
| 281 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, | 288 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData, |
| 282 &peb_memory_); | 289 &extra_memory_); |
| 283 AddMemorySnapshot( | 290 AddMemorySnapshot( |
| 284 process_parameters.Environment, | 291 process_parameters.Environment, |
| 285 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), | 292 DetermineSizeOfEnvironmentBlock(process_parameters.Environment), |
| 286 &peb_memory_); | 293 &extra_memory_); |
| 294 | |
| 295 // Walk the loader lock which is directly referenced by the PEB. It may or may | |
| 296 // not have a .DebugInfo list, but typically doesn't. If it does, then we may | |
| 297 // walk the lock list more than once, but AddMemorySnapshot() will take care | |
| 298 // of deduplicating the added regions. | |
| 299 ReadLocks<Traits>(peb_data.LoaderLock, &extra_memory_); | |
| 300 | |
| 301 // Traverse the locks with valid .DebugInfo if a starting point was supplied. | |
| 302 if (debug_critical_section_address) | |
| 303 ReadLocks<Traits>(debug_critical_section_address, &extra_memory_); | |
| 287 } | 304 } |
| 288 | 305 |
| 289 void ProcessSnapshotWin::AddMemorySnapshot( | 306 void ProcessSnapshotWin::AddMemorySnapshot( |
| 290 WinVMAddress address, | 307 WinVMAddress address, |
| 291 WinVMSize size, | 308 WinVMSize size, |
| 292 PointerVector<internal::MemorySnapshotWin>* into) { | 309 PointerVector<internal::MemorySnapshotWin>* into) { |
| 293 if (size == 0) | 310 if (size == 0) |
| 294 return; | 311 return; |
| 295 | 312 |
| 296 // Ensure that the entire range is readable. TODO(scottmg): Consider | 313 // Ensure that the entire range is readable. TODO(scottmg): Consider |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 env_block.resize( | 394 env_block.resize( |
| 378 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); | 395 static_cast<unsigned int>(bytes_read / sizeof(env_block[0]))); |
| 379 const wchar_t terminator[] = { 0, 0 }; | 396 const wchar_t terminator[] = { 0, 0 }; |
| 380 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); | 397 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator))); |
| 381 if (at != std::wstring::npos) | 398 if (at != std::wstring::npos) |
| 382 env_block.resize(at + arraysize(terminator)); | 399 env_block.resize(at + arraysize(terminator)); |
| 383 | 400 |
| 384 return env_block.size() * sizeof(env_block[0]); | 401 return env_block.size() * sizeof(env_block[0]); |
| 385 } | 402 } |
| 386 | 403 |
| 404 template <class Traits> | |
| 405 void ProcessSnapshotWin::ReadLocks( | |
| 406 WinVMAddress start, | |
| 407 PointerVector<internal::MemorySnapshotWin>* into) { | |
| 408 // We're walking the RTL_CRITICAL_SECTION_DEBUG ProcessLocksList, but starting | |
| 409 // from an actual RTL_CRITICAL_SECTION, so start by getting to the first | |
| 410 // RTL_CRITICAL_SECTION_DEBUG. | |
| 411 | |
| 412 process_types::RTL_CRITICAL_SECTION<Traits> critical_section; | |
| 413 if (!process_reader_.ReadMemory( | |
| 414 start, sizeof(critical_section), &critical_section)) { | |
| 415 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION"; | |
| 416 return; | |
| 417 } | |
| 418 | |
| 419 const decltype(critical_section.DebugInfo) kInvalid = | |
| 420 static_cast<decltype(critical_section.DebugInfo)>(-1); | |
| 421 if (critical_section.DebugInfo == kInvalid) | |
| 422 return; | |
| 423 | |
| 424 WinVMAddress current = critical_section.DebugInfo; | |
| 425 do { | |
| 426 // Read the RTL_CRITICAL_SECTION_DEBUG structure to get ProcessLocksList. | |
| 427 process_types::RTL_CRITICAL_SECTION_DEBUG<Traits> critical_section_debug; | |
| 428 if (!process_reader_.ReadMemory( | |
| 429 current, sizeof(critical_section_debug), &critical_section_debug)) { | |
| 430 LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION_DEBUG"; | |
| 431 return; | |
| 432 } | |
| 433 | |
| 434 // Add both RTL_CRITICAL_SECTION_DEBUG and RTL_CRITICAL_SECTION_DEBUG to the | |
|
Mark Mentovai
2015/10/12 14:08:59
One of these shouldn’t be _DEBUG.
| |
| 435 // extra memory to be saved. | |
| 436 AddMemorySnapshot(current, | |
| 437 sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>), | |
| 438 into); | |
| 439 AddMemorySnapshot(critical_section_debug.CriticalSection, | |
| 440 sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), | |
| 441 into); | |
| 442 | |
| 443 if (critical_section_debug.ProcessLocksList.Flink == 0) | |
| 444 break; | |
| 445 | |
| 446 // Move to the next RTL_CRITICAL_SECTION_DEBUG by walking | |
| 447 // ProcessLocksList.Flink. | |
| 448 current = critical_section_debug.ProcessLocksList.Flink - | |
| 449 offsetof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>, | |
| 450 ProcessLocksList); | |
| 451 } while (current != critical_section.DebugInfo && current != kInvalid); | |
| 452 } | |
| 453 | |
| 387 } // namespace crashpad | 454 } // namespace crashpad |
| OLD | NEW |