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, |
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/pe_image_reader.h" | 15 #include "snapshot/win/pe_image_reader.h" |
16 | 16 |
17 #include <string.h> | 17 #include <string.h> |
18 | 18 |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
21 #include "base/strings/stringprintf.h" | |
22 #include "client/crashpad_info.h" | 21 #include "client/crashpad_info.h" |
23 #include "snapshot/win/process_reader_win.h" | 22 #include "snapshot/win/pe_image_resource_reader.h" |
24 #include "util/misc/pdb_structures.h" | 23 #include "util/misc/pdb_structures.h" |
25 #include "util/win/process_structs.h" | 24 #include "util/win/process_structs.h" |
26 | 25 |
27 namespace crashpad { | 26 namespace crashpad { |
28 | 27 |
29 namespace { | 28 namespace { |
30 | 29 |
31 std::string RangeToString(const CheckedWinAddressRange& range) { | |
32 return base::StringPrintf("[0x%llx + 0x%llx (%s)]", | |
33 range.Base(), | |
34 range.Size(), | |
35 range.Is64Bit() ? "64" : "32"); | |
36 } | |
37 | |
38 // Map from Traits to an IMAGE_NT_HEADERSxx. | 30 // Map from Traits to an IMAGE_NT_HEADERSxx. |
39 template <class Traits> | 31 template <class Traits> |
40 struct NtHeadersForTraits; | 32 struct NtHeadersForTraits; |
41 | 33 |
42 template <> | 34 template <> |
43 struct NtHeadersForTraits<process_types::internal::Traits32> { | 35 struct NtHeadersForTraits<process_types::internal::Traits32> { |
44 using type = IMAGE_NT_HEADERS32; | 36 using type = IMAGE_NT_HEADERS32; |
45 }; | 37 }; |
46 | 38 |
47 template <> | 39 template <> |
48 struct NtHeadersForTraits<process_types::internal::Traits64> { | 40 struct NtHeadersForTraits<process_types::internal::Traits64> { |
49 using type = IMAGE_NT_HEADERS64; | 41 using type = IMAGE_NT_HEADERS64; |
50 }; | 42 }; |
51 | 43 |
52 } // namespace | 44 } // namespace |
53 | 45 |
54 PEImageReader::PEImageReader() | 46 PEImageReader::PEImageReader() |
55 : process_reader_(nullptr), | 47 : module_subrange_reader_(), |
56 module_range_(), | |
57 module_name_(), | |
58 initialized_() { | 48 initialized_() { |
59 } | 49 } |
60 | 50 |
61 PEImageReader::~PEImageReader() { | 51 PEImageReader::~PEImageReader() { |
62 } | 52 } |
63 | 53 |
64 bool PEImageReader::Initialize(ProcessReaderWin* process_reader, | 54 bool PEImageReader::Initialize(ProcessReaderWin* process_reader, |
65 WinVMAddress address, | 55 WinVMAddress address, |
66 WinVMSize size, | 56 WinVMSize size, |
67 const std::string& module_name) { | 57 const std::string& module_name) { |
68 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 58 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
69 | 59 |
70 process_reader_ = process_reader; | 60 if (!module_subrange_reader_.Initialize( |
71 module_range_.SetRange(process_reader_->Is64Bit(), address, size); | 61 process_reader, address, size, module_name)) { |
72 if (!module_range_.IsValid()) { | |
73 LOG(WARNING) << "invalid module range for " << module_name << ": " | |
74 << RangeToString(module_range_); | |
75 return false; | 62 return false; |
76 } | 63 } |
77 module_name_ = module_name; | |
78 | 64 |
79 INITIALIZATION_STATE_SET_VALID(initialized_); | 65 INITIALIZATION_STATE_SET_VALID(initialized_); |
80 return true; | 66 return true; |
81 } | 67 } |
82 | 68 |
83 template <class Traits> | 69 template <class Traits> |
84 bool PEImageReader::GetCrashpadInfo( | 70 bool PEImageReader::GetCrashpadInfo( |
85 process_types::CrashpadInfo<Traits>* crashpad_info) const { | 71 process_types::CrashpadInfo<Traits>* crashpad_info) const { |
86 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 72 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
87 | 73 |
88 IMAGE_SECTION_HEADER section; | 74 IMAGE_SECTION_HEADER section; |
89 if (!GetSectionByName<typename NtHeadersForTraits<Traits>::type>("CPADinfo", | 75 if (!GetSectionByName<typename NtHeadersForTraits<Traits>::type>("CPADinfo", |
90 §ion)) { | 76 §ion)) { |
91 return false; | 77 return false; |
92 } | 78 } |
93 | 79 |
94 if (section.Misc.VirtualSize < sizeof(process_types::CrashpadInfo<Traits>)) { | 80 if (section.Misc.VirtualSize < sizeof(process_types::CrashpadInfo<Traits>)) { |
95 LOG(WARNING) << "small crashpad info section size " | 81 LOG(WARNING) << "small crashpad info section size " |
96 << section.Misc.VirtualSize << ", " << module_name_; | 82 << section.Misc.VirtualSize << ", " |
| 83 << module_subrange_reader_.name(); |
97 return false; | 84 return false; |
98 } | 85 } |
99 | 86 |
100 WinVMAddress crashpad_info_address = Address() + section.VirtualAddress; | 87 ProcessSubrangeReader crashpad_info_subrange_reader; |
101 CheckedWinAddressRange crashpad_info_range(process_reader_->Is64Bit(), | 88 const WinVMAddress crashpad_info_address = Address() + section.VirtualAddress; |
102 crashpad_info_address, | 89 if (!crashpad_info_subrange_reader.InitializeSubrange( |
103 section.Misc.VirtualSize); | 90 module_subrange_reader_, |
104 if (!crashpad_info_range.IsValid()) { | 91 crashpad_info_address, |
105 LOG(WARNING) << "invalid range for crashpad info: " | 92 section.Misc.VirtualSize, |
106 << RangeToString(crashpad_info_range); | 93 "crashpad_info")) { |
107 return false; | 94 return false; |
108 } | 95 } |
109 | 96 |
110 if (!module_range_.ContainsRange(crashpad_info_range)) { | 97 if (!crashpad_info_subrange_reader.ReadMemory( |
111 LOG(WARNING) << "crashpad info does not fall inside module " | 98 crashpad_info_address, |
112 << module_name_; | 99 sizeof(process_types::CrashpadInfo<Traits>), |
113 return false; | 100 crashpad_info)) { |
114 } | 101 LOG(WARNING) << "could not read crashpad info from " |
115 | 102 << module_subrange_reader_.name(); |
116 if (!process_reader_->ReadMemory(crashpad_info_address, | |
117 sizeof(process_types::CrashpadInfo<Traits>), | |
118 crashpad_info)) { | |
119 LOG(WARNING) << "could not read crashpad info " << module_name_; | |
120 return false; | 103 return false; |
121 } | 104 } |
122 | 105 |
123 if (crashpad_info->signature != CrashpadInfo::kSignature || | 106 if (crashpad_info->signature != CrashpadInfo::kSignature || |
124 crashpad_info->version < 1) { | 107 crashpad_info->version < 1) { |
125 LOG(WARNING) << "unexpected crashpad info data " << module_name_; | 108 LOG(WARNING) << "unexpected crashpad info data in " |
| 109 << module_subrange_reader_.name(); |
126 return false; | 110 return false; |
127 } | 111 } |
128 | 112 |
129 return true; | 113 return true; |
130 } | 114 } |
131 | 115 |
132 bool PEImageReader::DebugDirectoryInformation(UUID* uuid, | 116 bool PEImageReader::DebugDirectoryInformation(UUID* uuid, |
133 DWORD* age, | 117 DWORD* age, |
134 std::string* pdbname) const { | 118 std::string* pdbname) const { |
135 if (process_reader_->Is64Bit()) { | 119 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
136 return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS64>( | |
137 uuid, age, pdbname); | |
138 } else { | |
139 return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS32>( | |
140 uuid, age, pdbname); | |
141 } | |
142 } | |
143 | 120 |
144 template <class NtHeadersType> | 121 IMAGE_DATA_DIRECTORY data_directory; |
145 bool PEImageReader::ReadDebugDirectoryInformation(UUID* uuid, | 122 if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, &data_directory)) |
146 DWORD* age, | |
147 std::string* pdbname) const { | |
148 NtHeadersType nt_headers; | |
149 if (!ReadNtHeaders(&nt_headers, nullptr)) | |
150 return false; | 123 return false; |
151 | 124 |
152 if (nt_headers.FileHeader.SizeOfOptionalHeader < | |
153 offsetof(decltype(nt_headers.OptionalHeader), | |
154 DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) + | |
155 sizeof(nt_headers.OptionalHeader | |
156 .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) || | |
157 nt_headers.OptionalHeader.NumberOfRvaAndSizes <= | |
158 IMAGE_DIRECTORY_ENTRY_DEBUG) { | |
159 return false; | |
160 } | |
161 | |
162 const IMAGE_DATA_DIRECTORY& data_directory = | |
163 nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; | |
164 if (data_directory.VirtualAddress == 0 || data_directory.Size == 0) | |
165 return false; | |
166 IMAGE_DEBUG_DIRECTORY debug_directory; | 125 IMAGE_DEBUG_DIRECTORY debug_directory; |
167 if (data_directory.Size % sizeof(debug_directory) != 0) | 126 if (data_directory.Size % sizeof(debug_directory) != 0) |
168 return false; | 127 return false; |
169 for (size_t offset = 0; offset < data_directory.Size; | 128 for (size_t offset = 0; offset < data_directory.Size; |
170 offset += sizeof(debug_directory)) { | 129 offset += sizeof(debug_directory)) { |
171 if (!CheckedReadMemory(Address() + data_directory.VirtualAddress + offset, | 130 if (!module_subrange_reader_.ReadMemory( |
172 sizeof(debug_directory), | 131 Address() + data_directory.VirtualAddress + offset, |
173 &debug_directory)) { | 132 sizeof(debug_directory), |
174 LOG(WARNING) << "could not read data directory"; | 133 &debug_directory)) { |
| 134 LOG(WARNING) << "could not read data directory from " |
| 135 << module_subrange_reader_.name(); |
175 return false; | 136 return false; |
176 } | 137 } |
177 | 138 |
178 if (debug_directory.Type != IMAGE_DEBUG_TYPE_CODEVIEW) | 139 if (debug_directory.Type != IMAGE_DEBUG_TYPE_CODEVIEW) |
179 continue; | 140 continue; |
180 | 141 |
181 if (debug_directory.AddressOfRawData) { | 142 if (debug_directory.AddressOfRawData) { |
182 if (debug_directory.SizeOfData < sizeof(CodeViewRecordPDB70)) { | 143 if (debug_directory.SizeOfData < sizeof(CodeViewRecordPDB70)) { |
183 LOG(WARNING) << "CodeView debug entry of unexpected size"; | 144 LOG(WARNING) << "CodeView debug entry of unexpected size in " |
| 145 << module_subrange_reader_.name(); |
184 continue; | 146 continue; |
185 } | 147 } |
186 | 148 |
187 scoped_ptr<char[]> data(new char[debug_directory.SizeOfData]); | 149 scoped_ptr<char[]> data(new char[debug_directory.SizeOfData]); |
188 if (!CheckedReadMemory(Address() + debug_directory.AddressOfRawData, | 150 if (!module_subrange_reader_.ReadMemory( |
189 debug_directory.SizeOfData, | 151 Address() + debug_directory.AddressOfRawData, |
190 data.get())) { | 152 debug_directory.SizeOfData, |
191 LOG(WARNING) << "could not read debug directory"; | 153 data.get())) { |
| 154 LOG(WARNING) << "could not read debug directory from " |
| 155 << module_subrange_reader_.name(); |
192 return false; | 156 return false; |
193 } | 157 } |
194 | 158 |
195 if (*reinterpret_cast<DWORD*>(data.get()) != | 159 if (*reinterpret_cast<DWORD*>(data.get()) != |
196 CodeViewRecordPDB70::kSignature) { | 160 CodeViewRecordPDB70::kSignature) { |
197 LOG(WARNING) << "encountered non-7.0 CodeView debug record"; | 161 LOG(WARNING) << "encountered non-7.0 CodeView debug record in " |
| 162 << module_subrange_reader_.name(); |
198 continue; | 163 continue; |
199 } | 164 } |
200 | 165 |
201 CodeViewRecordPDB70* codeview = | 166 CodeViewRecordPDB70* codeview = |
202 reinterpret_cast<CodeViewRecordPDB70*>(data.get()); | 167 reinterpret_cast<CodeViewRecordPDB70*>(data.get()); |
203 *uuid = codeview->uuid; | 168 *uuid = codeview->uuid; |
204 *age = codeview->age; | 169 *age = codeview->age; |
205 // This is a NUL-terminated string encoded in the codepage of the system | 170 // This is a NUL-terminated string encoded in the codepage of the system |
206 // where the binary was linked. We have no idea what that was, so we just | 171 // where the binary was linked. We have no idea what that was, so we just |
207 // assume ASCII. | 172 // assume ASCII. |
208 *pdbname = std::string(reinterpret_cast<char*>(&codeview->pdb_name[0])); | 173 *pdbname = std::string(reinterpret_cast<char*>(&codeview->pdb_name[0])); |
209 return true; | 174 return true; |
210 } else if (debug_directory.PointerToRawData) { | 175 } else if (debug_directory.PointerToRawData) { |
211 // This occurs for non-PDB based debug information. We simply ignore these | 176 // This occurs for non-PDB based debug information. We simply ignore these |
212 // as we don't expect to encounter modules that will be in this format | 177 // as we don't expect to encounter modules that will be in this format |
213 // for which we'll actually have symbols. See | 178 // for which we'll actually have symbols. See |
214 // https://crashpad.chromium.org/bug/47. | 179 // https://crashpad.chromium.org/bug/47. |
215 } | 180 } |
216 } | 181 } |
217 | 182 |
218 return false; | 183 return false; |
219 } | 184 } |
220 | 185 |
| 186 bool PEImageReader::VSFixedFileInfo( |
| 187 VS_FIXEDFILEINFO* vs_fixed_file_info) const { |
| 188 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 189 |
| 190 IMAGE_DATA_DIRECTORY data_directory; |
| 191 if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, |
| 192 &data_directory)) { |
| 193 return false; |
| 194 } |
| 195 |
| 196 PEImageResourceReader resource_reader; |
| 197 if (!resource_reader.Initialize(module_subrange_reader_, data_directory)) { |
| 198 return false; |
| 199 } |
| 200 |
| 201 WinVMAddress address; |
| 202 WinVMSize size; |
| 203 if (!resource_reader.FindResourceByID( |
| 204 reinterpret_cast<uint16_t>(VS_FILE_INFO), // RT_VERSION |
| 205 VS_VERSION_INFO, |
| 206 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), |
| 207 &address, |
| 208 &size, |
| 209 nullptr)) { |
| 210 return false; |
| 211 } |
| 212 |
| 213 // This structure is not declared anywhere in the SDK, but is documented at |
| 214 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001.aspx. |
| 215 struct VS_VERSIONINFO { |
| 216 WORD wLength; |
| 217 WORD wValueLength; |
| 218 WORD wType; |
| 219 |
| 220 // The structure documentation on MSDN doesn’t show the [16], but it does |
| 221 // say that it’s supposed to be L"VS_VERSION_INFO", which is is in fact a |
| 222 // 16-character string (including its NUL terminator). |
| 223 WCHAR szKey[16]; |
| 224 |
| 225 WORD Padding1; |
| 226 VS_FIXEDFILEINFO Value; |
| 227 |
| 228 // Don’t include Children or the Padding2 that precedes it, because they may |
| 229 // not be present. |
| 230 // WORD Padding2; |
| 231 // WORD Children; |
| 232 }; |
| 233 VS_VERSIONINFO version_info; |
| 234 |
| 235 if (size < sizeof(version_info)) { |
| 236 LOG(WARNING) << "version info size " << size |
| 237 << " too small for structure of size " << sizeof(version_info) |
| 238 << " in " << module_subrange_reader_.name(); |
| 239 return false; |
| 240 } |
| 241 |
| 242 if (!module_subrange_reader_.ReadMemory( |
| 243 address, sizeof(version_info), &version_info)) { |
| 244 LOG(WARNING) << "could not read version info from " |
| 245 << module_subrange_reader_.name(); |
| 246 return false; |
| 247 } |
| 248 |
| 249 if (version_info.wLength < sizeof(version_info) || |
| 250 version_info.wValueLength != sizeof(version_info.Value) || |
| 251 version_info.wType != 0 || |
| 252 wcsncmp(version_info.szKey, |
| 253 L"VS_VERSION_INFO", |
| 254 arraysize(version_info.szKey)) != 0) { |
| 255 LOG(WARNING) << "unexpected VS_VERSIONINFO in " |
| 256 << module_subrange_reader_.name(); |
| 257 return false; |
| 258 } |
| 259 |
| 260 if (version_info.Value.dwSignature != VS_FFI_SIGNATURE || |
| 261 version_info.Value.dwStrucVersion != VS_FFI_STRUCVERSION) { |
| 262 LOG(WARNING) << "unexpected VS_FIXEDFILEINFO in " |
| 263 << module_subrange_reader_.name(); |
| 264 return false; |
| 265 } |
| 266 |
| 267 *vs_fixed_file_info = version_info.Value; |
| 268 vs_fixed_file_info->dwFileFlags &= vs_fixed_file_info->dwFileFlagsMask; |
| 269 return true; |
| 270 } |
| 271 |
221 template <class NtHeadersType> | 272 template <class NtHeadersType> |
222 bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers, | 273 bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers, |
223 WinVMAddress* nt_headers_address) const { | 274 WinVMAddress* nt_headers_address) const { |
224 IMAGE_DOS_HEADER dos_header; | 275 IMAGE_DOS_HEADER dos_header; |
225 if (!CheckedReadMemory(Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) { | 276 if (!module_subrange_reader_.ReadMemory( |
226 LOG(WARNING) << "could not read dos header of " << module_name_; | 277 Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) { |
| 278 LOG(WARNING) << "could not read dos header from " |
| 279 << module_subrange_reader_.name(); |
227 return false; | 280 return false; |
228 } | 281 } |
229 | 282 |
230 if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) { | 283 if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) { |
231 LOG(WARNING) << "invalid e_magic in dos header of " << module_name_; | 284 LOG(WARNING) << "invalid e_magic in dos header of " |
| 285 << module_subrange_reader_.name(); |
232 return false; | 286 return false; |
233 } | 287 } |
234 | 288 |
235 WinVMAddress local_nt_headers_address = Address() + dos_header.e_lfanew; | 289 WinVMAddress local_nt_headers_address = Address() + dos_header.e_lfanew; |
236 if (!CheckedReadMemory( | 290 if (!module_subrange_reader_.ReadMemory( |
237 local_nt_headers_address, sizeof(NtHeadersType), nt_headers)) { | 291 local_nt_headers_address, sizeof(NtHeadersType), nt_headers)) { |
238 LOG(WARNING) << "could not read nt headers of " << module_name_; | 292 LOG(WARNING) << "could not read nt headers from " |
| 293 << module_subrange_reader_.name(); |
239 return false; | 294 return false; |
240 } | 295 } |
241 | 296 |
242 if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { | 297 if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { |
243 LOG(WARNING) << "invalid signature in nt headers of " << module_name_; | 298 LOG(WARNING) << "invalid signature in nt headers of " |
| 299 << module_subrange_reader_.name(); |
244 return false; | 300 return false; |
245 } | 301 } |
246 | 302 |
247 if (nt_headers_address) | 303 if (nt_headers_address) |
248 *nt_headers_address = local_nt_headers_address; | 304 *nt_headers_address = local_nt_headers_address; |
249 | 305 |
250 return true; | 306 return true; |
251 } | 307 } |
252 | 308 |
253 template <class NtHeadersType> | 309 template <class NtHeadersType> |
254 bool PEImageReader::GetSectionByName(const std::string& name, | 310 bool PEImageReader::GetSectionByName(const std::string& name, |
255 IMAGE_SECTION_HEADER* section) const { | 311 IMAGE_SECTION_HEADER* section) const { |
256 if (name.size() > sizeof(section->Name)) { | 312 if (name.size() > sizeof(section->Name)) { |
257 LOG(WARNING) << "supplied section name too long " << name; | 313 LOG(WARNING) << "supplied section name too long " << name; |
258 return false; | 314 return false; |
259 } | 315 } |
260 | 316 |
261 NtHeadersType nt_headers; | 317 NtHeadersType nt_headers; |
262 WinVMAddress nt_headers_address; | 318 WinVMAddress nt_headers_address; |
263 if (!ReadNtHeaders(&nt_headers, &nt_headers_address)) | 319 if (!ReadNtHeaders(&nt_headers, &nt_headers_address)) |
264 return false; | 320 return false; |
265 | 321 |
266 WinVMAddress first_section_address = | 322 WinVMAddress first_section_address = |
267 nt_headers_address + offsetof(NtHeadersType, OptionalHeader) + | 323 nt_headers_address + offsetof(NtHeadersType, OptionalHeader) + |
268 nt_headers.FileHeader.SizeOfOptionalHeader; | 324 nt_headers.FileHeader.SizeOfOptionalHeader; |
269 for (DWORD i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) { | 325 for (DWORD i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) { |
270 WinVMAddress section_address = | 326 WinVMAddress section_address = |
271 first_section_address + sizeof(IMAGE_SECTION_HEADER) * i; | 327 first_section_address + sizeof(IMAGE_SECTION_HEADER) * i; |
272 if (!CheckedReadMemory( | 328 if (!module_subrange_reader_.ReadMemory( |
273 section_address, sizeof(IMAGE_SECTION_HEADER), section)) { | 329 section_address, sizeof(IMAGE_SECTION_HEADER), section)) { |
274 LOG(WARNING) << "could not read section " << i << " of " << module_name_; | 330 LOG(WARNING) << "could not read section " << i << " from " |
| 331 << module_subrange_reader_.name(); |
275 return false; | 332 return false; |
276 } | 333 } |
277 if (strncmp(reinterpret_cast<const char*>(section->Name), | 334 if (strncmp(reinterpret_cast<const char*>(section->Name), |
278 name.c_str(), | 335 name.c_str(), |
279 sizeof(section->Name)) == 0) { | 336 sizeof(section->Name)) == 0) { |
280 return true; | 337 return true; |
281 } | 338 } |
282 } | 339 } |
283 | 340 |
284 return false; | 341 return false; |
285 } | 342 } |
286 | 343 |
287 bool PEImageReader::CheckedReadMemory(WinVMAddress address, | 344 bool PEImageReader::ImageDataDirectoryEntry(size_t index, |
288 WinVMSize size, | 345 IMAGE_DATA_DIRECTORY* entry) const { |
289 void* into) const { | 346 bool rv; |
290 CheckedWinAddressRange read_range(process_reader_->Is64Bit(), address, size); | 347 if (module_subrange_reader_.Is64Bit()) { |
291 if (!read_range.IsValid()) { | 348 rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS64>(index, entry); |
292 LOG(WARNING) << "invalid read range: " << RangeToString(read_range); | 349 } else { |
| 350 rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS32>(index, entry); |
| 351 } |
| 352 |
| 353 return rv && entry->VirtualAddress != 0 && entry->Size != 0; |
| 354 } |
| 355 |
| 356 template <class NtHeadersType> |
| 357 bool PEImageReader::ImageDataDirectoryEntryT( |
| 358 size_t index, |
| 359 IMAGE_DATA_DIRECTORY* entry) const { |
| 360 NtHeadersType nt_headers; |
| 361 if (!ReadNtHeaders(&nt_headers, nullptr)) { |
293 return false; | 362 return false; |
294 } | 363 } |
295 if (!module_range_.ContainsRange(read_range)) { | 364 |
296 LOG(WARNING) << "attempt to read outside of module " << module_name_ | 365 if (nt_headers.FileHeader.SizeOfOptionalHeader < |
297 << " at range: " << RangeToString(read_range); | 366 offsetof(decltype(nt_headers.OptionalHeader), DataDirectory[index]) + |
| 367 sizeof(nt_headers.OptionalHeader.DataDirectory[index]) || |
| 368 nt_headers.OptionalHeader.NumberOfRvaAndSizes <= index) { |
298 return false; | 369 return false; |
299 } | 370 } |
300 return process_reader_->ReadMemory(address, size, into); | 371 |
| 372 *entry = nt_headers.OptionalHeader.DataDirectory[index]; |
| 373 return true; |
301 } | 374 } |
302 | 375 |
303 // Explicit instantiations with the only 2 valid template arguments to avoid | 376 // Explicit instantiations with the only 2 valid template arguments to avoid |
304 // putting the body of the function in the header. | 377 // putting the body of the function in the header. |
305 template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits32>( | 378 template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits32>( |
306 process_types::CrashpadInfo<process_types::internal::Traits32>* | 379 process_types::CrashpadInfo<process_types::internal::Traits32>* |
307 crashpad_info) const; | 380 crashpad_info) const; |
308 template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits64>( | 381 template bool PEImageReader::GetCrashpadInfo<process_types::internal::Traits64>( |
309 process_types::CrashpadInfo<process_types::internal::Traits64>* | 382 process_types::CrashpadInfo<process_types::internal::Traits64>* |
310 crashpad_info) const; | 383 crashpad_info) const; |
311 | 384 |
312 } // namespace crashpad | 385 } // namespace crashpad |
OLD | NEW |