1 : // Copyright 2012 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (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
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : #include "syzygy/pe/pe_file.h"
15 :
16 : #include "base/file_util.h"
17 : #include "base/logging.h"
18 :
19 : namespace {
20 :
21 E : bool ReadAt(FILE* file, size_t pos, void* buf, size_t len) {
22 E : if (fseek(file, pos, SEEK_SET) != 0)
23 i : return false;
24 :
25 E : size_t read = fread(buf, 1, len, file);
26 E : if (read != len)
27 i : return false;
28 :
29 E : return true;
30 E : }
31 :
32 : } // namespace
33 :
34 : namespace pe {
35 :
36 : const size_t kInvalidSection = -1;
37 :
38 : using core::AbsoluteAddress;
39 : using core::FileOffsetAddress;
40 : using core::RelativeAddress;
41 :
42 : PEFile::PEFile()
43 : : dos_header_(NULL),
44 : nt_headers_(NULL),
45 E : section_headers_(NULL) {
46 E : }
47 :
48 E : PEFile::~PEFile() {
49 E : }
50 :
51 E : bool PEFile::Init(const FilePath& path) {
52 E : path_ = path;
53 E : FILE* file = file_util::OpenFile(path, "rb");
54 E : if (file == NULL) {
55 E : LOG(ERROR) << "Failed to open file " << path.value();
56 E : return false;
57 : }
58 :
59 E : bool success = ReadHeaders(file);
60 E : if (success)
61 E : success = ReadSections(file);
62 :
63 E : file_util::CloseFile(file);
64 :
65 E : return success;
66 E : }
67 :
68 E : void PEFile::GetSignature(Signature* signature) const {
69 E : DCHECK(signature != NULL);
70 E : DCHECK(nt_headers_ != NULL);
71 :
72 : // TODO(chrisha): Make GetSignature return a bool, and update all calling
73 : // sites.
74 E : FilePath abs_path(path_);
75 E : CHECK(file_util::AbsolutePath(&abs_path));
76 :
77 E : signature->path = abs_path.value();
78 : signature->base_address =
79 E : AbsoluteAddress(nt_headers_->OptionalHeader.ImageBase);
80 E : signature->module_size = nt_headers_->OptionalHeader.SizeOfImage;
81 E : signature->module_time_date_stamp = nt_headers_->FileHeader.TimeDateStamp;
82 E : signature->module_checksum = nt_headers_->OptionalHeader.CheckSum;
83 E : }
84 :
85 E : bool PEFile::Contains(RelativeAddress rel, size_t len) const {
86 E : const ImageAddressSpace::Range range(rel, len);
87 E : return image_data_.FindContaining(range) != image_data_.ranges().end();
88 E : }
89 :
90 E : bool PEFile::Contains(AbsoluteAddress abs, size_t len) const {
91 E : RelativeAddress rel;
92 E : return Translate(abs, &rel) && Contains(rel, len);
93 E : }
94 :
95 E : size_t PEFile::GetSectionIndex(RelativeAddress rel, size_t len) const {
96 E : const ImageAddressSpace::Range range(rel, len);
97 : ImageAddressSpace::RangeMap::const_iterator it =
98 E : image_data_.FindContaining(range);
99 E : if (it == image_data_.ranges().end())
100 E : return kInvalidSection;
101 E : return it->second.id;
102 E : }
103 :
104 E : size_t PEFile::GetSectionIndex(AbsoluteAddress abs, size_t len) const {
105 E : RelativeAddress rel;
106 E : Translate(abs, &rel);
107 E : return GetSectionIndex(rel, len);
108 E : }
109 :
110 : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(
111 E : RelativeAddress rel, size_t len) const {
112 E : size_t id = GetSectionIndex(rel, len);
113 E : if (id == kInvalidSection)
114 E : return NULL;
115 E : DCHECK(id < nt_headers_->FileHeader.NumberOfSections);
116 E : return section_headers_ + id;
117 E : }
118 :
119 : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(
120 E : AbsoluteAddress abs, size_t len) const {
121 E : RelativeAddress rel;
122 E : Translate(abs, &rel);
123 E : return GetSectionHeader(rel, len);
124 E : }
125 :
126 E : size_t PEFile::GetSectionIndex(const char* name) const {
127 E : size_t section_count = nt_headers_->FileHeader.NumberOfSections;
128 E : for (size_t i = 0; i < section_count; ++i) {
129 E : const IMAGE_SECTION_HEADER* header = section_headers_ + i;
130 : if (strncmp(reinterpret_cast<const char*>(header->Name), name,
131 E : IMAGE_SIZEOF_SHORT_NAME) == 0)
132 E : return i;
133 E : }
134 E : return kInvalidSection;
135 E : }
136 :
137 : std::string PEFile::GetSectionName(
138 E : const IMAGE_SECTION_HEADER& section) {
139 E : const char* name = reinterpret_cast<const char*>(section.Name);
140 E : return std::string(name, strnlen(name, arraysize(section.Name)));
141 E : }
142 :
143 E : std::string PEFile::GetSectionName(size_t section_index) const {
144 E : DCHECK_LT(section_index, nt_headers_->FileHeader.NumberOfSections);
145 :
146 E : const IMAGE_SECTION_HEADER* section = section_headers_ + section_index;
147 E : return GetSectionName(*section);
148 E : }
149 :
150 E : const IMAGE_SECTION_HEADER* PEFile::GetSectionHeader(const char* name) const {
151 E : size_t id = GetSectionIndex(name);
152 E : if (id == kInvalidSection)
153 E : return NULL;
154 E : return section_headers_ + id;
155 E : }
156 :
157 E : bool PEFile::ReadHeaders(FILE* file) {
158 : // Read the DOS header.
159 E : IMAGE_DOS_HEADER dos_header = {};
160 E : if (!ReadAt(file, 0, &dos_header, sizeof(dos_header))) {
161 i : LOG(ERROR) << "Unable to read DOS header";
162 i : return false;
163 : }
164 :
165 : // And the NT headers.
166 E : IMAGE_NT_HEADERS nt_headers = {};
167 E : size_t pos = dos_header.e_lfanew;
168 E : if (!ReadAt(file, pos, &nt_headers, sizeof(nt_headers))) {
169 i : LOG(ERROR) << "Unable to read NT headers";
170 i : return false;
171 : }
172 :
173 : // We now know how large the headers are, so create a range for them.
174 E : size_t header_size = nt_headers.OptionalHeader.SizeOfHeaders;
175 E : ImageAddressSpace::Range header_range(RelativeAddress(0), header_size);
176 E : ImageAddressSpace::RangeMap::iterator it;
177 E : bool inserted = image_data_.Insert(header_range, SectionInfo(), &it);
178 E : DCHECK(inserted);
179 E : if (!inserted) {
180 i : LOG(ERROR) << "Unable to create header range";
181 i : return false;
182 : }
183 :
184 E : SectionBuffer& header = it->second.buffer;
185 E : header.resize(header_size);
186 E : if (!ReadAt(file, 0, &header[0], header_size)) {
187 i : LOG(ERROR) << "Unable to read header data";
188 i : return false;
189 : }
190 :
191 : // TODO(siggi): Validate these pointers!
192 E : dos_header_ = reinterpret_cast<IMAGE_DOS_HEADER*>(&header.at(0));
193 : nt_headers_ =
194 E : reinterpret_cast<IMAGE_NT_HEADERS*>(&header.at(dos_header_->e_lfanew));
195 E : section_headers_ = IMAGE_FIRST_SECTION(nt_headers_);
196 :
197 E : return true;
198 E : }
199 :
200 E : bool PEFile::ReadSections(FILE* file) {
201 E : DCHECK(nt_headers_ != NULL);
202 E : DCHECK(section_headers_ != NULL);
203 :
204 E : size_t num_sections = nt_headers_->FileHeader.NumberOfSections;
205 E : for (size_t i = 0; i < num_sections; ++i) {
206 E : const IMAGE_SECTION_HEADER* hdr = section_headers_ + i;
207 : // Insert the range for the new section.
208 : ImageAddressSpace::Range section_range(RelativeAddress(hdr->VirtualAddress),
209 E : hdr->Misc.VirtualSize);
210 E : ImageAddressSpace::RangeMap::iterator it;
211 E : if (!image_data_.Insert(section_range, SectionInfo(), &it)) {
212 i : LOG(ERROR) << "Unable to insert range for section " << hdr->Name;
213 i : return false;
214 : }
215 :
216 E : it->second.id = i;
217 E : SectionBuffer& buf = it->second.buffer;
218 E : if (hdr->SizeOfRawData == 0)
219 i : continue;
220 :
221 E : buf.resize(hdr->SizeOfRawData);
222 E : if (!ReadAt(file, hdr->PointerToRawData, &buf.at(0), hdr->SizeOfRawData)) {
223 i : LOG(ERROR) << "Unable to read data for section " << hdr->Name;
224 i : return false;
225 : }
226 E : }
227 :
228 E : return true;
229 E : }
230 :
231 E : bool PEFile::Translate(RelativeAddress rel, AbsoluteAddress* abs) const {
232 E : DCHECK(abs != NULL);
233 E : if (rel.value() >= nt_headers_->OptionalHeader.SizeOfImage)
234 E : return false;
235 E : abs->set_value(rel.value() + nt_headers_->OptionalHeader.ImageBase);
236 E : return true;
237 E : }
238 :
239 E : bool PEFile::Translate(AbsoluteAddress abs, RelativeAddress* rel) const {
240 E : DCHECK(rel != NULL);
241 E : size_t rel_addr = abs.value() - nt_headers_->OptionalHeader.ImageBase;
242 E : if (rel_addr >= nt_headers_->OptionalHeader.SizeOfImage)
243 E : return false;
244 E : rel->set_value(rel_addr);
245 E : return true;
246 E : }
247 :
248 E : bool PEFile::Translate(FileOffsetAddress offs, RelativeAddress* rel) const {
249 E : DCHECK(rel != NULL);
250 :
251 : // The first "previous section" is the headers.
252 E : RelativeAddress previous_section_start(0);
253 E : FileOffsetAddress previous_section_file_start(0);
254 E : const IMAGE_SECTION_HEADER* previous_section = NULL;
255 E : for (size_t i = 0; i < nt_headers_->FileHeader.NumberOfSections; ++i) {
256 E : if (offs.value() < section_headers_[i].PointerToRawData)
257 E : break;
258 :
259 E : previous_section_start.set_value(section_headers_[i].VirtualAddress);
260 E : previous_section_file_start.set_value(section_headers_[i].PointerToRawData);
261 E : previous_section = section_headers_ + i;
262 E : }
263 :
264 E : size_t section_offset = offs - previous_section_file_start;
265 : if (previous_section != NULL &&
266 E : section_offset >= previous_section->SizeOfRawData) {
267 E : return false;
268 : }
269 :
270 E : *rel = previous_section_start + section_offset;
271 :
272 E : return true;
273 E : }
274 :
275 E : bool PEFile::Translate(RelativeAddress rel, FileOffsetAddress* offs) const {
276 E : DCHECK(offs != NULL);
277 :
278 : // In the headers?
279 E : if (rel.value() < section_header(0)->VirtualAddress) {
280 E : offs->set_value(rel.value());
281 E : return true;
282 : }
283 :
284 : // Find the section in which this address lies.
285 E : const IMAGE_SECTION_HEADER* section = GetSectionHeader(rel, 1);
286 E : if (section == NULL)
287 E : return false;
288 :
289 : // Calculate the offset of this address and ensure it can be expressed as
290 : // a file offset (lies in the explicit data part of the section, not the
291 : // implicit virtual data at the end).
292 E : size_t section_offset = rel.value() - section->VirtualAddress;
293 E : if (section_offset >= section->SizeOfRawData)
294 E : return false;
295 :
296 E : offs->set_value(section->PointerToRawData + section_offset);
297 :
298 E : return true;
299 E : }
300 :
301 E : const uint8* PEFile::GetImageData(RelativeAddress rel, size_t len) const {
302 E : DCHECK(nt_headers_ != NULL);
303 :
304 E : ImageAddressSpace::Range range(rel, len);
305 : ImageAddressSpace::RangeMap::const_iterator it(
306 E : image_data_.FindContaining(range));
307 :
308 E : if (it != image_data_.ranges().end()) {
309 E : ptrdiff_t offs = rel - it->first.start();
310 E : DCHECK_GE(offs, 0);
311 :
312 E : const SectionBuffer& buf = it->second.buffer;
313 E : if (offs + len <= buf.size())
314 E : return &buf.at(offs);
315 : }
316 :
317 E : return NULL;
318 E : }
319 :
320 E : const uint8* PEFile::GetImageData(AbsoluteAddress abs, size_t len) const {
321 E : RelativeAddress rel;
322 E : if (Translate(abs, &rel))
323 E : return GetImageData(rel, len);
324 :
325 i : return NULL;
326 E : }
327 :
328 E : uint8* PEFile::GetImageData(RelativeAddress rel, size_t len) {
329 : return const_cast<uint8*>(
330 E : static_cast<const PEFile*>(this)->GetImageData(rel, len));
331 E : }
332 :
333 E : uint8* PEFile::GetImageData(AbsoluteAddress abs, size_t len) {
334 : return const_cast<uint8*>(
335 E : static_cast<const PEFile*>(this)->GetImageData(abs, len));
336 E : }
337 :
338 E : bool PEFile::ReadImage(RelativeAddress rel, void* data, size_t len) const {
339 E : DCHECK(data != NULL);
340 E : const uint8* buf = GetImageData(rel, len);
341 E : if (buf == NULL)
342 i : return false;
343 :
344 E : memcpy(data, buf, len);
345 E : return true;
346 E : }
347 :
348 E : bool PEFile::ReadImage(AbsoluteAddress abs, void* data, size_t len) const {
349 E : RelativeAddress rel;
350 E : if (!Translate(abs, &rel))
351 i : return false;
352 :
353 E : return ReadImage(rel, data, len);
354 E : }
355 :
356 E : bool PEFile::ReadImageString(RelativeAddress rel, std::string* str) const {
357 E : DCHECK(nt_headers_ != NULL);
358 E : str->clear();
359 :
360 : // Locate the range that contains the first byte of the string.
361 E : ImageAddressSpace::Range range(rel, 1);
362 : ImageAddressSpace::RangeMap::const_iterator it(
363 E : image_data_.FindContaining(range));
364 :
365 E : if (it != image_data_.ranges().end()) {
366 E : ptrdiff_t offs = rel - it->first.start();
367 E : DCHECK_GE(offs, 0);
368 : // Stash the start position.
369 E : const SectionBuffer& buf = it->second.buffer;
370 E : const char* begin = reinterpret_cast<const char*>(&buf.at(offs));
371 : // And loop through until we find a zero-terminating byte,
372 : // or run off the end.
373 E : for (; static_cast<size_t>(offs) < buf.size() && buf.at(offs); ++offs) {
374 : // Intentionally empty.
375 E : }
376 :
377 E : if (static_cast<size_t>(offs) == buf.size())
378 i : return false;
379 :
380 E : str->assign(begin);
381 E : return true;
382 : }
383 :
384 i : return false;
385 E : }
386 :
387 E : bool PEFile::ReadImageString(AbsoluteAddress abs, std::string* str) const {
388 E : RelativeAddress rel;
389 E : if (!Translate(abs, &rel))
390 i : return false;
391 :
392 E : return ReadImageString(rel, str);
393 E : }
394 :
395 E : bool PEFile::DecodeRelocs(RelocSet* relocs) const {
396 E : DCHECK(nt_headers_ != NULL);
397 E : DCHECK(relocs != NULL);
398 :
399 : // Walk the relocs.
400 : IMAGE_DATA_DIRECTORY dir =
401 : nt_headers_->OptionalHeader.DataDirectory[
402 E : IMAGE_DIRECTORY_ENTRY_BASERELOC];
403 E : RelativeAddress offs(dir.VirtualAddress);
404 E : RelativeAddress end(offs + dir.Size);
405 :
406 E : const IMAGE_BASE_RELOCATION* hdr = NULL;
407 E : for (; offs < end; offs += hdr->SizeOfBlock) {
408 : // Read the next header.
409 : hdr = reinterpret_cast<const IMAGE_BASE_RELOCATION*>(
410 E : GetImageData(offs, sizeof(hdr)));
411 E : if (hdr == NULL) {
412 i : LOG(ERROR) << "Failed to read relocation block header.";
413 i : return false;
414 : }
415 :
416 : // Read the entries.
417 E : size_t num_relocs = (hdr->SizeOfBlock - sizeof(*hdr)) / sizeof(WORD);
418 : const WORD* reloc_block = reinterpret_cast<const WORD*>(
419 E : GetImageData(offs + sizeof(*hdr), sizeof(*reloc_block) * num_relocs));
420 E : if (reloc_block == NULL) {
421 i : LOG(ERROR) << "Failed to read relocation entries.";
422 i : return false;
423 : }
424 :
425 : // Walk the entries.
426 E : for (size_t i = 0; i < num_relocs; ++i) {
427 E : uint8 type = reloc_block[i] >> 12;
428 E : uint16 offs = reloc_block[i] & 0xFFF;
429 : DCHECK(type == IMAGE_REL_BASED_HIGHLOW ||
430 E : type == IMAGE_REL_BASED_ABSOLUTE);
431 :
432 E : if (type == IMAGE_REL_BASED_HIGHLOW) {
433 : // Record the entry.
434 E : relocs->insert(RelativeAddress(hdr->VirtualAddress) + offs);
435 : }
436 E : }
437 E : }
438 :
439 E : DCHECK(offs == end);
440 E : return true;
441 E : }
442 :
443 E : bool PEFile::ReadRelocs(const RelocSet& relocs, RelocMap* reloc_values) const {
444 E : RelocSet::const_iterator it(relocs.begin());
445 E : for (; it != relocs.end(); ++it) {
446 : const AbsoluteAddress* abs = reinterpret_cast<const AbsoluteAddress*>(
447 E : GetImageData(*it, sizeof(*abs)));
448 E : if (abs == NULL) {
449 i : LOG(ERROR) << "Failed to read reloc at " << it->value();
450 i : return false;
451 : }
452 :
453 E : reloc_values->insert(std::make_pair(*it, *abs));
454 E : }
455 :
456 E : return true;
457 E : }
458 :
459 E : bool PEFile::DecodeExports(ExportInfoVector* exports) const {
460 E : DCHECK(exports != NULL);
461 :
462 : IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
463 E : DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
464 E : RelativeAddress addr(dir.VirtualAddress);
465 E : RelativeAddress end(addr + dir.Size);
466 :
467 E : if (addr.value() == 0)
468 i : return true;
469 :
470 : const IMAGE_EXPORT_DIRECTORY* export_dir =
471 : reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(
472 E : GetImageData(addr, sizeof(export_dir)));
473 E : if (export_dir == NULL) {
474 i : LOG(ERROR) << "Unable to read export directory";
475 i : return false;
476 : }
477 :
478 : const RelativeAddress* functions =
479 : reinterpret_cast<const RelativeAddress*>(
480 : GetImageData(RelativeAddress(export_dir->AddressOfFunctions),
481 E : sizeof(*functions) * export_dir->NumberOfFunctions));
482 E : if (functions == NULL) {
483 i : LOG(ERROR) << "Unable to read export functions.";
484 i : return false;
485 : }
486 :
487 : const RelativeAddress* names =
488 : reinterpret_cast<const RelativeAddress*>(
489 : GetImageData(RelativeAddress(export_dir->AddressOfNames),
490 E : sizeof(*functions) * export_dir->NumberOfNames));
491 E : if (names == NULL) {
492 i : LOG(ERROR) << "Unable to read export names.";
493 i : return false;
494 : }
495 :
496 : const WORD* name_ordinals =
497 : reinterpret_cast<const WORD*>(
498 : GetImageData(RelativeAddress(export_dir->AddressOfNameOrdinals),
499 E : sizeof(*functions) * export_dir->NumberOfNames));
500 E : if (names == NULL) {
501 i : LOG(ERROR) << "Unable to read name ordinals.";
502 i : return false;
503 : }
504 :
505 E : for (size_t index = 0; index < export_dir->NumberOfFunctions; ++index) {
506 : // Is it a blank entry?
507 E : if (functions[index] != RelativeAddress(0)) {
508 E : ExportInfo info;
509 E : info.ordinal = index + 1;
510 :
511 E : RelativeAddress function = functions[index];
512 : // Is it a forward?
513 E : if (function >= addr && function < end) {
514 E : if (!ReadImageString(function, &info.forward)) {
515 i : LOG(ERROR) << "Unable to read export forward string";
516 i : return false;
517 : }
518 E : } else {
519 E : info.function = function;
520 : }
521 :
522 : // Does it have a name?
523 E : for (size_t i = 0; i < export_dir->NumberOfNames; ++i) {
524 E : if (name_ordinals[i] == index) {
525 E : if (!ReadImageString(names[i], &info.name)) {
526 i : LOG(ERROR) << "Unable to read export name";
527 i : return false;
528 : }
529 E : break;
530 : }
531 E : }
532 :
533 E : exports->push_back(info);
534 E : }
535 E : }
536 :
537 E : return true;
538 E : }
539 :
540 E : bool PEFile::DecodeImports(ImportDllVector* imports) const {
541 E : DCHECK(imports != NULL);
542 :
543 : // Walk the import thunks.
544 : IMAGE_DATA_DIRECTORY dir = nt_headers_->OptionalHeader.
545 E : DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
546 E : RelativeAddress offs(dir.VirtualAddress);
547 E : RelativeAddress end(offs + dir.Size);
548 :
549 E : const IMAGE_IMPORT_DESCRIPTOR* import_desc = NULL;
550 E : for (; offs < end; offs += sizeof(*import_desc)) {
551 : import_desc = reinterpret_cast<const IMAGE_IMPORT_DESCRIPTOR*>(
552 E : GetImageData(offs, sizeof(*import_desc)));
553 E : if (import_desc == NULL) {
554 i : LOG(ERROR) << "Unable to read import descriptor";
555 i : return false;
556 : }
557 :
558 E : if (import_desc->Characteristics == 0 && import_desc->FirstThunk == 0) {
559 : // This is the last chunk, bail the loop.
560 E : break;
561 : }
562 :
563 E : std::string dll_name;
564 E : if (!ReadImageString(RelativeAddress(import_desc->Name), &dll_name)) {
565 i : LOG(ERROR) << "Unable to read import descriptor name";
566 i : return false;
567 : }
568 :
569 : // Iterate the Import Name Table and the Import Address Table
570 : // concurrently. They will yield, respectively, the name of the
571 : // function and the address of the entry.
572 E : RelativeAddress int_offs(import_desc->OriginalFirstThunk);
573 E : RelativeAddress iat_offs(import_desc->FirstThunk);
574 :
575 E : imports->push_back(ImportDll());
576 E : ImportDll& dll = imports->back();
577 E : dll.name = dll_name;
578 E : dll.desc = *import_desc;
579 :
580 E : while (true) {
581 E : IMAGE_THUNK_DATA int_thunk = {};
582 E : IMAGE_THUNK_DATA iat_thunk = {};
583 :
584 : if (!ReadImage(int_offs, &int_thunk, sizeof(int_thunk)) ||
585 E : !ReadImage(iat_offs, &iat_thunk, sizeof(iat_thunk))) {
586 i : LOG(ERROR) << "Unable to read import name or address table thunk";
587 i : return false;
588 : }
589 :
590 : // Are we at the end of the table?
591 E : if (int_thunk.u1.Function == 0) {
592 E : DCHECK_EQ(0U, iat_thunk.u1.Function);
593 E : break;
594 : }
595 :
596 E : uint16 hint = 0;
597 E : uint16 ordinal = 0;
598 E : std::string function_name;
599 E : if (int_thunk.u1.AddressOfData & IMAGE_ORDINAL_FLAG32) {
600 : // It's an ordinal.
601 E : ordinal = IMAGE_ORDINAL32(int_thunk.u1.Ordinal);
602 E : } else {
603 : // Read the hint word, followed by the function name.
604 E : RelativeAddress import_name(int_thunk.u1.AddressOfData);
605 : if (!ReadImage(import_name, &hint, sizeof(hint)) ||
606 E : !ReadImageString(import_name + sizeof(hint), &function_name)) {
607 i : LOG(ERROR) << "Unable to read import function hint or name";
608 i : return false;
609 : }
610 : }
611 :
612 E : dll.functions.push_back(ImportInfo());
613 E : ImportInfo& info = dll.functions.back();
614 E : info.function = function_name;
615 E : info.ordinal = ordinal;
616 E : info.hint = hint;
617 :
618 E : int_offs += sizeof(int_thunk);
619 E : iat_offs += sizeof(iat_thunk);
620 E : }
621 E : }
622 :
623 E : return true;
624 E : }
625 :
626 E : bool PEFile::Signature::IsConsistent(const Signature& signature) const {
627 : return base_address == signature.base_address &&
628 : module_size == signature.module_size &&
629 : module_time_date_stamp == signature.module_time_date_stamp &&
630 E : module_checksum == signature.module_checksum;
631 E : }
632 :
633 E : bool PEFile::Signature::Save(core::OutArchive* out_archive) const {
634 : return out_archive->Save(path) &&
635 : out_archive->Save(base_address) &&
636 : out_archive->Save(module_size) &&
637 : out_archive->Save(module_time_date_stamp) &&
638 E : out_archive->Save(module_checksum);
639 E : }
640 :
641 E : bool PEFile::Signature::Load(core::InArchive* in_archive) {
642 : return in_archive->Load(&path) &&
643 : in_archive->Load(&base_address) &&
644 : in_archive->Load(&module_size) &&
645 : in_archive->Load(&module_time_date_stamp) &&
646 E : in_archive->Load(&module_checksum);
647 E : }
648 :
649 : } // namespace pe
|