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

Side by Side Diff: util/win/process_info.cc

Issue 1052813002: win: make CrashpadInfo retrievable (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: more fixes Created 5 years, 7 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 | « util/win/process_info.h ('k') | util/win/process_info_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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 PLOG(ERROR) << "ReadProcessMemory UNICODE_STRING"; 73 PLOG(ERROR) << "ReadProcessMemory UNICODE_STRING";
74 return false; 74 return false;
75 } 75 }
76 if (bytes_read != us.Length) { 76 if (bytes_read != us.Length) {
77 LOG(ERROR) << "ReadProcessMemory UNICODE_STRING incorrect size"; 77 LOG(ERROR) << "ReadProcessMemory UNICODE_STRING incorrect size";
78 return false; 78 return false;
79 } 79 }
80 return true; 80 return true;
81 } 81 }
82 82
83 template <class T> bool ReadStruct(HANDLE process, uintptr_t at, T* into) { 83 template <class T> bool ReadStruct(HANDLE process, WinVMAddress at, T* into) {
84 SIZE_T bytes_read; 84 SIZE_T bytes_read;
85 if (!ReadProcessMemory(process, 85 if (!ReadProcessMemory(process,
86 reinterpret_cast<const void*>(at), 86 reinterpret_cast<const void*>(at),
87 into, 87 into,
88 sizeof(T), 88 sizeof(T),
89 &bytes_read)) { 89 &bytes_read)) {
90 // We don't have a name for the type we're reading, so include the signature 90 // We don't have a name for the type we're reading, so include the signature
91 // to get the type of T. 91 // to get the type of T.
92 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__; 92 PLOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__;
93 return false; 93 return false;
94 } 94 }
95 if (bytes_read != sizeof(T)) { 95 if (bytes_read != sizeof(T)) {
96 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size"; 96 LOG(ERROR) << "ReadProcessMemory " << __FUNCSIG__ << " incorrect size";
97 return false; 97 return false;
98 } 98 }
99 return true; 99 return true;
100 } 100 }
101 101
102 } // namespace 102 } // namespace
103 103
104 template <class Traits> 104 template <class Traits>
105 bool ReadProcessData(HANDLE process, 105 bool ReadProcessData(HANDLE process,
106 uintptr_t peb_address_uintptr, 106 WinVMAddress peb_address_vmaddr,
107 ProcessInfo* process_info) { 107 ProcessInfo* process_info) {
108 Traits::Pointer peb_address; 108 Traits::Pointer peb_address;
109 if (!AssignIfInRange(&peb_address, peb_address_uintptr)) { 109 if (!AssignIfInRange(&peb_address, peb_address_vmaddr)) {
110 LOG(ERROR) << "peb_address_uintptr " << peb_address_uintptr 110 LOG(ERROR) << "peb_address_vmaddr " << peb_address_vmaddr
111 << " out of range"; 111 << " out of range";
112 return false; 112 return false;
113 } 113 }
114 114
115 // Try to read the process environment block. 115 // Try to read the process environment block.
116 process_types::PEB<Traits> peb; 116 process_types::PEB<Traits> peb;
117 if (!ReadStruct(process, peb_address, &peb)) 117 if (!ReadStruct(process, peb_address, &peb))
118 return false; 118 return false;
119 119
120 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters; 120 process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters;
121 if (!ReadStruct(process, peb.ProcessParameters, &process_parameters)) 121 if (!ReadStruct(process, peb.ProcessParameters, &process_parameters))
122 return false; 122 return false;
123 123
124 if (!ReadUnicodeString(process, 124 if (!ReadUnicodeString(process,
125 process_parameters.CommandLine, 125 process_parameters.CommandLine,
126 &process_info->command_line_)) { 126 &process_info->command_line_)) {
127 return false; 127 return false;
128 } 128 }
129 129
130 process_types::PEB_LDR_DATA<Traits> peb_ldr_data; 130 process_types::PEB_LDR_DATA<Traits> peb_ldr_data;
131 if (!ReadStruct(process, peb.Ldr, &peb_ldr_data)) 131 if (!ReadStruct(process, peb.Ldr, &peb_ldr_data))
132 return false; 132 return false;
133 133
134 std::wstring module;
135 process_types::LDR_DATA_TABLE_ENTRY<Traits> ldr_data_table_entry; 134 process_types::LDR_DATA_TABLE_ENTRY<Traits> ldr_data_table_entry;
136 135
137 // Include the first module in the memory order list to get our the main 136 // Include the first module in the memory order list to get our the main
138 // executable's name, as it's not included in initialization order below. 137 // executable's name, as it's not included in initialization order below.
139 if (!ReadStruct(process, 138 if (!ReadStruct(process,
140 reinterpret_cast<uintptr_t>( 139 reinterpret_cast<WinVMAddress>(
141 reinterpret_cast<const char*>( 140 reinterpret_cast<const char*>(
142 peb_ldr_data.InMemoryOrderModuleList.Flink) - 141 peb_ldr_data.InMemoryOrderModuleList.Flink) -
143 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, 142 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
144 InMemoryOrderLinks)), 143 InMemoryOrderLinks)),
145 &ldr_data_table_entry)) { 144 &ldr_data_table_entry)) {
146 return false; 145 return false;
147 } 146 }
148 if (!ReadUnicodeString(process, ldr_data_table_entry.FullDllName, &module)) 147 ProcessInfo::Module module;
148 if (!ReadUnicodeString(
149 process, ldr_data_table_entry.FullDllName, &module.name)) {
149 return false; 150 return false;
151 }
152 module.dll_base = ldr_data_table_entry.DllBase;
153 module.size = ldr_data_table_entry.SizeOfImage;
154 module.timestamp = ldr_data_table_entry.TimeDateStamp;
150 process_info->modules_.push_back(module); 155 process_info->modules_.push_back(module);
151 156
152 // Walk the PEB LDR structure (doubly-linked list) to get the list of loaded 157 // Walk the PEB LDR structure (doubly-linked list) to get the list of loaded
153 // modules. We use this method rather than EnumProcessModules to get the 158 // modules. We use this method rather than EnumProcessModules to get the
154 // modules in initialization order rather than memory order. 159 // modules in initialization order rather than memory order.
155 Traits::Pointer last = peb_ldr_data.InInitializationOrderModuleList.Blink; 160 Traits::Pointer last = peb_ldr_data.InInitializationOrderModuleList.Blink;
156 for (Traits::Pointer cur = peb_ldr_data.InInitializationOrderModuleList.Flink; 161 for (Traits::Pointer cur = peb_ldr_data.InInitializationOrderModuleList.Flink;
157 ; 162 ;
158 cur = ldr_data_table_entry.InInitializationOrderLinks.Flink) { 163 cur = ldr_data_table_entry.InInitializationOrderLinks.Flink) {
159 // |cur| is the pointer to the LIST_ENTRY embedded in the 164 // |cur| is the pointer to the LIST_ENTRY embedded in the
160 // LDR_DATA_TABLE_ENTRY, in the target process's address space. So we need 165 // LDR_DATA_TABLE_ENTRY, in the target process's address space. So we need
161 // to read from the target, and also offset back to the beginning of the 166 // to read from the target, and also offset back to the beginning of the
162 // structure. 167 // structure.
163 if (!ReadStruct(process, 168 if (!ReadStruct(process,
164 reinterpret_cast<uintptr_t>( 169 reinterpret_cast<WinVMAddress>(
165 reinterpret_cast<const char*>(cur) - 170 reinterpret_cast<const char*>(cur) -
166 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, 171 offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
167 InInitializationOrderLinks)), 172 InInitializationOrderLinks)),
168 &ldr_data_table_entry)) { 173 &ldr_data_table_entry)) {
169 break; 174 break;
170 } 175 }
171 // TODO(scottmg): Capture TimeDateStamp, Checksum, etc. too? 176 // TODO(scottmg): Capture Checksum, etc. too?
172 if (!ReadUnicodeString(process, ldr_data_table_entry.FullDllName, &module)) 177 if (!ReadUnicodeString(
178 process, ldr_data_table_entry.FullDllName, &module.name)) {
173 break; 179 break;
180 }
181 module.dll_base = ldr_data_table_entry.DllBase;
182 module.size = ldr_data_table_entry.SizeOfImage;
183 module.timestamp = ldr_data_table_entry.TimeDateStamp;
174 process_info->modules_.push_back(module); 184 process_info->modules_.push_back(module);
175 if (cur == last) 185 if (cur == last)
176 break; 186 break;
177 } 187 }
178 188
179 return true; 189 return true;
180 } 190 }
181 191
192 ProcessInfo::Module::Module() : name(), dll_base(0), size(0), timestamp() {
193 }
194
195 ProcessInfo::Module::~Module() {
196 }
197
182 ProcessInfo::ProcessInfo() 198 ProcessInfo::ProcessInfo()
183 : process_id_(), 199 : process_id_(),
184 inherited_from_process_id_(), 200 inherited_from_process_id_(),
185 command_line_(), 201 command_line_(),
186 modules_(), 202 modules_(),
187 is_64_bit_(false), 203 is_64_bit_(false),
188 is_wow64_(false), 204 is_wow64_(false),
189 initialized_() { 205 initialized_() {
190 } 206 }
191 207
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 return false; 260 return false;
245 } 261 }
246 process_id_ = process_basic_information.UniqueProcessId; 262 process_id_ = process_basic_information.UniqueProcessId;
247 inherited_from_process_id_ = 263 inherited_from_process_id_ =
248 process_basic_information.InheritedFromUniqueProcessId; 264 process_basic_information.InheritedFromUniqueProcessId;
249 265
250 // We now want to read the PEB to gather the rest of our information. The 266 // We now want to read the PEB to gather the rest of our information. The
251 // PebBaseAddress as returned above is what we want for 64-on-64 and 32-on-32, 267 // PebBaseAddress as returned above is what we want for 64-on-64 and 32-on-32,
252 // but for Wow64, we want to read the 32 bit PEB (a Wow64 process has both). 268 // but for Wow64, we want to read the 32 bit PEB (a Wow64 process has both).
253 // The address of this is found by a second call to NtQueryInformationProcess. 269 // The address of this is found by a second call to NtQueryInformationProcess.
254 uintptr_t peb_address = process_basic_information.PebBaseAddress; 270 WinVMAddress peb_address = process_basic_information.PebBaseAddress;
255 if (is_wow64_) { 271 if (is_wow64_) {
256 ULONG_PTR wow64_peb_address; 272 ULONG_PTR wow64_peb_address;
257 status = 273 status =
258 crashpad::NtQueryInformationProcess(process, 274 crashpad::NtQueryInformationProcess(process,
259 ProcessWow64Information, 275 ProcessWow64Information,
260 &wow64_peb_address, 276 &wow64_peb_address,
261 sizeof(wow64_peb_address), 277 sizeof(wow64_peb_address),
262 &bytes_returned); 278 &bytes_returned);
263 if (status < 0) { 279 if (status < 0) {
264 LOG(ERROR) << "NtQueryInformationProcess: status=" << status; 280 LOG(ERROR) << "NtQueryInformationProcess: status=" << status;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 318 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
303 return inherited_from_process_id_; 319 return inherited_from_process_id_;
304 } 320 }
305 321
306 bool ProcessInfo::CommandLine(std::wstring* command_line) const { 322 bool ProcessInfo::CommandLine(std::wstring* command_line) const {
307 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 323 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
308 *command_line = command_line_; 324 *command_line = command_line_;
309 return true; 325 return true;
310 } 326 }
311 327
312 bool ProcessInfo::Modules(std::vector<std::wstring>* modules) const { 328 bool ProcessInfo::Modules(std::vector<Module>* modules) const {
313 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 329 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
314 *modules = modules_; 330 *modules = modules_;
315 return true; 331 return true;
316 } 332 }
317 333
318 } // namespace crashpad 334 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/win/process_info.h ('k') | util/win/process_info_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698