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