ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ExecLE.C
Go to the documentation of this file.
1 /* Copyright 2008 Lawrence Livermore National Security, LLC */
2 
3 #include "sage3basic.h"
4 
5 // DQ (8/21/2008): Now we want to move away from using the older header files (from before we used the IR nodes).
6 // #include "ExecLE.h"
7 
8 // namespace Exec {
9 // namespace LE {
10 
12 // LE File Header
14 
15 void
17 {
18  set_offset(offset);
19  set_size(sizeof(LEFileHeader_disk));
20  grab_content();
21 
22  // DQ (8/16/2008): Added code to set SgAsmPEFileHeader as parent of input SgAsmGenericFile
23  f->set_parent(this);
24 
26  read_content_local(0, &fh, sizeof fh);
27 
28  /* Check magic number early */
29  if (fh.e_magic[0]!='L' ||
30  (fh.e_magic[1]!='E' && fh.e_magic[1]!='X'))
31  throw FormatError("Bad LE/LX magic number");
32 
33  /* Decode file header */
35  const char *section_name = FAMILY_LE == p_exec_format->get_family() ? "LE File Header" : "LX File Header";
36  set_name(new SgAsmBasicString(section_name));
37  set_synthesized(true);
41  ROSE_ASSERT(p_e_byte_order == p_e_word_order);
43 
58  } else {
59  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
62  }
94 
95  /* Magic number */
96  for (size_t i = 0; i < sizeof(fh.e_magic); ++i)
97  p_magic.push_back(fh.e_magic[i]);
98 
99  /* File format */
100  //exec_format.family = ???; /*set above*/
102  p_exec_format->set_sex( sex );
103  switch (p_e_os_type) {
104  case 0: p_exec_format->set_abi( ABI_UNSPECIFIED ); break;
105  case 1: p_exec_format->set_abi( ABI_OS2 ); break;
106  case 2: p_exec_format->set_abi( ABI_NT ); break;
107  case 3: p_exec_format->set_abi( ABI_MSDOS ); break;
108  case 4: p_exec_format->set_abi( ABI_WIN386 ); break;
109  default: p_exec_format->set_abi( ABI_OTHER ); break;
110  }
115 
116  /* Target architecture */
117  switch (p_e_cpu_type) {
118  case 0x01: set_isa(ISA_IA32_286); break;
119  case 0x02: set_isa(ISA_IA32_386); break;
120  case 0x03: set_isa(ISA_IA32_486); break;
121  case 0x04: set_isa(ISA_IA32_Pentium); break;
122  case 0x20: set_isa(ISA_I860_860XR); break; /*N10*/
123  case 0x21: set_isa(ISA_I860_860XP); break; /*N11*/
124  case 0x40: set_isa(ISA_MIPS_MarkI); break; /*R2000, R3000*/
125  case 0x41: set_isa(ISA_MIPS_MarkII); break; /*R6000*/
126  case 0x42: set_isa(ISA_MIPS_MarkIII); break; /*R4000*/
127  default: set_isa(ISA_OTHER); break;
128  }
129 
130  /* Entry point */
131 // entry_rva = ???; /*FIXME: see e_eip and e_eip_section; we must parse section table first */
132 }
133 
137 bool
139 {
140  /* Turn off byte reference tracking for the duration of this function. We don't want our testing the file contents to
141  * affect the list of bytes that we've already referenced or which we might reference later. */
142  bool was_tracking = file->get_tracking_references();
143  file->set_tracking_references(false);
144 
145  try {
146  /* Check DOS File Header magic number at beginning of the file */
147  unsigned char dos_magic[2];
148  file->read_content(0, dos_magic, sizeof dos_magic);
149  if ('M'!=dos_magic[0] || 'Z'!=dos_magic[1])
150  throw 1;
151 
152  /* Read four-byte offset of potential LE/LX File Header at offset 0x3c */
153  uint32_t lfanew_disk;
154  file->read_content(0x3c, &lfanew_disk, sizeof lfanew_disk);
155  rose_addr_t le_offset = ByteOrder::le_to_host(lfanew_disk);
156 
157  /* Look for the LE/LX File Header magic number */
158  unsigned char le_magic[4];
159  file->read_content(le_offset, le_magic, sizeof le_magic);
160  if ('L'!=le_magic[0] || ('E'!=le_magic[1] && 'X'!=le_magic[1]))
161  throw 1;
162  } catch (...) {
163  file->set_tracking_references(was_tracking);
164  return false;
165  }
166 
167  file->set_tracking_references(was_tracking);
168  return true;
169 }
170 
171 /* Encode the LE header into disk format */
172 void *
174 {
175  for (size_t i=0; i<NELMTS(disk->e_magic); i++)
176  disk->e_magic[i] = get_magic()[i];
177  host_to_disk(sex, p_e_byte_order, &(disk->e_byte_order));
178  host_to_disk(sex, p_e_word_order, &(disk->e_word_order));
180  host_to_disk(sex, p_e_cpu_type, &(disk->e_cpu_type));
181  host_to_disk(sex, p_e_os_type, &(disk->e_os_type));
183  host_to_disk(sex, p_e_flags, &(disk->e_flags));
184  host_to_disk(sex, p_e_npages, &(disk->e_npages));
186  host_to_disk(sex, p_e_eip, &(disk->e_eip));
188  host_to_disk(sex, p_e_esp, &(disk->e_esp));
189  host_to_disk(sex, p_e_page_size, &(disk->e_page_size));
190  if (FAMILY_LE == p_exec_format->get_family()) {
192  } else {
193  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
195  }
226  host_to_disk(sex, p_e_heap_size, &(disk->e_heap_size));
227  return disk;
228 }
229 
230 /* Write the LE file header back to disk and all that it references */
231 void
232 SgAsmLEFileHeader::unparse(std::ostream &f) const
233 {
235  encode(get_sex(), &fh);
236  write(f, 0, sizeof fh, &fh);
237 
238  /* The extended DOS header */
239  if (p_dos2_header)
241 
242  /* The section table and all the non-synthesized sections */
243  if (p_section_table)
245 
246  /* Sections defined in the file header */
247  if (p_page_table)
248  p_page_table->unparse(f);
249  if (p_resname_table)
251  if (p_nonresname_table)
253  if (p_entry_table)
255  if (p_reloc_table)
257 }
258 
259 /* Format name */
260 const char *
262 {
263  if (FAMILY_LE == p_exec_format->get_family()) {
264  return "LE";
265  } else {
266  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
267  return "LX";
268  }
269 }
270 
271 /* Print some debugging information */
272 void
273 SgAsmLEFileHeader::dump(FILE *f, const char *prefix, ssize_t idx) const
274 {
275  char p[4096];
276  if (idx>=0) {
277  sprintf(p, "%s%sFileHeader[%zd].", prefix, format_name(), idx);
278  } else {
279  sprintf(p, "%s%sFileHeader.", prefix, format_name());
280  }
281 
282  int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
283 
284  SgAsmGenericHeader::dump(f, p, -1);
285  fprintf(f, "%s%-*s = %u\n", p, w, "e_byte_order", p_e_byte_order);
286  fprintf(f, "%s%-*s = %u\n", p, w, "e_word_order", p_e_word_order);
287  fprintf(f, "%s%-*s = %u\n", p, w, "e_format_level", p_e_format_level);
288  fprintf(f, "%s%-*s = %u\n", p, w, "e_cpu_type", p_e_cpu_type);
289  fprintf(f, "%s%-*s = %u\n", p, w, "e_os_type", p_e_os_type);
290  fprintf(f, "%s%-*s = %u\n", p, w, "e_module_version", p_e_module_version);
291  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_flags", p_e_flags);
292  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_npages", p_e_npages);
293  fprintf(f, "%s%-*s = %u\n", p, w, "e_eip_section", p_e_eip_section);
294  fprintf(f, "%s%-*s = 0x%08"PRIx64"\n", p, w, "e_eip", p_e_eip);
295  fprintf(f, "%s%-*s = %u\n", p, w, "e_esp_section", p_e_esp_section);
296  fprintf(f, "%s%-*s = 0x%08"PRIx64"\n", p, w, "e_esp", p_e_esp);
297  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_page_size", p_e_page_size);
298  if (FAMILY_LE == p_exec_format->get_family()) {
299  fprintf(f, "%s%-*s = %u\n", p, w, "e_last_page_size", p_e_last_page_size);
300  } else {
301  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
302  fprintf(f, "%s%-*s = %u\n", p, w, "e_page_offset_shift", p_e_page_offset_shift);
303  }
304  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_fixup_sect_size", p_e_fixup_sect_size);
305  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_fixup_sect_cksum", p_e_fixup_sect_cksum);
306  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_loader_sect_size", p_e_loader_sect_size);
307  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_loader_sect_cksum", p_e_loader_sect_cksum);
308  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_secttab_rfo",
310  fprintf(f, "%s%-*s = %u\n", p, w, "e_secttab_nentries", p_e_secttab_nentries);
311  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_pagetab_rfo",
313  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_iterpages_offset", p_e_iterpages_offset);
314  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_rsrctab_rfo",
316  fprintf(f, "%s%-*s = %u\n", p, w, "e_rsrctab_nentries", p_e_rsrctab_nentries);
317  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_resnametab_rfo",
319  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_entrytab_rfo",
321  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_fmtdirtab_rfo",
323  fprintf(f, "%s%-*s = %u\n", p, w, "e_fmtdirtab_nentries", p_e_fmtdirtab_nentries);
324  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_fixup_pagetab_rfo",
326  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_fixup_rectab_rfo",
328  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_import_modtab_rfo",
330  fprintf(f, "%s%-*s = %u\n", p, w, "e_import_modtab_nentries", p_e_import_modtab_nentries);
331  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_import_proctab_rfo",
333  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_ppcksumtab_rfo",
335  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_data_pages_offset", p_e_data_pages_offset);
336  fprintf(f, "%s%-*s = %u\n", p, w, "e_preload_npages", p_e_preload_npages);
337  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "e_nonresnametab_offset", p_e_nonresnametab_offset);
338  fprintf(f, "%s%-*s = %u\n", p, w, "e_nonresnametab_size", p_e_nonresnametab_size);
339  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_nonresnametab_cksum", p_e_nonresnametab_cksum);
340  fprintf(f, "%s%-*s = %u\n", p, w, "e_auto_ds_section", p_e_auto_ds_section);
341  fprintf(f, "%s%-*s = %"PRIu64" (%"PRIu64" abs)\n", p, w, "e_debug_info_rfo",
343  fprintf(f, "%s%-*s = %u\n", p, w, "e_debug_info_size", p_e_debug_info_size);
344  fprintf(f, "%s%-*s = %u\n", p, w, "e_num_instance_preload", p_e_num_instance_preload);
345  fprintf(f, "%s%-*s = %u\n", p, w, "e_num_instance_demand", p_e_num_instance_demand);
346  fprintf(f, "%s%-*s = %u\n", p, w, "e_heap_size", p_e_heap_size);
347 
348  if (p_dos2_header) {
349  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "dos2_header",
350  p_dos2_header->get_id(), p_dos2_header->get_name()->get_string(true).c_str());
351  } else {
352  fprintf(f, "%s%-*s = none\n", p, w, "dos2_header");
353  }
354  if (p_section_table) {
355  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "section_table",
357  } else {
358  fprintf(f, "%s%-*s = none\n", p, w, "section_table");
359  }
360  if (p_page_table) {
361  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "page_table",
362  p_page_table->get_id(), p_page_table->get_name()->get_string(true).c_str());
363  } else {
364  fprintf(f, "%s%-*s = none\n", p, w, "page_table");
365  }
366  if (p_resname_table) {
367  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "resname_table",
369  } else {
370  fprintf(f, "%s%-*s = none\n", p, w, "resname_table");
371  }
372  if (p_nonresname_table) {
373  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "nonresname_table",
375  } else {
376  fprintf(f, "%s%-*s = none\n", p, w, "nonresname_table");
377  }
378  if (p_entry_table) {
379  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "entry_table",
380  p_entry_table->get_id(), p_entry_table->get_name()->get_string(true).c_str());
381  } else {
382  fprintf(f, "%s%-*s = none\n", p, w, "entry_table");
383  }
384  if (p_reloc_table) {
385  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "reloc_table",
386  p_reloc_table->get_id(), p_reloc_table->get_name()->get_string(true).c_str());
387  } else {
388  fprintf(f, "%s%-*s = none\n", p, w, "reloc_table");
389  }
390 }
391 
393 // LE/LX Page Table
395 
396 /* Constructor */
397 void
399 {
400  unsigned pageno_lo = ByteOrder::disk_to_host(sex, disk->pageno_lo);
401  unsigned pageno_hi = ByteOrder::disk_to_host(sex, disk->pageno_hi);
402  p_pageno = (pageno_hi << 8) | pageno_lo;
403  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
404 }
405 
406 /* Encode page table entry to disk format */
407 void *
409 {
410  host_to_disk(sex, (p_pageno & 0xff), &(disk->pageno_lo));
411  host_to_disk(sex, (p_pageno>>8)&0xffff, &(disk->pageno_hi));
412  host_to_disk(sex, p_flags, &(disk->flags));
413  return disk;
414 }
415 
416 /* Print some debugging information */
417 void
418 SgAsmLEPageTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
419 {
420  char p[4096];
421  if (idx>=0) {
422  sprintf(p, "%sPageTableEntry[%zd].", prefix, idx);
423  } else {
424  sprintf(p, "%sPageTableEntry.", prefix);
425  }
426 
427  int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
428 
429  fprintf(f, "%s%-*s = 0x%04x\n", p, w, "flags", p_flags);
430  fprintf(f, "%s%-*s = %u\n", p, w, "pageno", p_pageno);
431 }
432 
433 /* Constructor */
434 void
436 {
437  set_offset(offset);
438  set_size(size);
439  grab_content();
440 
441  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
442  ROSE_ASSERT(fhdr!=NULL);
443 
444  char section_name[64];
445  sprintf(section_name, "%s Page Table", fhdr->format_name());
446  set_synthesized(true);
447  set_name(new SgAsmBasicString(section_name));
449 
451  for (rose_addr_t entry_offset=0; entry_offset+entry_size <= get_size(); entry_offset+=entry_size) {
453  read_content_local(entry_offset, &disk, entry_size);
454  p_entries.push_back(new SgAsmLEPageTableEntry(fhdr->get_sex(), &disk));
455  }
456 }
457 
458 /* Returns info about a particular page. Indices are 1-origin */
461 {
462  ROSE_ASSERT(idx > 0);
463  ROSE_ASSERT(idx <= p_entries.size());
464  return p_entries[idx-1];
465 }
466 
467 /* Write page table back to disk */
468 void
469 SgAsmLEPageTable::unparse(std::ostream &f) const
470 {
471  rose_addr_t spos=0; /*section offset*/
472  for (size_t i=0; i < p_entries.size(); i++) {
474  p_entries[i]->encode(get_header()->get_sex(), &disk);
475  spos = write(f, spos, sizeof disk, &disk);
476  }
477 }
478 
479 /* Print some debugging information */
480 void
481 SgAsmLEPageTable::dump(FILE *f, const char *prefix, ssize_t idx) const
482 {
483  char p[4096];
484  if (idx>=0) {
485  sprintf(p, "%s%sPageTable[%zd].", prefix, get_header()->format_name(), idx);
486  } else {
487  sprintf(p, "%s%sPageTable.", prefix, get_header()->format_name());
488  }
489 
490  SgAsmGenericSection::dump(f, p, -1);
491  for (size_t i = 0; i < p_entries.size(); i++) {
492  p_entries[i]->dump(f, p, i);
493  }
494 }
495 
497 // LE/LX Section Table
499 
500 /* Constructor */
501 void
503 {
506  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
509  p_res1 = ByteOrder::disk_to_host(sex, disk->res1);
510 }
511 
512 /* Encodes a section table entry back into disk format. */
513 void *
515 {
518  ByteOrder::host_to_disk(sex, p_flags, &(disk->flags));
521  ByteOrder::host_to_disk(sex, p_res1, &(disk->res1));
522  return disk;
523 }
524 
525 /* Prints some debugging info */
526 void
527 SgAsmLESectionTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
528 {
529  char p[4096];
530  if (idx>=0) {
531  sprintf(p, "%sLESectionTableEntry[%zd].", prefix, idx);
532  } else {
533  sprintf(p, "%sLESectionTableEntry.", prefix);
534  }
535 
536  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
537 
538  fprintf(f, "%s%-*s = %"PRIu64" bytes\n", p, w, "mapped_size", p_mapped_size);
539  fprintf(f, "%s%-*s = 0x%08"PRIx64"\n", p, w, "base_addr", p_base_addr);
540 
541  fprintf(f, "%s%-*s = 0x%08x", p, w, "flags", p_flags);
542  switch (p_flags & SF_TYPE_MASK) {
543  case SF_TYPE_NORMAL: fputs(" normal", f); break;
544  case SF_TYPE_ZERO: fputs(" zero", f); break;
545  case SF_TYPE_RESIDENT: fputs(" resident", f); break;
546  case SF_TYPE_RESCONT: fputs(" res-cont", f); break;
547  default: fprintf(f, "type=%u", p_flags & SF_TYPE_MASK); break;
548  }
549  fputs(" perm=", f);
550  fputc(p_flags & SF_READABLE ? 'r' : '-', f);
551  fputc(p_flags & SF_WRITABLE ? 'w' : '-', f);
552  fputc(p_flags & SF_EXECUTABLE ? 'x' : '-', f);
553  if (p_flags & SF_RESOURCE) fputs(" resource", f);
554  if (p_flags & SF_DISCARDABLE) fputs(" discardable", f);
555  if (p_flags & SF_SHARED) fputs(" shared", f);
556  if (p_flags & SF_PRELOAD_PAGES) fputs(" preload", f);
557  if (p_flags & SF_INVALID_PAGES) fputs(" invalid", f);
558  if (p_flags & SF_RES_LONG_LOCK) fputs(" res-long-lock", f);
559  if (p_flags & SF_1616_ALIAS) fputs(" 16:16-alias", f);
560  if (p_flags & SF_BIG_BIT) fputs(" big-bit", f);
561  if (p_flags & SF_CODE_CONFORM) fputs(" code-conform", f);
562  if (p_flags & SF_IO_PRIV) fputs(" io-priv", f);
563  fputc('\n', f);
564 
565  fprintf(f, "%s%-*s = %u\n", p, w, "pagemap_index", p_pagemap_index);
566  fprintf(f, "%s%-*s = %u entries\n", p, w, "pagemap_nentries", p_pagemap_nentries);
567  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "res1", p_res1);
568 }
569 
570 /* Print some debugging info. */
571 void
572 SgAsmLESection::dump(FILE *f, const char *prefix, ssize_t idx) const
573 {
574  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
575 
576  char p[4096];
577  if (idx>=0) {
578  sprintf(p, "%s%sSection[%zd].", prefix, fhdr->format_name(), idx);
579  } else {
580  sprintf(p, "%s%sSection.", prefix, fhdr->format_name());
581  }
582 
583  SgAsmGenericSection::dump(f, p, -1);
584  p_st_entry->dump(f, p, -1);
585 }
586 
587 /* Constructor */
588 void
590 {
591  set_offset(offset);
592  set_size(size);
593  grab_content();
594 
595  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
596  ROSE_ASSERT(fhdr!=NULL);
597 
598  set_synthesized(true);
599  char section_name[64];
600  sprintf(section_name, "%s Section Table", fhdr->format_name());
601  set_name(new SgAsmBasicString(section_name));
603 
604  SgAsmLEPageTable *pages = fhdr->get_page_table();
605 
606  const size_t entsize = sizeof(SgAsmLESectionTableEntry::LESectionTableEntry_disk);
607  for (size_t i = 0; i < fhdr->get_e_secttab_nentries(); i++) {
608  /* Parse the section table entry */
610  read_content_local(i*entsize, &disk, entsize);
611  SgAsmLESectionTableEntry *entry = new SgAsmLESectionTableEntry(fhdr->get_sex(), &disk);
612 
613  /* The section pages in the executable file. For now we require that the entries in the page table for the section
614  * being defined are contiguous in the executable file, otherwise we'd have to define more than one actual section to
615  * represent this section table entry. */
616  rose_addr_t section_offset, section_size; /*offset and size of section within file */
617  SgAsmLEPageTableEntry *page = pages->get_page(entry->get_pagemap_index());
618 #ifndef NDEBUG
619  for (size_t j = 1; j < entry->get_pagemap_nentries(); j++) {
620  SgAsmLEPageTableEntry *p2 = pages->get_page(entry->get_pagemap_index()+j);
621  ROSE_ASSERT(page->get_pageno()+j == p2->get_pageno());
622  }
623 #endif
624  rose_addr_t pageno = page->get_pageno();
625  ROSE_ASSERT(pageno>0);
626  if (FAMILY_LE==fhdr->get_exec_format()->get_family()) {
627  section_offset = fhdr->get_e_data_pages_offset() + (pageno-1) * fhdr->get_e_page_size();
628 
629  section_size = std::min(entry->get_mapped_size(), entry->get_pagemap_nentries() * fhdr->get_e_page_size());
630 
631  } else {
632  ROSE_ASSERT(FAMILY_LX==fhdr->get_exec_format()->get_family());
633  section_offset = fhdr->get_e_data_pages_offset() + ((pageno-1) << fhdr->get_e_page_offset_shift());
634 
635  section_size = std::min(entry->get_mapped_size(),
636  (rose_addr_t)(entry->get_pagemap_nentries() * (1<<fhdr->get_e_page_offset_shift())));
637 
638  }
639 
640  SgAsmLESection *section = new SgAsmLESection(fhdr);
641  section->set_offset(section_offset);
642  section->set_size(section_size);
643  section->parse();
644  section->set_synthesized(false);
645  section->set_id(i+1); /*numbered starting at 1, not zero*/
646  section->set_purpose(SP_PROGRAM);
647  section->set_st_entry(entry);
648 
649  /* Section permissions */
650  section->set_mapped_preferred_rva(entry->get_base_addr());
651  section->set_mapped_actual_va(0); /*assigned by Loader*/
652  section->set_mapped_size(entry->get_mapped_size());
659 
660  unsigned section_type = entry->get_flags() & SgAsmLESectionTableEntry::SF_TYPE_MASK;
661  if (SgAsmLESectionTableEntry::SF_TYPE_ZERO==section_type) {
662  section->set_name(new SgAsmBasicString(".bss"));
663  } else if (entry->get_flags() & SgAsmLESectionTableEntry::SF_EXECUTABLE) {
664  section->set_name(new SgAsmBasicString(".text"));
665  }
666  }
667 }
668 
669 /* Writes the section table back to disk along with each of the sections. */
670 void
671 SgAsmLESectionTable::unparse(std::ostream &f) const
672 {
673  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
674  ROSE_ASSERT(fhdr!=NULL);
676 
677  for (size_t i = 0; i < sections.size(); i++) {
678  if (sections[i]->get_id() >= 0) {
679  SgAsmLESection *section = dynamic_cast<SgAsmLESection*>(sections[i]);
680 
681  /* Write the table entry */
682  ROSE_ASSERT(section->get_id()>0); /*ID's are 1-origin in LE*/
683  size_t slot = section->get_id()-1;
684  SgAsmLESectionTableEntry *shdr = section->get_st_entry();
686  shdr->encode(get_header()->get_sex(), &disk);
687  write(f, slot*sizeof(disk), sizeof disk, &disk);
688 
689  /* Write the section */
690  section->unparse(f);
691  }
692  }
693 }
694 
695 /* Prints some debugging info */
696 void
697 SgAsmLESectionTable::dump(FILE *f, const char *prefix, ssize_t idx) const
698 {
699  char p[4096];
700  if (idx>=0) {
701  sprintf(p, "%s%sSectionTable[%zd].", prefix, get_header()->format_name(), idx);
702  } else {
703  sprintf(p, "%s%sSectionTable.", prefix, get_header()->format_name());
704  }
705  SgAsmGenericSection::dump(f, p, -1);
706 }
707 
709 // LE/LX Resident and Non-Resident Name Tables
711 
712 /* Constructor assumes SgAsmGenericSection is zero bytes long so far */
713 void
715 {
716  set_offset(offset);
717  set_size(0);
718  grab_content();
719 
720  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
721  ROSE_ASSERT(fhdr!=NULL);
722 
723  set_synthesized(true);
724  char section_name[64];
725  sprintf(section_name, "%s Name Table", fhdr->format_name());
726  set_name(new SgAsmBasicString(section_name));
728 
729  /* Resident exported procedure names, until we hit a zero length name. The first name
730  * is for the library itself and the corresponding ordinal has no meaning. */
731  rose_addr_t at = 0;
732  while (1) {
733  extend(1);
734  unsigned char byte;
735  read_content_local(at++, &byte, 1);
736  size_t length = byte;
737  if (0==length) break;
738 
739  extend(length);
740  char *buf = new char[length];
741  read_content_local(at, buf, length);
742  p_names.push_back(std::string(buf, length));
743  delete[] buf;
744  at += length;
745 
746  extend(2);
747  uint16_t u16_disk;
748  read_content_local(at, &u16_disk, 2);
749  p_ordinals.push_back(ByteOrder::le_to_host(u16_disk));
750  at += 2;
751  }
752 }
753 
754 /* Writes the section back to disk. */
755 void
756 SgAsmLENameTable::unparse(std::ostream &f) const
757 {
758  rose_addr_t spos=0; /*section offset*/
759  ROSE_ASSERT(p_names.size() == p_ordinals.size());
760  for (size_t i = 0; i < p_names.size(); i++) {
761  /* Name length */
762  ROSE_ASSERT(p_names[i].size() <= 0xff);
763  unsigned char len = p_names[i].size();
764  spos = write(f, spos, len);
765 
766  /* Name */
767  spos = write(f, spos, p_names[i]);
768 
769  /* Ordinal */
770  ROSE_ASSERT(p_ordinals[i] <= 0xffff);
771  uint16_t ordinal_le;
772  ByteOrder::host_to_le(p_ordinals[i], &ordinal_le);
773  spos = write(f, spos, sizeof ordinal_le, &ordinal_le);
774  }
775 
776  /* Zero-terminated */
777  write(f, spos, '\0');
778 }
779 
780 /* Prints some debugging info */
781 void
782 SgAsmLENameTable::dump(FILE *f, const char *prefix, ssize_t idx) const
783 {
784  char p[4096];
785  if (idx>=0) {
786  sprintf(p, "%sLENameTable[%zd].", prefix, idx);
787  } else {
788  sprintf(p, "%sLENameTable.", prefix);
789  }
790 
791  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
792 
793  SgAsmGenericSection::dump(f, p, -1);
794  ROSE_ASSERT(p_names.size() == p_ordinals.size());
795  for (size_t i = 0; i < p_names.size(); i++) {
796  fprintf(f, "%s%-*s = [%zd] \"%s\"\n", p, w, "names", i, escapeString(p_names[i]).c_str());
797  fprintf(f, "%s%-*s = [%zd] %u\n", p, w, "ordinals", i, p_ordinals[i]);
798  }
799 }
800 
802 // LE/LX Entry Table
804 
805 /* Constructor */
806 void
808 {
809  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
813  p_res1 = ByteOrder::disk_to_host(sex, disk->res1);
814 }
815 
816 /* Write the entry information back to the disk at the specified section and section offset, returning the new section offset. */
819  rose_addr_t spos) const
820 {
821  if (0==(p_flags & 0x01)) {
822  /* Empty entry; write only the flag byte */
823  uint8_t byte;
824  ByteOrder::host_to_disk(sex, p_flags, &byte);
825  spos = section->write(f, spos, byte);
826  } else {
827  /* Non-empty entry */
828  LEEntryPoint_disk disk;
829  ByteOrder::host_to_disk(sex, p_flags, &(disk.flags));
830  ByteOrder::host_to_disk(sex, p_objnum, &(disk.objnum));
833  ByteOrder::host_to_disk(sex, p_res1, &(disk.res1));
834  spos = section->write(f, spos, sizeof disk, &disk);
835  }
836  return spos;
837 }
838 
839 /* Print some debugging info */
840 void
841 SgAsmLEEntryPoint::dump(FILE *f, const char *prefix, ssize_t idx) const
842 {
843  char p[4096];
844  if (idx>=0) {
845  sprintf(p, "%sEntryPoint[%zd].", prefix, idx);
846  } else {
847  sprintf(p, "%sEntryPoint.", prefix);
848  }
849 
850  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
851 
852  fprintf(f, "%s%-*s = 0x%02x", p, w, "flags", p_flags);
853  if (p_flags & 0x01)
854  fprintf(f, " 32-bit");
855  if (p_flags & 0x01) {
856  fprintf(f, " non-empty\n");
857  fprintf(f, "%s%-*s = %u\n", p, w, "objnum", p_objnum);
858  fprintf(f, "%s%-*s = 0x%02x", p, w, "entry_type", p_entry_type);
859  if (p_entry_type & 0x01) fputs(" exported", f);
860  if (p_entry_type & 0x02) fputs(" shared-data", f);
861  fprintf(f, " stack-params=%u\n", (p_entry_type >> 3) & 0x1f);
862  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "entry_offset", p_entry_offset);
863  fprintf(f, "%s%-*s = 0x%04x\n", p, w, "res1", p_res1);
864  } else {
865  fprintf(f, " empty\n");
866  }
867 }
868 
869 /* Constructor. We don't know the size of the LE Entry table until after reading the first byte. Therefore the SgAsmGenericSection is
870  * created with an initial size of zero. */
871 void
873 {
874  set_offset(offset);
875  set_size(0);
876  grab_content();
877 
878  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
879  ROSE_ASSERT(fhdr!=NULL);
880 
881  set_synthesized(true);
882  char section_name[64];
883  sprintf(section_name, "%s Entry Table", fhdr->format_name());
884  set_name(new SgAsmBasicString(section_name));
886 
887  ROSE_ASSERT(0 == get_size());
888 
889  if (FAMILY_LX == fhdr->get_exec_format()->get_family()) {
890  /* FIXME: LX Entry tables have a different format than LE (they are similar to NE Entry Tables). See
891  * http://members.rediff.com/pguptaji/executable.htm (among others) for the format. We don't parse them
892  * at this time since it's not a Windows format and we leave the section size at zero to make this more
893  * obvious. */
894  return;
895  }
896 
897  rose_addr_t at = 0;
898  extend(1);
899  unsigned char byte;
900  read_content_local(at++, &byte, 1);
901  size_t nentries = byte;
902  for (size_t i = 0; i < nentries; i++) {
903  extend(1);
904  uint8_t flags;
905  read_content_local(at, &flags, 1);
906  if (flags & 0x01) {
909  read_content_local(at, &disk, sizeof disk);
910  p_entries.push_back(new SgAsmLEEntryPoint(fhdr->get_sex(), &disk));
911  } else {
912  p_entries.push_back(new SgAsmLEEntryPoint(fhdr->get_sex(), flags));
913  }
914  }
915 }
916 
917 /* Write entry table back to file */
918 void
919 SgAsmLEEntryTable::unparse(std::ostream &f) const
920 {
921  rose_addr_t spos=0; /*section offset*/
922  ROSE_ASSERT(p_entries.size()<=0xff);
923  uint8_t byte = p_entries.size();
924  spos = write(f, spos, byte);
925 
927  for (size_t i = 0; i < p_entries.size(); i++) {
928  spos = p_entries[i]->unparse(f, sex, this, spos);
929  }
930 }
931 
932 /* Print some debugging info */
933 void
934 SgAsmLEEntryTable::dump(FILE *f, const char *prefix, ssize_t idx) const
935 {
936  char p[4096];
937  if (idx>=0) {
938  sprintf(p, "%s%sEntryTable[%zd].", prefix, get_header()->format_name(), idx);
939  } else {
940  sprintf(p, "%s%sEntryTable.", prefix, get_header()->format_name());
941  }
942 
943  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
944 
945  SgAsmGenericSection::dump(f, p, -1);
946  fprintf(f, "%s%-*s = %zu entry points\n", p, w, "size", p_entries.size());
947  for (size_t i = 0; i < p_entries.size(); i++) {
948  p_entries[i]->dump(f, p, i);
949  }
950 }
951 
953 // LE/LX Relocation Table
955 
956 /* Constructor. */
957 void
959 {
960  set_offset(offset);
961  set_size(0);
962  grab_content();
963 
964  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
965  ROSE_ASSERT(fhdr!=NULL);
966 
967  char name[64];
968  sprintf(name, "%s Relocation Table", fhdr->format_name());
969  set_synthesized(true);
970  set_name(new SgAsmBasicString(name));
972 
973  ROSE_ASSERT(0 == get_size());
974 
975 #if 0 /*FIXME: How do we know how many entries are in the relocation table? */
976  size_t nrelocs = 0;
977 
978  // DQ (12/8/2008): reloc_size was previously not initialized before use in the for loop.
979  rose_addr_t at = 0, reloc_size = 0;
980  for (size_t i = 0; i < nrelocs; i++, at+=reloc_size) {
981  p_entries.push_back(new SgAsmLERelocEntry(this, at, &reloc_size));
982  }
983 #endif
984 }
985 
986 #if 0 /*FIXME: not implemented yet*/
987 /* Write relocation table back to disk */
988 void
989 SgAsmLERelocTable::unparse(std::ostream &f)
990 {
991  ROSE_ASSERT(0==reallocate(false)); /*should have been called well before any unparsing started*/
992 }
993 #endif
994 
995 /* Print some debugging info */
996 void
997 SgAsmLERelocTable::dump(FILE *f, const char *prefix, ssize_t idx) const
998 {
999  char p[4096];
1000  if (idx>=0) {
1001  sprintf(p, "%s%sRelocTable[%zd].", prefix, get_header()->format_name(), idx);
1002  } else {
1003  sprintf(p, "%s%sRelocTable.", prefix, get_header()->format_name());
1004  }
1005 
1006  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
1007 
1008  SgAsmGenericSection::dump(f, p, -1);
1009  fprintf(f, "%s%-*s = %zu entries\n", p, w, "size", p_entries.size());
1010  for (size_t i = 0; i < p_entries.size(); i++) {
1011  p_entries[i]->dump(f, p, i);
1012  }
1013 }
1014 
1016 
1017 /* Parses the structure of an LE/LX file and adds the information to the SgAsmGenericFile. */
1020 {
1021  ROSE_ASSERT(dos_header);
1022  SgAsmGenericFile *ef = dos_header->get_file();
1023  ROSE_ASSERT(ef);
1024 
1025  /* LE files extend the DOS header with some additional info */
1026  SgAsmDOSExtendedHeader *dos2_header = new SgAsmDOSExtendedHeader(dos_header);
1027  dos2_header->set_offset(dos_header->get_size());
1028  dos2_header->parse();
1029 
1030  /* The LE header */
1031  SgAsmLEFileHeader *le_header = new SgAsmLEFileHeader(ef, dos2_header->get_e_lfanew());
1032  le_header->set_dos2_header(dos2_header);
1033 
1034  /* Page Table */
1035  if (le_header->get_e_pagetab_rfo() > 0 && le_header->get_e_npages() > 0) {
1036  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_pagetab_rfo();
1037  rose_addr_t table_size = le_header->get_e_npages() * sizeof(SgAsmLEPageTableEntry::LEPageTableEntry_disk);
1038  SgAsmLEPageTable *table = new SgAsmLEPageTable(le_header, table_offset, table_size);
1039  le_header->set_page_table(table);
1040  }
1041 
1042  /* Section (Object) Table */
1043  if (le_header->get_e_secttab_rfo() > 0 && le_header->get_e_secttab_nentries() > 0) {
1044  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_secttab_rfo();
1046  SgAsmLESectionTable *table = new SgAsmLESectionTable(le_header, table_offset, table_size);
1047  le_header->set_section_table(table);
1048  }
1049 
1050  /* Resource Table */
1051  if (le_header->get_e_rsrctab_rfo() > 0 && le_header->get_e_rsrctab_nentries() > 0) {
1052  /*FIXME*/
1053  }
1054 
1055  /* Resident Names Table */
1056  if (le_header->get_e_resnametab_rfo() > 0) {
1057  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_resnametab_rfo();
1058  SgAsmLENameTable *table = new SgAsmLENameTable(le_header, table_offset);
1059  char section_name[64];
1060  sprintf(section_name, "%s Resident Name Table", le_header->format_name());
1061  table->set_name(new SgAsmBasicString(section_name));
1062  le_header->set_resname_table(table);
1063  }
1064 
1065  /* Non-resident Names Table */
1066  if (le_header->get_e_nonresnametab_offset() > 0) {
1067  rose_addr_t table_offset = le_header->get_e_nonresnametab_offset();
1068  SgAsmLENameTable *table = new SgAsmLENameTable(le_header, table_offset);
1069  char section_name[64];
1070  sprintf(section_name, "%s Non-resident Name Table", le_header->format_name());
1071  table->set_name(new SgAsmBasicString(section_name));
1072  le_header->set_nonresname_table(table);
1073  }
1074 
1075  /* Entry Table */
1076  if (le_header->get_e_entrytab_rfo() > 0) {
1077  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_entrytab_rfo();
1078  SgAsmLEEntryTable *table = new SgAsmLEEntryTable(le_header, table_offset);
1079  le_header->set_entry_table(table);
1080  }
1081 
1082  /* Fixup (Relocation) Table */
1083  if (le_header->get_e_fixup_rectab_rfo() > 0) {
1084  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_fixup_rectab_rfo();
1085  SgAsmLERelocTable *table = new SgAsmLERelocTable(le_header, table_offset);
1086  le_header->set_reloc_table(table);
1087  }
1088 
1089 // /*
1090 // * The table locations are indicated in the header but sizes are not stored. Any table whose offset is zero or whose
1091 // * size, calculated from the location of the following table, is zero is not present. */
1092 // rose_addr_t end_rfo = le_header->get_size() + le_header->e_loader_sect_size;
1093 // if (le_header->e_ppcksumtab_rfo > 0 && le_header->e_ppcksumtab_rfo < end_rfo) {
1094 // /* Per-Page Checksum */
1095 // rose_addr_t table_offset = le_header->get_offset() + le_header->e_ppcksumtab_rfo;
1096 // rose_addr_t table_size = end_rfo - le_header->e_ppcksumtab_rfo;
1097 // SgAsmGenericSection *table = new SgAsmGenericSection(ef, table_offset, table_size);
1098 // table->set_synthesized(true);
1099 // char section_name[64];
1100 // sprintf(section_name, "%s Per-Page Checksum Table", le_header->format_name());
1101 // table->set_name(section_name);
1102 // table->set_purpose(SP_HEADER);
1103 // table->set_header(le_header);
1104 // end_rfo = le_header->e_ppcksumtab_rfo;
1105 // }
1106 // if (0) {
1107 // /* FIXME: "Resident Directives Data" goes here! */
1108 // }
1109 // if (le_header->e_fmtdirtab_rfo > 0 && le_header->e_fmtdirtab_rfo < end_rfo) {
1110 // /* Module Format Directives Table */
1111 // rose_addr_t table_offset = le_header->get_offset() + le_header->e_fmtdirtab_rfo;
1112 // rose_addr_t table_size = end_rfo - le_header->e_fmtdirtab_rfo;
1113 // SgAsmGenericSection *table = new SgAsmGenericSection(ef, table_offset, table_size);
1114 // table->set_synthesized(true);
1115 // char section_name[64];
1116 // sprintf(section_name, "%s Module Format Directives Table", le_header->format_name());
1117 // table->set_name(section_name);
1118 // table->set_purpose(SP_HEADER);
1119 // table->set_header(le_header);
1120 // end_rfo = le_header->e_fmtdirtab_rfo;
1121 // }
1122 
1123  return le_header;
1124 }
1125 
1126 // }; //namespace LE
1127 // }; //namespace Exec