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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 return handle; | 110 return handle; |
| 111 } | 111 } |
| 112 | 112 |
| 113 // It's necessary to suspend the thread to grab CONTEXT. SuspendThread has a | 113 // It's necessary to suspend the thread to grab CONTEXT. SuspendThread has a |
| 114 // side-effect of returning the SuspendCount of the thread on success, so we | 114 // side-effect of returning the SuspendCount of the thread on success, so we |
| 115 // fill out these two pieces of semi-unrelated data in the same function. | 115 // fill out these two pieces of semi-unrelated data in the same function. |
| 116 template <class Traits> | 116 template <class Traits> |
| 117 void FillThreadContextAndSuspendCount( | 117 void FillThreadContextAndSuspendCount( |
| 118 const process_types::SYSTEM_EXTENDED_THREAD_INFORMATION<Traits>& | 118 const process_types::SYSTEM_EXTENDED_THREAD_INFORMATION<Traits>& |
| 119 thread_info, | 119 thread_info, |
| 120 ProcessReaderWin::Thread* thread) { | 120 ProcessReaderWin::Thread* thread, |
| 121 | 121 ProcessSuspensionState process_state) { |
| 122 // Don't suspend the thread if it's this thread. This is really only for test | 122 // Don't suspend the thread if it's this thread. This is really only for test |
| 123 // binaries, as we won't be walking ourselves, in general. | 123 // binaries, as we won't be walking ourselves, in general. |
| 124 bool is_current_thread = thread_info.ClientId.UniqueThread == | 124 bool is_current_thread = thread_info.ClientId.UniqueThread == |
| 125 reinterpret_cast<process_types::TEB<Traits>*>( | 125 reinterpret_cast<process_types::TEB<Traits>*>( |
| 126 NtCurrentTeb())->ClientId.UniqueThread; | 126 NtCurrentTeb())->ClientId.UniqueThread; |
| 127 | 127 |
| 128 ScopedKernelHANDLE thread_handle(OpenThread(thread_info)); | 128 ScopedKernelHANDLE thread_handle(OpenThread(thread_info)); |
| 129 | 129 |
| 130 // TODO(scottmg): Handle cross-bitness in this function. | 130 // TODO(scottmg): Handle cross-bitness in this function. |
| 131 | 131 |
| 132 if (is_current_thread) { | 132 if (is_current_thread) { |
| 133 thread->suspend_count = 0; | 133 thread->suspend_count = 0; |
|
Mark Mentovai
2015/09/09 18:57:27
LOG(ERROR) or DCHECK() if the suspension state is
scottmg
2015/09/09 19:13:25
Done.
| |
| 134 RtlCaptureContext(&thread->context); | 134 RtlCaptureContext(&thread->context); |
| 135 } else { | 135 } else { |
| 136 DWORD previous_suspend_count = SuspendThread(thread_handle.get()); | 136 DWORD previous_suspend_count = SuspendThread(thread_handle.get()); |
| 137 if (previous_suspend_count == -1) { | 137 if (previous_suspend_count == -1) { |
| 138 PLOG(ERROR) << "SuspendThread failed"; | 138 PLOG(ERROR) << "SuspendThread failed"; |
| 139 return; | 139 return; |
| 140 } | 140 } |
| 141 thread->suspend_count = previous_suspend_count; | 141 if (previous_suspend_count == 0 && |
| 142 process_state == ProcessSuspensionState::kSuspended) { | |
| 143 LOG(ERROR) << "suspend count was 0, but process should be suspended"; | |
|
Mark Mentovai
2015/09/09 18:57:27
Upgrade (sidegrade) to a DCHECK()? This indicates
scottmg
2015/09/09 19:13:25
Done.
| |
| 144 } | |
| 145 thread->suspend_count = | |
| 146 previous_suspend_count - | |
| 147 (process_state == ProcessSuspensionState::kSuspended ? 1 : 0); | |
| 142 | 148 |
| 143 memset(&thread->context, 0, sizeof(thread->context)); | 149 memset(&thread->context, 0, sizeof(thread->context)); |
| 144 thread->context.ContextFlags = CONTEXT_ALL; | 150 thread->context.ContextFlags = CONTEXT_ALL; |
| 145 if (!GetThreadContext(thread_handle.get(), &thread->context)) { | 151 if (!GetThreadContext(thread_handle.get(), &thread->context)) { |
| 146 PLOG(ERROR) << "GetThreadContext failed"; | 152 PLOG(ERROR) << "GetThreadContext failed"; |
| 147 return; | 153 return; |
| 148 } | 154 } |
| 149 | 155 |
| 150 if (!ResumeThread(thread_handle.get())) { | 156 if (!ResumeThread(thread_handle.get())) { |
| 151 PLOG(ERROR) << "ResumeThread failed"; | 157 PLOG(ERROR) << "ResumeThread failed"; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 164 suspend_count(0), | 170 suspend_count(0), |
| 165 priority_class(0), | 171 priority_class(0), |
| 166 priority(0) { | 172 priority(0) { |
| 167 } | 173 } |
| 168 | 174 |
| 169 ProcessReaderWin::ProcessReaderWin() | 175 ProcessReaderWin::ProcessReaderWin() |
| 170 : process_(INVALID_HANDLE_VALUE), | 176 : process_(INVALID_HANDLE_VALUE), |
| 171 process_info_(), | 177 process_info_(), |
| 172 threads_(), | 178 threads_(), |
| 173 modules_(), | 179 modules_(), |
| 180 process_state_(), | |
| 174 initialized_threads_(false), | 181 initialized_threads_(false), |
| 175 initialized_() { | 182 initialized_() { |
| 176 } | 183 } |
| 177 | 184 |
| 178 ProcessReaderWin::~ProcessReaderWin() { | 185 ProcessReaderWin::~ProcessReaderWin() { |
| 179 } | 186 } |
| 180 | 187 |
| 181 bool ProcessReaderWin::Initialize(HANDLE process) { | 188 bool ProcessReaderWin::Initialize(HANDLE process, |
| 189 ProcessSuspensionState process_state) { | |
| 182 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 190 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
| 183 | 191 |
| 184 process_ = process; | 192 process_ = process; |
| 193 process_state_ = process_state; | |
| 185 process_info_.Initialize(process); | 194 process_info_.Initialize(process); |
| 186 | 195 |
| 187 INITIALIZATION_STATE_SET_VALID(initialized_); | 196 INITIALIZATION_STATE_SET_VALID(initialized_); |
| 188 return true; | 197 return true; |
| 189 } | 198 } |
| 190 | 199 |
| 191 bool ProcessReaderWin::ReadMemory(WinVMAddress at, | 200 bool ProcessReaderWin::ReadMemory(WinVMAddress at, |
| 192 WinVMSize num_bytes, | 201 WinVMSize num_bytes, |
| 193 void* into) { | 202 void* into) { |
| 194 SIZE_T bytes_read; | 203 SIZE_T bytes_read; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 GetProcessInformation<SizeTraits>(process_, &buffer); | 256 GetProcessInformation<SizeTraits>(process_, &buffer); |
| 248 if (!process_information) | 257 if (!process_information) |
| 249 return threads_; | 258 return threads_; |
| 250 | 259 |
| 251 for (unsigned long i = 0; i < process_information->NumberOfThreads; ++i) { | 260 for (unsigned long i = 0; i < process_information->NumberOfThreads; ++i) { |
| 252 const process_types::SYSTEM_EXTENDED_THREAD_INFORMATION<SizeTraits>& | 261 const process_types::SYSTEM_EXTENDED_THREAD_INFORMATION<SizeTraits>& |
| 253 thread_info = process_information->Threads[i]; | 262 thread_info = process_information->Threads[i]; |
| 254 Thread thread; | 263 Thread thread; |
| 255 thread.id = thread_info.ClientId.UniqueThread; | 264 thread.id = thread_info.ClientId.UniqueThread; |
| 256 | 265 |
| 257 FillThreadContextAndSuspendCount(thread_info, &thread); | 266 FillThreadContextAndSuspendCount(thread_info, &thread, process_state_); |
| 258 | 267 |
| 259 // TODO(scottmg): I believe we could reverse engineer the PriorityClass from | 268 // TODO(scottmg): I believe we could reverse engineer the PriorityClass from |
| 260 // the Priority, BasePriority, and | 269 // the Priority, BasePriority, and |
| 261 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms685100 . | 270 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms685100 . |
| 262 // MinidumpThreadWriter doesn't handle it yet in any case, so investigate | 271 // MinidumpThreadWriter doesn't handle it yet in any case, so investigate |
| 263 // both of those at the same time if it's useful. | 272 // both of those at the same time if it's useful. |
| 264 thread.priority_class = NORMAL_PRIORITY_CLASS; | 273 thread.priority_class = NORMAL_PRIORITY_CLASS; |
| 265 | 274 |
| 266 thread.priority = thread_info.Priority; | 275 thread.priority = thread_info.Priority; |
| 267 thread.teb = thread_info.TebBase; | 276 thread.teb = thread_info.TebBase; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 287 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 296 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 288 | 297 |
| 289 if (!process_info_.Modules(&modules_)) { | 298 if (!process_info_.Modules(&modules_)) { |
| 290 LOG(ERROR) << "couldn't retrieve modules"; | 299 LOG(ERROR) << "couldn't retrieve modules"; |
| 291 } | 300 } |
| 292 | 301 |
| 293 return modules_; | 302 return modules_; |
| 294 } | 303 } |
| 295 | 304 |
| 296 } // namespace crashpad | 305 } // namespace crashpad |
| OLD | NEW |