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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |