ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PeFileHeader.C
Go to the documentation of this file.
1 /* Windows PE file header (SgAsmPEFileHeader and related classes) */
2 #include "sage3basic.h"
3 #include "MemoryMap.h"
4 
5 /* The __attribute__ mechanism is only supported by GNU compilers */
6 #ifndef __GNUC__
7 #define __attribute__(x) /*NOTHING*/
8 #define __attribute(x) /*NOTHING*/
9 #endif
10 
13 std::string
15 {
16  const char *full="", *abbr="";
17  switch (idx) {
18  case PAIR_EXPORTS: full="Export Table"; abbr="Exports"; break;
19  case PAIR_IMPORTS: full="Import Table"; abbr="Imports"; break;
20  case PAIR_RESOURCES: full="Resource Table"; abbr="Rsrc"; break;
21  case PAIR_EXCEPTIONS: full="Exception Table"; abbr="Excpns"; break;
22  case PAIR_CERTIFICATES: full="Certificate Table"; abbr="Certs"; break;
23  case PAIR_BASERELOCS: full="Base Relocation Table"; abbr="BaseReloc"; break;
24  case PAIR_DEBUG: full="Debug"; abbr="Debug"; break;
25  case PAIR_ARCHITECTURE: full="Architecture"; abbr="Arch"; break;
26  case PAIR_GLOBALPTR: full="Global Ptr"; abbr="GlobPtr"; break;
27  case PAIR_TLS: full="TLS Table"; abbr="TLS"; break;
28  case PAIR_LOADCONFIG: full="Load Config Table"; abbr="LCT"; break;
29  case PAIR_BOUNDIMPORT: full="Bound Import Table"; abbr="BIT"; break;
30  case PAIR_IAT: full="Import Address Table"; abbr="IAT"; break;
31  case PAIR_DELAYIMPORT: full="Delay Import Descriptor"; abbr="DID"; break;
32  case PAIR_CLRRUNTIME: full="CLR Runtime Header"; abbr="CLRHdr"; break;
33  case PAIR_RESERVED15: full="Reserved Pair 15"; abbr="Pair15"; break;
34  // default: NOT PRESENT (it would prevent compiler warnings for newly added enum members)
35  }
36 
37  if (short_name)
38  *short_name = abbr;
39  return full;
40 }
41 
42 /* Construct a new PE File Header with default values. */
43 void
45 {
46  ROSE_ASSERT(get_file()!=NULL);
47  ROSE_ASSERT(get_size()>0);
48 
49  set_name(new SgAsmBasicString("PE File Header"));
50  set_synthesized(true);
52 
54 
55  /* Magic number */
56  p_magic.clear();
57  p_magic.push_back('P');
58  p_magic.push_back('E');
59  p_magic.push_back('\0');
60  p_magic.push_back('\0');
61 
62  /* Executable Format */
63  ROSE_ASSERT(p_exec_format!=NULL);
72 
73  /* Default instruction architecture */
74  p_e_cpu_type = 0x014c; /*i386*/
76 
77  p_e_time = time(NULL);
79 }
80 
84 bool
86 {
87  /* Turn off byte reference tracking for the duration of this function. We don't want our testing the file contents to
88  * affect the list of bytes that we've already referenced or which we might reference later. */
89  bool was_tracking = file->get_tracking_references();
90  file->set_tracking_references(false);
91 
92  try {
93  /* Check DOS File Header magic number at beginning of the file */
94  unsigned char dos_magic[2];
95  file->read_content(0, dos_magic, sizeof dos_magic);
96  if ('M'!=dos_magic[0] || 'Z'!=dos_magic[1])
97  throw 1;
98 
99  /* Read four-byte offset of potential PE File Header at offset 0x3c */
100  uint32_t lfanew_disk;
101  file->read_content(0x3c, &lfanew_disk, sizeof lfanew_disk);
102  rose_addr_t pe_offset = ByteOrder::le_to_host(lfanew_disk);
103 
104  /* Look for the PE File Header magic number */
105  unsigned char pe_magic[4];
106  file->read_content(pe_offset, pe_magic, sizeof pe_magic);
107  if ('P'!=pe_magic[0] || 'E'!=pe_magic[1] || '\0'!=pe_magic[2] || '\0'!=pe_magic[3])
108  throw 1;
109  } catch (...) {
110  file->set_tracking_references(was_tracking);
111  return false;
112  }
113 
114  file->set_tracking_references(was_tracking);
115  return true;
116 }
117 
122 {
124 
125  /* Read header, zero padding if the file isn't large enough */
127  if (sizeof(fh)>get_size())
128  extend(sizeof(fh)-get_size());
129  if (sizeof(fh)!=read_content_local(0, &fh, sizeof fh, false))
130  fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE header at byte 0x%08"PRIx64"\n", get_offset());
131 
132  /* Check magic number before getting too far */
133  if (fh.e_magic[0]!='P' || fh.e_magic[1]!='E' || fh.e_magic[2]!='\0' || fh.e_magic[3]!='\0')
134  throw FormatError("Bad PE magic number");
135 
136  /* Decode COFF file header */
144 
145  /* Read the "Optional Header" (optional in the sense that not all files have one, but required for an executable), the
146  * size of which is stored in the e_nt_hdr_size of the main PE file header. According to
147  * http://www.phreedom.org/solar/code/tinype the Windows loader honors the e_nt_hdr_size even when set to smaller than the
148  * smallest possible documented size of the optional header. Also it's possible for the optional header to extend beyond
149  * the end of the file, in which case that part should be read as zero. */
150  PE32OptHeader_disk oh32;
151  rose_addr_t need32 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh32));
152  if (need32>get_size())
153  extend(need32-get_size());
154  if (sizeof(oh32)!=read_content_local(sizeof fh, &oh32, sizeof oh32, false))
155  fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n",
156  get_offset() + sizeof(fh));
158 
159  /* File format changes from ctor() */
161  p_exec_format->set_word_size(0x010b==p_e_opt_magic? 4 : 8);
162 
163  /* Decode the optional header. */
164  rose_addr_t entry_rva;
165  if (4==p_exec_format->get_word_size()) {
171  entry_rva = ByteOrder::le_to_host(oh32.e_entrypoint_rva);
195  } else if (8==p_exec_format->get_word_size()) {
196  /* We guessed wrong. This is a 64-bit header, not 32-bit. */
197  PE64OptHeader_disk oh64;
198  rose_addr_t need64 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh64));
199  if (need64>get_size())
200  extend(need64-get_size());
201  if (sizeof(oh64)!=read_content_local(sizeof fh, &oh64, sizeof oh64))
202  fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n",
203  get_offset() + sizeof(fh));
209  entry_rva = ByteOrder::le_to_host(oh64.e_entrypoint_rva);
211  // p_e_data_rva = ByteOrder::le_to_host(oh.e_data_rva); /* not in PE32+ */
233  } else {
234  throw FormatError("unrecognized Windows PE optional header magic number");
235  }
236 
237  /* Magic number */
238  p_magic.clear();
239  for (size_t i = 0; i < sizeof(fh.e_magic); ++i)
240  p_magic.push_back(fh.e_magic[i]);
241 
242  /* File format */
243  ROSE_ASSERT(p_e_lmajor <= 0xffff && p_e_lminor <= 0xffff);
245  p_exec_format->set_is_current_version(true); /*FIXME*/
246 
247  /* Target architecture */
248  switch (p_e_cpu_type) {
249  case 0x0000:
251  break;
252  case 0x014c:
254  break;
255  case 0x014d:
257  break;
258  case 0x014e:
260  break;
261  case 0x0162:
262  set_isa(ISA_MIPS_MarkI); /* R2000, R3000 */
263  break;
264  case 0x0163:
265  set_isa(ISA_MIPS_MarkII); /* R6000 */
266  break;
267  case 0x0166:
268  set_isa(ISA_MIPS_MarkIII); /* R4000 */
269  break;
270  case 0x01a2: /*Hitachi SH3*/
271  case 0x01a3: /*Hitachi SH3 with FPU*/
272  case 0x01a6: /*Hitachi SH4*/
273  case 0x01a8: /*Hitachi SH5*/
275  break;
276  case 0x01c0:
278  break;
279  case 0x01d3:
281  break;
282  case 0x01f0: /*w/o FPU*/
283  case 0x01f1: /*with FPU*/
285  break;
286  case 0x0200:
288  break;
289  case 0x0266:
291  break;
292  case 0x0366:
294  break;
295  case 0x0466:
297  break;
298  case 0x0ebc:
300  break;
301  case 0x8664:
303  break;
304  case 0x9041:
306  break;
307  default:
308  fprintf(stderr, "SgAsmPEFileHeader::parse: warning: unrecognized e_cputype = 0x%x (%u)\n", p_e_cpu_type, p_e_cpu_type);
310  break;
311  }
312 
313  /* The NT loader normally maps this file header at the header's base virtual address. */
315  set_mapped_actual_va(0); /* will be assigned by BinaryLoader */
318  set_mapped_rperm(true);
319  set_mapped_wperm(false);
320  set_mapped_xperm(false);
321 
322  /* Entry point. We will eventually bind the entry point to a particular section (in SgAsmPEFileHeader::parse) so that if
323  * sections are rearranged, extended, etc. the entry point will be updated automatically. */
324  add_entry_rva(entry_rva);
325 
326  /* The PE File Header has a fixed-size component followed by some number of RVA/Size pairs. The add_rvasize_pairs() will
327  * extend the header and parse the RVA/Size pairs. */
328  if (get_e_num_rvasize_pairs() > 1000) {
329  fprintf(stderr, "warning: PE File Header contains an unreasonable number of Rva/Size pairs. Limiting to 1000.\n");
331  }
333 
334  /* Construct the section table and its sections (non-synthesized sections). The specification says that the section table
335  * comes after the optional (NT) header, which in turn comes after the fixed part of the PE header. The size of the
336  * optional header is indicated in the fixed header. */
337  rose_addr_t secttab_offset = get_offset() + sizeof(PEFileHeader_disk) + get_e_nt_hdr_size();
339  SgAsmPESectionTable *secttab = new SgAsmPESectionTable(this);
340  secttab->set_offset(secttab_offset);
341  secttab->set_size(secttab_size);
342  secttab->parse();
343  set_section_table(secttab);
344 
345  /* Parse the COFF symbol table */
346  if (get_e_coff_symtab() && get_e_coff_nsyms()) {
347  SgAsmCoffSymbolTable *symtab = new SgAsmCoffSymbolTable(this);
348  symtab->set_offset(get_e_coff_symtab());
349  symtab->parse();
350  set_coff_symtab(symtab);
351  }
352 
353  /* Associate RVAs with particular sections so that if a section's mapping is changed the RVA gets adjusted automatically. */
354  ROSE_ASSERT(get_entry_rvas().size()==1);
355  get_entry_rvas()[0].bind(this);
356  set_e_code_rva(get_e_code_rva().bind(this));
357  set_e_data_rva(get_e_data_rva().bind(this));
358 
359  /* Turn header-specified tables (RVA/Size pairs) into generic sections */
361  return this;
362 }
363 
364 /* Encode the PE header into disk format */
365 void *
367 {
368  for (size_t i=0; i<NELMTS(disk->e_magic); i++)
369  disk->e_magic[i] = get_magic()[i];
377 
378  return disk;
379 }
380 void *
382 {
413 
414  return disk;
415 }
416 void *
418 {
427  // ByteOrder::host_to_le(p_e_data_rva, &(disk->e_data_rva)); /* not present in PE32+ */
449 
450  return disk;
451 }
452 
454 void
456 {
457  ROSE_ASSERT(get_rvasize_pairs()!=NULL);
458  ROSE_ASSERT(section->get_parent()!=NULL);
459  ROSE_ASSERT(isSgAsmPEFileHeader(section->get_header())!=NULL);
460 
461  if (idx>=16)
462  fprintf(stderr, "SgAsmPEFileHeader::set_rvasize_pair: warning: index %u exceeds specification limit\n", (unsigned)idx);
463 
464  /* Extend array of rva/size pairs if necessary */
465  if ((size_t)idx>=get_rvasize_pairs()->get_pairs().size()) {
466  get_rvasize_pairs()->get_pairs().resize(idx+1, NULL);
467  for (size_t i=0; i<=(size_t)idx; i++) {
468  if (NULL==get_rvasize_pairs()->get_pairs()[i]) {
470  get_rvasize_pairs()->get_pairs()[i] = pair;
471  }
472  }
473  }
474 
476  ROSE_ASSERT(pair!=NULL);
477  pair->set_e_rva(rose_rva_t(section->get_mapped_preferred_rva(), section));
478  pair->set_e_size(section->get_mapped_size());
479  pair->set_section(section);
480 
481  /* If the section has no name then give it one based on the RVA/Size index. This is mostly for convenience and debugging
482  * since the name is never stored in the file. */
483  if (section->get_name()->get_string().empty()) {
484  const char *short_name;
485  section->get_name()->set_string(rvasize_pair_name(idx, &short_name));
486  section->set_short_name(short_name);
487  }
488 }
489 
491 void
493 {
494  for (size_t i=0; i<get_rvasize_pairs()->get_pairs().size(); i++) {
496  SgAsmGenericSection *section = pair->get_section();
497  if (section) {
498  pair->set_e_rva(rose_rva_t(section->get_mapped_preferred_rva(), section));
499  pair->set_e_size(section->get_mapped_size());
500  }
501  }
502 }
503 
504 /* Adds the RVA/Size pairs to the end of the PE file header */
505 void
507 {
508  rose_addr_t pairs_offset = get_size();
511 
512  ROSE_ASSERT(p_rvasize_pairs != NULL);
513  ROSE_ASSERT(p_rvasize_pairs->get_pairs().size()==0);
515 
516  extend(pairs_size);
517  for (size_t i = 0; i < p_e_num_rvasize_pairs; i++, pairs_offset += sizeof pairs_disk) {
518  if (sizeof(pairs_disk)!=read_content_local(pairs_offset, &pairs_disk, sizeof pairs_disk, false))
519  fprintf(stderr, "SgAsmPEFileHeader::add_rvasize_pairs: warning: RVA/Size pair %zu at file offset 0x%08"PRIx64
520  " extends beyond the end of file (assuming 0/0)\n", i, get_offset()+pairs_offset);
521  p_rvasize_pairs->get_pairs().push_back(new SgAsmPERVASizePair(p_rvasize_pairs, &pairs_disk));
522  }
523 }
524 
525 /* Looks at the RVA/Size pairs in the PE header and creates an SgAsmGenericSection object for each one. This must be done
526  * after we build the mapping from virtual addresses to file offsets. */
527 void
529 {
530 
531  /* First, only create the sections. */
532  for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) {
534  if (0==pair->get_e_size())
535  continue;
536 
537  /* Table names come from PE file specification and are hard coded by RVA/Size pair index */
538  const char *tabname_short;
539  std::string tabname = rvasize_pair_name((PairPurpose)i, &tabname_short);
540 
541  /* Find the starting offset in the file.
542  * FIXME: We have a potential problem here in that ROSE sections are always contiguous in the file but a section created
543  * from an RVA/Size pair is not necessarily contiguous in the file. Normally such sections are in fact
544  * contiguous and we'll just ignore this for now. In any case, as long as these sections only ever read their
545  * data via the same MemoryMap that we use here, everything should be fine. [RPM 2009-08-17] */
546  rose_addr_t pair_va = get_base_va() + pair->get_e_rva();
547  MemoryMap *map = get_loader_map();
548  ROSE_ASSERT(map!=NULL);
549  if (!map->exists(Extent(pair_va, pair->get_e_size()))) {
550  fprintf(stderr, "SgAsmPEFileHeader::create_table_sections: warning: pair-%zu, rva=0x%08"PRIx64", size=%"PRIu64
551  " bytes \"%s\": unable to find a mapping for the virtual address (skipping)\n",
552  i, pair->get_e_rva().get_rva(), pair->get_e_size(), tabname.c_str());
553  continue;
554  }
555  std::pair<Extent, MemoryMap::Segment> me = map->at(pair_va);
556  rose_addr_t file_offset = me.second.get_buffer_offset(me.first, pair_va);
557 
558  /* Create the new section */
559  SgAsmGenericSection *tabsec = NULL;
560  switch (i) {
561  case 0: {
562  /* Sometimes export sections are represented by a ".edata" section, and sometimes they're represented by an
563  * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the exports duplicated
564  * in the AST, so we only create this table as exports if we haven't already seen some other export section. */
566  bool seen_exports = false;
567  for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_exports && si!=sections.end(); ++si)
568  seen_exports = isSgAsmPEExportSection(*si);
569  if (seen_exports) {
570  tabsec = new SgAsmGenericSection(get_file(), this);
571  } else {
572  tabsec = new SgAsmPEExportSection(this);
573  }
574  break;
575  }
576  case 1: {
577  /* Sometimes import sections are represented by a ".idata" section, and sometimes they're represented by an
578  * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the imports duplicated
579  * in the AST, so we only create this table as imports if we haven't already seen some other import section. */
581  bool seen_imports = false;
582  for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_imports && si!=sections.end(); ++si)
583  seen_imports = isSgAsmPEImportSection(*si);
584  if (seen_imports) {
585  tabsec = new SgAsmGenericSection(get_file(), this);
586  } else {
587  tabsec = new SgAsmPEImportSection(this);
588  }
589  break;
590  }
591  default: {
592  tabsec = new SgAsmGenericSection(get_file(), this);
593  break;
594  }
595  }
596  tabsec->set_name(new SgAsmBasicString(tabname));
597  tabsec->set_short_name(tabname_short);
598  tabsec->set_synthesized(true);
599  tabsec->set_purpose(SP_HEADER);
600 
601  tabsec->set_offset(file_offset);
602  tabsec->set_size(pair->get_e_size());
603  tabsec->set_file_alignment(1);
604 
605  tabsec->set_mapped_alignment(1);
606  tabsec->set_mapped_preferred_rva(pair->get_e_rva().get_rva());
607  tabsec->set_mapped_actual_va(pair->get_e_rva().get_rva()+get_base_va()); /*FIXME: not sure this is correct. [RPM 2009-09-11]*/
608  tabsec->set_mapped_size(pair->get_e_size());
609  tabsec->set_mapped_rperm(true);
610  tabsec->set_mapped_wperm(false);
611  tabsec->set_mapped_xperm(false);
612  pair->set_section(tabsec);
613  pair->set_e_rva(pair->get_e_rva().set_section(tabsec));
614  }
615 
616  /* Now parse the sections */
617  for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) {
619  SgAsmGenericSection *tabsec = pair->get_section();
620  if (tabsec)
621  tabsec->parse();
622  }
623 }
624 
625 /* Change size of PE header based on word size */
626 bool
628 {
629  bool reallocated = SgAsmGenericHeader::reallocate();
630 
631  /* Resize if necessary */
632  rose_addr_t need = sizeof(PEFileHeader_disk);
633  if (4==get_word_size()) {
634  need += sizeof(PE32OptHeader_disk);
635  } else if (8==get_word_size()) {
636  need += sizeof(PE64OptHeader_disk);
637  } else {
638  throw FormatError("unsupported PE word size");
639  }
641  if (need<get_size()) {
642  if (is_mapped()) {
643  ROSE_ASSERT(get_mapped_size()==get_size());
644  set_mapped_size(need);
645  }
646  set_size(need);
647  reallocated = true;
648  } else if (need>get_size()) {
650  reallocated = true;
651  }
652 
653  /* Make sure the RVA/Size pairs at the end of the header are consistent with the sections to which they point. Reallocate()
654  * has already been called recursively for the sections. */
656 
657  /* Make sure header is consistent with sections. Reallocate() has already been called recursively for the sections.
658  * Count the number of sections in the table and update the header's e_nsections member. */
659  if (p_section_table) {
660  ROSE_ASSERT(p_section_table->get_header()==this);
662  p_e_nsections = 0;
663  for (size_t i=0; i<all->get_sections().size(); i++) {
664  SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]);
665  if (pesec && pesec->get_section_entry()!=NULL)
666  p_e_nsections++;
667  }
668 
671 #if 1
672  /* The PE Specification regarding e_header_size (known as "SizeOfHeader" on page 14 of "Microsoft Portable Executable
673  * and Common Object File Format Specification: Revision 8.1 February 15, 2008" is not always followed. We recompute
674  * it here as being the minimum RVA from all the sections defined in the PE Section Table, but not smaller
675  * than the value according to the specification. This alternate value is kept if it's already in the parse tree,
676  * otherwise we use the correct value. (RPM 2008-10-21) */
677  rose_addr_t min_offset = 0;
678  for (size_t i=0, nfound=0; i<all->get_sections().size(); i++) {
679  SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]);
680  if (pesec && pesec->get_section_entry()!=NULL) {
681  if (0==nfound++) {
682  min_offset = pesec->get_offset();
683  } else {
684  min_offset = std::min(min_offset, pesec->get_offset() );
685  }
686  }
687  }
688 
689  rose_addr_t header_size2 = std::max(header_size, min_offset);
690  if (p_e_header_size==header_size2)
691  header_size = header_size2;
692 
693  /* If the original header size was zero then don't change that--leave it at zero. Some tiny executables have a zero
694  * value here and as a result, since this is near the end of the NT Optional Header, they can truncate the file and
695  * the loader will fill the optional header with zeros when reading. (RPM 2008-11-11) */
696  if (p_e_header_size==0)
697  header_size = 0;
698 #endif
699  p_e_header_size = header_size;
700  }
701 
702  /* The size of the optional header. If there's a section table then we use its offset to calculate the optional header
703  * size in order to be compatible with the PE loader. Otherwise use the actual optional header size. */
704  if (p_section_table) {
705  ROSE_ASSERT(p_section_table->get_offset() >= get_offset() + sizeof(PEFileHeader_disk));
707  } else if (4==get_word_size()) {
709  } else if (8==get_word_size()) {
711  } else {
712  throw FormatError("invalid PE word size");
713  }
714 
715  /* Update COFF symbol table related data members in the file header */
716  if (get_coff_symtab()) {
717  ROSE_ASSERT(get_coff_symtab()->get_header()==this);
719  set_e_coff_nsyms(get_coff_symtab()->get_nslots());
720  }
721 
722  /* Update some additional header fields */
723  set_e_num_rvasize_pairs(get_rvasize_pairs()->get_pairs().size());
724  set_e_opt_magic(4==get_word_size() ? 0x010b : 0x020b);
725  set_e_lmajor((get_exec_format()->get_version() >> 16) & 0xffff);
726  set_e_lminor(get_exec_format()->get_version() & 0xffff);
727 
728  /* Adjust the COFF Header's e_nt_hdr_size to accommodate the NT Optional Header in such a way that EXEs from tinype.com
729  * don't change (i.e., don't increase e_nt_hdr_size if the bytes beyond it are zero anyway, and if they aren't then adjust
730  * it as little as possible. The RVA/Size pairs are considered to be part of the NT Optional Header. */
731  size_t oh_size = p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk);
732  size_t rvasize_offset; /*offset with respect to "oh" buffer allocated below*/
733  if (4==get_word_size()) {
734  oh_size += sizeof(PE32OptHeader_disk);
735  } else if (8==get_word_size()) {
736  oh_size += sizeof(PE64OptHeader_disk);
737  } else {
738  throw FormatError("unsupported PE word size");
739  }
740  unsigned char *oh = new unsigned char[oh_size];
741  if (4==get_word_size()) {
743  rvasize_offset = sizeof(PE32OptHeader_disk);
744  } else if (8==get_word_size()) {
746  rvasize_offset = sizeof(PE64OptHeader_disk);
747  } else {
748  delete[] oh;
749  throw FormatError("unsupported PE word size");
750  }
751  while (oh_size>p_e_nt_hdr_size) {
752  if (0!=oh[oh_size-1]) break;
753  --oh_size;
754  }
755  set_e_nt_hdr_size(oh_size);
756  return reallocated;
757 }
758 
759 /* Write the PE file header back to disk and all that it references */
760 void
761 SgAsmPEFileHeader::unparse(std::ostream &f) const
762 {
763  /* Write unreferenced areas back to the file before anything else. */
764  unparse_holes(f);
765 
766  /* Write sections in the order of specialization, from least specialized to most specialized. This gives more specialized
767  * sections a chance to overwrite the less specialized sections. */
769  for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) {
770  if (V_SgAsmGenericSection==(*si)->variantT())
771  (*si)->unparse(f);
772  }
773  for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) {
774  if (V_SgAsmPESection==(*si)->variantT())
775  (*si)->unparse(f);
776  }
777  for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) {
778  if (V_SgAsmGenericSection!=(*si)->variantT() && V_SgAsmPESection!=(*si)->variantT())
779  (*si)->unparse(f);
780  }
781 
782  /* Encode the "NT Optional Header" before the COFF Header since the latter depends on the former. Adjust the COFF Header's
783  * e_nt_hdr_size to accommodate the NT Optional Header in such a way that EXEs from tinype.com don't change (i.e., don't
784  * increase e_nt_hdr_size if the bytes beyond it are zero anyway, and if they aren't then adjust it as little as possible.
785  * The RVA/Size pairs are considered to be part of the NT Optional Header. */
786  size_t oh_size = p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk);
787  size_t rvasize_offset; /*offset with respect to "oh" buffer allocated below*/
788  if (4==get_word_size()) {
789  oh_size += sizeof(PE32OptHeader_disk);
790  } else if (8==get_word_size()) {
791  oh_size += sizeof(PE64OptHeader_disk);
792  } else {
793  throw FormatError("unsupported PE word size");
794  }
795  unsigned char *oh = new unsigned char[oh_size];
796  if (4==get_word_size()) {
798  rvasize_offset = sizeof(PE32OptHeader_disk);
799  } else if (8==get_word_size()) {
801  rvasize_offset = sizeof(PE64OptHeader_disk);
802  } else {
803  throw FormatError("unsupported PE word size");
804  }
805  for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++, rvasize_offset+=sizeof(SgAsmPERVASizePair::RVASizePair_disk)) {
807  p_rvasize_pairs->get_pairs()[i]->encode(rvasize_disk);
808  }
809  while (oh_size>p_e_nt_hdr_size) {
810  if (0!=oh[oh_size-1]) break;
811  --oh_size;
812  }
813  ROSE_ASSERT(p_e_nt_hdr_size==oh_size); /*set in reallocate()*/
814 
815  /* Write the fixed-length COFF Header */
817  encode(&fh);
818  rose_addr_t spos = write(f, 0, sizeof fh, &fh);
819 
820  /* Write the following "NT Optional Header" */
821  spos = write(f, spos, oh_size, oh);
822 }
823 
824 /* Print some debugging information */
825 void
826 SgAsmPEFileHeader::dump(FILE *f, const char *prefix, ssize_t idx) const
827 {
828  char p[4096];
829  if (idx>=0) {
830  sprintf(p, "%sPEFileHeader[%zd].", prefix, idx);
831  } else {
832  sprintf(p, "%sPEFileHeader.", prefix);
833  }
834 
835  int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
836  time_t t = p_e_time;
837  char time_str[128];
838  struct tm *tm = localtime(&t);
839  if (tm) {
840  strftime(time_str, sizeof time_str, "%c", tm);
841  } else {
842  strcpy(time_str, "INVALID");
843  }
844 
845  SgAsmGenericHeader::dump(f, p, -1);
846  fprintf(f, "%s%-*s = 0x%04x (%u)\n", p, w, "e_cpu_type", p_e_cpu_type, p_e_cpu_type);
847  fprintf(f, "%s%-*s = %u\n", p, w, "e_nsections", p_e_nsections);
848  fprintf(f, "%s%-*s = %u (%s)\n", p, w, "e_time", p_e_time, time_str);
849  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64")\n", p, w, "e_coff_symtab", p_e_coff_symtab, p_e_coff_symtab);
850  fprintf(f, "%s%-*s = %u\n", p, w, "e_coff_nsyms", p_e_coff_nsyms);
851  if (p_coff_symtab) {
852  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "coff_symtab",
853  p_coff_symtab->get_id(), p_coff_symtab->get_name()->get_string(true).c_str());
854  } else {
855  fprintf(f, "%s%-*s = none\n", p, w, "coff_symtab");
856  }
857  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64")\n", p, w, "e_nt_hdr_size", p_e_nt_hdr_size, p_e_nt_hdr_size);
858  fprintf(f, "%s%-*s = 0x%04x (%u)\n", p, w, "e_flags", p_e_flags, p_e_flags);
859  fprintf(f, "%s%-*s = 0x%04x %s\n", p, w, "e_opt_magic", p_e_opt_magic,
860  0x10b == p_e_opt_magic ? "PE32" : (0x20b == p_e_opt_magic ? "PE32+" : "other"));
861  fprintf(f, "%s%-*s = %u.%u\n", p, w, "linker_vers", p_e_lmajor, p_e_lminor);
862  fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n", p, w, "e_code_size", p_e_code_size, p_e_code_size);
863  fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n", p, w, "e_data_size", p_e_data_size, p_e_data_size);
864  fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n", p, w, "e_bss_size", p_e_bss_size, p_e_bss_size);
865  fprintf(f, "%s%-*s = %s\n", p, w, "e_code_rva", p_e_code_rva.to_string().c_str());
866  fprintf(f, "%s%-*s = %s\n", p, w, "e_data_rva", p_e_data_rva.to_string().c_str());
867  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_section_align", p_e_section_align, p_e_section_align);
868  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_file_align", p_e_file_align, p_e_file_align);
869  fprintf(f, "%s%-*s = %u.%u\n", p, w, "os_vers", p_e_os_major, p_e_os_minor);
870  fprintf(f, "%s%-*s = %u.%u\n", p, w, "user_vers", p_e_user_major, p_e_user_minor);
871  fprintf(f, "%s%-*s = %u.%u\n", p, w, "subsys_vers", p_e_subsys_major, p_e_subsys_minor);
872  fprintf(f, "%s%-*s = %u\n", p, w, "e_reserved9", p_e_reserved9);
873  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_image_size", p_e_image_size, p_e_image_size);
874  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_header_size", p_e_header_size, p_e_header_size);
875  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_file_checksum", p_e_file_checksum, p_e_file_checksum);
876  fprintf(f, "%s%-*s = %u\n", p, w, "e_subsystem", p_e_subsystem);
877  fprintf(f, "%s%-*s = 0x%04x (%u)\n", p, w, "e_dll_flags", p_e_dll_flags, p_e_dll_flags);
878  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_stack_reserve_size",
880  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_stack_commit_size", p_e_stack_commit_size, p_e_stack_commit_size);
881  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_heap_reserve_size", p_e_heap_reserve_size, p_e_heap_reserve_size);
882  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_heap_commit_size", p_e_heap_commit_size, p_e_heap_commit_size);
883  fprintf(f, "%s%-*s = 0x%08x (%u)\n", p, w, "e_loader_flags", p_e_loader_flags, p_e_loader_flags);
884  fprintf(f, "%s%-*s = %u\n", p, w, "e_num_rvasize_pairs", p_e_num_rvasize_pairs);
885  for (unsigned i = 0; i < p_rvasize_pairs->get_pairs().size(); i++) {
886  char p2[256];
887  int nprint __attribute__((unused)) = snprintf(p2, sizeof p2, "%s.pair[%d].", p, i);
888  assert((size_t)nprint<sizeof p2);
889  w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p2));
890  fprintf(f, "%s%-*s = rva %s,\tsize 0x%08"PRIx64" (%"PRIu64")\n", p2, w, "..",
891  p_rvasize_pairs->get_pairs()[i]->get_e_rva().to_string().c_str(),
892  p_rvasize_pairs->get_pairs()[i]->get_e_size(), p_rvasize_pairs->get_pairs()[i]->get_e_size());
893  }
894  if (p_section_table) {
895  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "section_table",
897  } else {
898  fprintf(f, "%s%-*s = none\n", p, w, "section_table");
899  }
900 
901  if (variantT() == V_SgAsmPEFileHeader) //unless a base class
902  hexdump(f, 0, std::string(p)+"data at ", p_data);
903 
904  /* Show the simulated loader memory map */
905  const MemoryMap *map = get_loader_map();
906  if (map) {
907  map->dump(f, (std::string(p)+"loader_map: ").c_str());
908  } else {
909  fprintf(f, "%s%-*s = not defined\n", p, w, "loader_map");
910  }
911 }