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

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

Issue 1360863006: win: Add more memory regions to gathering of PEB (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@save-peb
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') | no next file » | 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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "snapshot/win/process_snapshot_win.h" 15 #include "snapshot/win/process_snapshot_win.h"
16 16
17 #include <algorithm>
18
17 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/strings/stringprintf.h"
18 #include "snapshot/win/module_snapshot_win.h" 21 #include "snapshot/win/module_snapshot_win.h"
19 #include "util/win/registration_protocol_win.h" 22 #include "util/win/registration_protocol_win.h"
20 #include "util/win/time.h" 23 #include "util/win/time.h"
21 24
22 namespace crashpad { 25 namespace crashpad {
23 26
24 ProcessSnapshotWin::ProcessSnapshotWin() 27 ProcessSnapshotWin::ProcessSnapshotWin()
25 : ProcessSnapshot(), 28 : ProcessSnapshot(),
26 system_(), 29 system_(),
27 threads_(), 30 threads_(),
(...skipping 13 matching lines...) Expand all
41 bool ProcessSnapshotWin::Initialize(HANDLE process, 44 bool ProcessSnapshotWin::Initialize(HANDLE process,
42 ProcessSuspensionState suspension_state) { 45 ProcessSuspensionState suspension_state) {
43 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); 46 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
44 47
45 GetTimeOfDay(&snapshot_time_); 48 GetTimeOfDay(&snapshot_time_);
46 49
47 if (!process_reader_.Initialize(process, suspension_state)) 50 if (!process_reader_.Initialize(process, suspension_state))
48 return false; 51 return false;
49 52
50 system_.Initialize(&process_reader_); 53 system_.Initialize(&process_reader_);
51 WinVMAddress peb_address; 54
52 WinVMSize peb_size; 55 if (process_reader_.Is64Bit())
53 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size); 56 InitializePebData<process_types::internal::Traits64>();
54 peb_.Initialize(&process_reader_, peb_address, peb_size); 57 else
58 InitializePebData<process_types::internal::Traits32>();
55 59
56 InitializeThreads(); 60 InitializeThreads();
57 InitializeModules(); 61 InitializeModules();
58 62
59 INITIALIZATION_STATE_SET_VALID(initialized_); 63 INITIALIZATION_STATE_SET_VALID(initialized_);
60 return true; 64 return true;
61 } 65 }
62 66
63 bool ProcessSnapshotWin::InitializeException( 67 bool ProcessSnapshotWin::InitializeException(
64 WinVMAddress exception_information_address) { 68 WinVMAddress exception_information_address) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 return modules; 183 return modules;
180 } 184 }
181 185
182 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { 186 const ExceptionSnapshot* ProcessSnapshotWin::Exception() const {
183 return exception_.get(); 187 return exception_.get();
184 } 188 }
185 189
186 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const { 190 std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const {
187 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 191 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
188 std::vector<const MemorySnapshot*> extra_memory; 192 std::vector<const MemorySnapshot*> extra_memory;
189 extra_memory.push_back(&peb_); 193 for (const auto& peb_memory : peb_memory_)
194 extra_memory.push_back(peb_memory);
190 return extra_memory; 195 return extra_memory;
191 } 196 }
192 197
193 void ProcessSnapshotWin::InitializeThreads() { 198 void ProcessSnapshotWin::InitializeThreads() {
194 const std::vector<ProcessReaderWin::Thread>& process_reader_threads = 199 const std::vector<ProcessReaderWin::Thread>& process_reader_threads =
195 process_reader_.Threads(); 200 process_reader_.Threads();
196 for (const ProcessReaderWin::Thread& process_reader_thread : 201 for (const ProcessReaderWin::Thread& process_reader_thread :
197 process_reader_threads) { 202 process_reader_threads) {
198 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); 203 auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin());
199 if (thread->Initialize(&process_reader_, process_reader_thread)) { 204 if (thread->Initialize(&process_reader_, process_reader_thread)) {
200 threads_.push_back(thread.release()); 205 threads_.push_back(thread.release());
201 } 206 }
202 } 207 }
203 } 208 }
204 209
205 void ProcessSnapshotWin::InitializeModules() { 210 void ProcessSnapshotWin::InitializeModules() {
206 const std::vector<ProcessInfo::Module>& process_reader_modules = 211 const std::vector<ProcessInfo::Module>& process_reader_modules =
207 process_reader_.Modules(); 212 process_reader_.Modules();
208 for (const ProcessInfo::Module& process_reader_module : 213 for (const ProcessInfo::Module& process_reader_module :
209 process_reader_modules) { 214 process_reader_modules) {
210 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); 215 auto module = make_scoped_ptr(new internal::ModuleSnapshotWin());
211 if (module->Initialize(&process_reader_, process_reader_module)) { 216 if (module->Initialize(&process_reader_, process_reader_module)) {
212 modules_.push_back(module.release()); 217 modules_.push_back(module.release());
213 } 218 }
214 } 219 }
215 } 220 }
216 221
222 template <class Traits>
223 void ProcessSnapshotWin::InitializePebData() {
224 WinVMAddress peb_address;
225 WinVMSize peb_size;
226 process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size);
227 AddMemorySnapshot(peb_address, peb_size, &peb_memory_);
228
229 process_types::PEB<Traits> peb_data;
230 if (!process_reader_.ReadMemory(peb_address, peb_size, &peb_data)) {
231 LOG(ERROR) << "ReadMemory PEB";
232 return;
233 }
234
235 process_types::PEB_LDR_DATA<Traits> peb_ldr_data;
236 AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &peb_memory_);
237 if (!process_reader_.ReadMemory(
238 peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) {
239 LOG(ERROR) << "ReadMemory PEB_LDR_DATA";
240 } else {
241 // Walk the LDR structure to retrieve its pointed-to data.
242 AddMemorySnapshotForLdrLIST_ENTRY(
243 peb_ldr_data.InLoadOrderModuleList,
244 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks),
245 &peb_memory_);
246 AddMemorySnapshotForLdrLIST_ENTRY(
247 peb_ldr_data.InMemoryOrderModuleList,
248 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
249 InMemoryOrderLinks),
250 &peb_memory_);
251 AddMemorySnapshotForLdrLIST_ENTRY(
252 peb_ldr_data.InInitializationOrderModuleList,
253 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
254 InInitializationOrderLinks),
255 &peb_memory_);
256 }
257
258 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters;
259 if (!process_reader_.ReadMemory(peb_data.ProcessParameters,
260 sizeof(process_parameters),
261 &process_parameters)) {
262 LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS";
263 return;
264 }
265 AddMemorySnapshot(
266 peb_data.ProcessParameters, sizeof(process_parameters), &peb_memory_);
267
268 AddMemorySnapshotForUNICODE_STRING(
269 process_parameters.CurrentDirectory.DosPath, &peb_memory_);
270 AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath, &peb_memory_);
271 AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName,
272 &peb_memory_);
273 AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine,
274 &peb_memory_);
275 AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle,
276 &peb_memory_);
277 AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo,
278 &peb_memory_);
279 AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo,
280 &peb_memory_);
281 AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData,
282 &peb_memory_);
283 AddMemorySnapshot(
284 process_parameters.Environment,
285 DetermineSizeOfEnvironmentBlock(process_parameters.Environment),
286 &peb_memory_);
287 }
288
289 void ProcessSnapshotWin::AddMemorySnapshot(
290 WinVMAddress address,
291 WinVMSize size,
292 PointerVector<internal::MemorySnapshotWin>* into) {
293 if (size == 0)
294 return;
295
296 // Ensure that the entire range is readable. TODO(scottmg): Consider
297 // generalizing this as part of
298 // https://code.google.com/p/crashpad/issues/detail?id=59.
299 auto ranges = process_reader_.GetProcessInfo().GetReadableRanges(
300 CheckedRange<WinVMAddress, WinVMSize>(address, size));
301 if (ranges.size() != 1) {
302 LOG(ERROR) << base::StringPrintf(
303 "range at 0x%llx, size 0x%llx fully unreadable", address, size);
304 return;
305 }
306 if (ranges[0].base() != address || ranges[0].size() != size) {
307 LOG(ERROR) << base::StringPrintf(
308 "some of range at 0x%llx, size 0x%llx unreadable", address, size);
309 return;
310 }
311
312 // If we have already added this exact range, don't add it again. This is
313 // useful for the LDR module lists which are a set of doubly-linked lists, all
314 // pointing to the same module name strings.
315 // TODO(scottmg): A more general version of this, handling overlapping,
316 // contained, etc. https://code.google.com/p/crashpad/issues/detail?id=61.
317 for (const auto& memory_snapshot : *into) {
318 if (memory_snapshot->Address() == address &&
319 memory_snapshot->Size() == size) {
320 return;
321 }
322 }
323
324 internal::MemorySnapshotWin* memory_snapshot =
325 new internal::MemorySnapshotWin();
326 memory_snapshot->Initialize(&process_reader_, address, size);
327 into->push_back(memory_snapshot);
328 }
329
330 template <class Traits>
331 void ProcessSnapshotWin::AddMemorySnapshotForUNICODE_STRING(
332 const process_types::UNICODE_STRING<Traits>& us,
333 PointerVector<internal::MemorySnapshotWin>* into) {
334 AddMemorySnapshot(us.Buffer, us.Length, into);
335 }
336
337 template <class Traits>
338 void ProcessSnapshotWin::AddMemorySnapshotForLdrLIST_ENTRY(
339 const process_types::LIST_ENTRY<Traits>& le, size_t offset_of_member,
340 PointerVector<internal::MemorySnapshotWin>* into) {
341 // Walk the doubly-linked list of entries, adding the list memory itself, as
342 // well as pointed-to strings.
343 Traits::Pointer last = le.Blink;
344 process_types::LDR_DATA_TABLE_ENTRY<Traits> entry;
345 Traits::Pointer cur = le.Flink;
346 for (;;) {
347 // |cur| is the pointer to LIST_ENTRY embedded in the LDR_DATA_TABLE_ENTRY.
348 // So we need to offset back to the beginning of the structure.
349 if (!process_reader_.ReadMemory(
350 cur - offset_of_member, sizeof(entry), &entry)) {
351 return;
352 }
353 AddMemorySnapshot(cur - offset_of_member, sizeof(entry), into);
354 AddMemorySnapshotForUNICODE_STRING(entry.FullDllName, into);
355 AddMemorySnapshotForUNICODE_STRING(entry.BaseDllName, into);
356
357 process_types::LIST_ENTRY<Traits>* links =
358 reinterpret_cast<process_types::LIST_ENTRY<Traits>*>(
359 reinterpret_cast<unsigned char*>(&entry) + offset_of_member);
360 cur = links->Flink;
361 if (cur == last)
362 break;
363 }
364 }
365
366 WinVMSize ProcessSnapshotWin::DetermineSizeOfEnvironmentBlock(
367 WinVMAddress start_of_environment_block) {
368 // http://blogs.msdn.com/b/oldnewthing/archive/2010/02/03/9957320.aspx On
369 // newer OSs there's no stated limit, but in practice grabbing 32k characters
370 // should be more than enough.
371 std::wstring env_block;
372 env_block.resize(32768);
373 WinVMSize bytes_read = process_reader_.ReadAvailableMemory(
374 start_of_environment_block,
375 env_block.size() * sizeof(env_block[0]),
376 &env_block[0]);
377 env_block.resize(
378 static_cast<unsigned int>(bytes_read / sizeof(env_block[0])));
379 const wchar_t terminator[] = { 0, 0 };
380 size_t at = env_block.find(std::wstring(terminator, arraysize(terminator)));
381 if (at != std::wstring::npos)
382 env_block.resize(at + arraysize(terminator));
383
384 return env_block.size() * sizeof(env_block[0]);
385 }
386
217 } // namespace crashpad 387 } // namespace crashpad
OLDNEW
« no previous file with comments | « snapshot/win/process_snapshot_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698