ROSE  0.11.50.0
ExecLE.C
1 /* Copyright 2008 Lawrence Livermore National Security, LLC */
2 #include <featureTests.h>
3 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
4 #include "sage3basic.h"
5 
6 // In order to efficiently (in terms of amount of code) parse a file format that's defined for a different architecture, we
7 // need to occassionally take addresses of structs that don't follow alignment rules for this architecture.
8 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
9 
10 // DQ (8/21/2008): Now we want to move away from using the older header files (from before we used the IR nodes).
11 // #include "ExecLE.h"
12 
13 // namespace Exec {
14 // namespace LE {
15 
17 // LE File Header
19 
20 void
21 SgAsmLEFileHeader::ctor(SgAsmGenericFile *f, rose_addr_t offset)
22 {
23  set_offset(offset);
24  set_size(sizeof(LEFileHeader_disk));
25  grab_content();
26 
27  // DQ (8/16/2008): Added code to set SgAsmPEFileHeader as parent of input SgAsmGenericFile
28  f->set_parent(this);
29 
30  LEFileHeader_disk fh;
31  read_content_local(0, &fh, sizeof fh);
32 
33  /* Check magic number early */
34  if (fh.e_magic[0]!='L' ||
35  (fh.e_magic[1]!='E' && fh.e_magic[1]!='X'))
36  throw FormatError("Bad LE/LX magic number");
37 
38  /* Decode file header */
39  p_exec_format->set_family( fh.e_magic[1]=='E' ? FAMILY_LE : FAMILY_LX );
40  const char *section_name = FAMILY_LE == p_exec_format->get_family() ? "LE File Header" : "LX File Header";
41  set_name(new SgAsmBasicString(section_name));
42  set_synthesized(true);
44  p_e_byte_order = ByteOrder::le_to_host(fh.e_byte_order);
45  p_e_word_order = ByteOrder::le_to_host(fh.e_word_order);
46  ROSE_ASSERT(p_e_byte_order == p_e_word_order);
47  ByteOrder::Endianness sex = 0 == p_e_byte_order ? ByteOrder::ORDER_LSB : ByteOrder::ORDER_MSB;
48 
49  p_e_format_level = ByteOrder::disk_to_host(sex, fh.e_format_level);
50  p_e_cpu_type = ByteOrder::disk_to_host(sex, fh.e_cpu_type);
51  p_e_os_type = ByteOrder::disk_to_host(sex, fh.e_os_type);
52  p_e_module_version = ByteOrder::disk_to_host(sex, fh.e_module_version);
53  p_e_flags = ByteOrder::disk_to_host(sex, fh.e_flags);
54  p_e_npages = ByteOrder::disk_to_host(sex, fh.e_npages);
55  p_e_eip_section = ByteOrder::disk_to_host(sex, fh.e_eip_section);
56  p_e_eip = ByteOrder::disk_to_host(sex, fh.e_eip);
57  p_e_esp_section = ByteOrder::disk_to_host(sex, fh.e_esp_section);
58  p_e_esp = ByteOrder::disk_to_host(sex, fh.e_esp);
59  p_e_page_size = ByteOrder::disk_to_host(sex, fh.e_page_size);
60  if (FAMILY_LE == p_exec_format->get_family()) {
61  p_e_last_page_size = ByteOrder::disk_to_host(sex, fh.e_lps_or_shift);
62  p_e_page_offset_shift = 0;
63  } else {
64  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
65  p_e_last_page_size = 0;
66  p_e_page_offset_shift = ByteOrder::disk_to_host(sex, fh.e_lps_or_shift);
67  }
68  p_e_fixup_sect_size = ByteOrder::disk_to_host(sex, fh.e_fixup_sect_size);
69  p_e_fixup_sect_cksum = ByteOrder::disk_to_host(sex, fh.e_fixup_sect_cksum);
70  p_e_loader_sect_size = ByteOrder::disk_to_host(sex, fh.e_loader_sect_size);
71  p_e_loader_sect_cksum = ByteOrder::disk_to_host(sex, fh.e_loader_sect_cksum);
72  p_e_secttab_rfo = ByteOrder::disk_to_host(sex, fh.e_secttab_rfo);
73  p_e_secttab_nentries = ByteOrder::disk_to_host(sex, fh.e_secttab_nentries);
74  p_e_pagetab_rfo = ByteOrder::disk_to_host(sex, fh.e_pagetab_rfo);
75  p_e_iterpages_offset = ByteOrder::disk_to_host(sex, fh.e_iterpages_offset);
76  p_e_rsrctab_rfo = ByteOrder::disk_to_host(sex, fh.e_rsrctab_rfo);
77  p_e_rsrctab_nentries = ByteOrder::disk_to_host(sex, fh.e_rsrctab_nentries);
78  p_e_resnametab_rfo = ByteOrder::disk_to_host(sex, fh.e_resnametab_rfo);
79  p_e_entrytab_rfo = ByteOrder::disk_to_host(sex, fh.e_entrytab_rfo);
80  p_e_fmtdirtab_rfo = ByteOrder::disk_to_host(sex, fh.e_fmtdirtab_rfo);
81  p_e_fmtdirtab_nentries = ByteOrder::disk_to_host(sex, fh.e_fmtdirtab_nentries);
82  p_e_fixup_pagetab_rfo = ByteOrder::disk_to_host(sex, fh.e_fixup_pagetab_rfo);
83  p_e_fixup_rectab_rfo = ByteOrder::disk_to_host(sex, fh.e_fixup_rectab_rfo);
84  p_e_import_modtab_rfo = ByteOrder::disk_to_host(sex, fh.e_import_modtab_rfo);
85  p_e_import_modtab_nentries = ByteOrder::disk_to_host(sex, fh.e_import_modtab_nentries);
86  p_e_import_proctab_rfo = ByteOrder::disk_to_host(sex, fh.e_import_proctab_rfo);
87  p_e_ppcksumtab_rfo = ByteOrder::disk_to_host(sex, fh.e_ppcksumtab_rfo);
88  p_e_data_pages_offset = ByteOrder::disk_to_host(sex, fh.e_data_pages_offset);
89  p_e_preload_npages = ByteOrder::disk_to_host(sex, fh.e_preload_npages);
90  p_e_nonresnametab_offset = ByteOrder::disk_to_host(sex, fh.e_nonresnametab_offset);
91  p_e_nonresnametab_size = ByteOrder::disk_to_host(sex, fh.e_nonresnametab_size);
92  p_e_nonresnametab_cksum = ByteOrder::disk_to_host(sex, fh.e_nonresnametab_cksum);
93  p_e_auto_ds_section = ByteOrder::disk_to_host(sex, fh.e_auto_ds_section);
94  p_e_debug_info_rfo = ByteOrder::disk_to_host(sex, fh.e_debug_info_rfo);
95  p_e_debug_info_size = ByteOrder::disk_to_host(sex, fh.e_debug_info_size);
96  p_e_num_instance_preload = ByteOrder::disk_to_host(sex, fh.e_num_instance_preload);
97  p_e_num_instance_demand = ByteOrder::disk_to_host(sex, fh.e_num_instance_demand);
98  p_e_heap_size = ByteOrder::disk_to_host(sex, fh.e_heap_size);
99 
100  /* Magic number */
101  for (size_t i = 0; i < sizeof(fh.e_magic); ++i)
102  p_magic.push_back(fh.e_magic[i]);
103 
104  /* File format */
105  //exec_format.family = ???; /*set above*/
106  p_exec_format->set_purpose( HF_MODTYPE_PROG == (p_e_flags & HF_MODTYPE_MASK) ? PURPOSE_EXECUTABLE : PURPOSE_LIBRARY );
107  p_exec_format->set_sex( sex );
108  switch (p_e_os_type) {
109  case 0: p_exec_format->set_abi( ABI_UNSPECIFIED ); break;
110  case 1: p_exec_format->set_abi( ABI_OS2 ); break;
111  case 2: p_exec_format->set_abi( ABI_NT ); break;
112  case 3: p_exec_format->set_abi( ABI_MSDOS ); break;
113  case 4: p_exec_format->set_abi( ABI_WIN386 ); break;
114  default: p_exec_format->set_abi( ABI_OTHER ); break;
115  }
116  p_exec_format->set_abi_version( 0 );
117  p_exec_format->set_word_size( 4 );
118  p_exec_format->set_version( p_e_format_level );
119  p_exec_format->set_is_current_version( 0 == p_e_format_level );
120 
121  /* Target architecture */
122  switch (p_e_cpu_type) {
123  case 0x01: set_isa(ISA_IA32_286); break;
124  case 0x02: set_isa(ISA_IA32_386); break;
125  case 0x03: set_isa(ISA_IA32_486); break;
126  case 0x04: set_isa(ISA_IA32_Pentium); break;
127  case 0x20: set_isa(ISA_I860_860XR); break; /*N10*/
128  case 0x21: set_isa(ISA_I860_860XP); break; /*N11*/
129  case 0x40: set_isa(ISA_MIPS_MarkI); break; /*R2000, R3000*/
130  case 0x41: set_isa(ISA_MIPS_MarkII); break; /*R6000*/
131  case 0x42: set_isa(ISA_MIPS_MarkIII); break; /*R4000*/
132  default: set_isa(ISA_OTHER); break;
133  }
134 
135  /* Entry point */
136 // entry_rva = ???; /*FIXME: see e_eip and e_eip_section; we must parse section table first */
137 }
138 
142 bool
144 {
145  /* Turn off byte reference tracking for the duration of this function. We don't want our testing the file contents to
146  * affect the list of bytes that we've already referenced or which we might reference later. */
147  bool was_tracking = file->get_tracking_references();
148  file->set_tracking_references(false);
149 
150  try {
151  /* Check DOS File Header magic number at beginning of the file */
152  unsigned char dos_magic[2];
153  file->read_content(0, dos_magic, sizeof dos_magic);
154  if ('M'!=dos_magic[0] || 'Z'!=dos_magic[1])
155  throw 1;
156 
157  /* Read four-byte offset of potential LE/LX File Header at offset 0x3c */
158  uint32_t lfanew_disk;
159  file->read_content(0x3c, &lfanew_disk, sizeof lfanew_disk);
160  rose_addr_t le_offset = ByteOrder::le_to_host(lfanew_disk);
161 
162  /* Look for the LE/LX File Header magic number */
163  unsigned char le_magic[4];
164  file->read_content(le_offset, le_magic, sizeof le_magic);
165  if ('L'!=le_magic[0] || ('E'!=le_magic[1] && 'X'!=le_magic[1]))
166  throw 1;
167  } catch (...) {
168  file->set_tracking_references(was_tracking);
169  return false;
170  }
171 
172  file->set_tracking_references(was_tracking);
173  return true;
174 }
175 
176 /* Encode the LE header into disk format */
177 void *
178 SgAsmLEFileHeader::encode(ByteOrder::Endianness sex, LEFileHeader_disk *disk) const
179 {
180  for (size_t i=0; i<NELMTS(disk->e_magic); i++)
181  disk->e_magic[i] = get_magic()[i];
182  host_to_disk(sex, p_e_byte_order, &(disk->e_byte_order));
183  host_to_disk(sex, p_e_word_order, &(disk->e_word_order));
184  host_to_disk(sex, p_e_format_level, &(disk->e_format_level));
185  host_to_disk(sex, p_e_cpu_type, &(disk->e_cpu_type));
186  host_to_disk(sex, p_e_os_type, &(disk->e_os_type));
187  host_to_disk(sex, p_e_module_version, &(disk->e_module_version));
188  host_to_disk(sex, p_e_flags, &(disk->e_flags));
189  host_to_disk(sex, p_e_npages, &(disk->e_npages));
190  host_to_disk(sex, p_e_eip_section, &(disk->e_eip_section));
191  host_to_disk(sex, p_e_eip, &(disk->e_eip));
192  host_to_disk(sex, p_e_esp_section, &(disk->e_esp_section));
193  host_to_disk(sex, p_e_esp, &(disk->e_esp));
194  host_to_disk(sex, p_e_page_size, &(disk->e_page_size));
195  if (FAMILY_LE == p_exec_format->get_family()) {
196  host_to_disk(sex, p_e_last_page_size, &(disk->e_lps_or_shift));
197  } else {
198  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
199  host_to_disk(sex, p_e_page_offset_shift, &(disk->e_lps_or_shift));
200  }
201  host_to_disk(sex, p_e_fixup_sect_size, &(disk->e_fixup_sect_size));
202  host_to_disk(sex, p_e_fixup_sect_cksum, &(disk->e_fixup_sect_cksum));
203  host_to_disk(sex, p_e_loader_sect_size, &(disk->e_loader_sect_size));
204  host_to_disk(sex, p_e_loader_sect_cksum, &(disk->e_loader_sect_cksum));
205  host_to_disk(sex, p_e_secttab_rfo, &(disk->e_secttab_rfo));
206  host_to_disk(sex, p_e_secttab_nentries, &(disk->e_secttab_nentries));
207  host_to_disk(sex, p_e_pagetab_rfo, &(disk->e_pagetab_rfo));
208  host_to_disk(sex, p_e_iterpages_offset, &(disk->e_iterpages_offset));
209  host_to_disk(sex, p_e_rsrctab_rfo, &(disk->e_rsrctab_rfo));
210  host_to_disk(sex, p_e_rsrctab_nentries, &(disk->e_rsrctab_nentries));
211  host_to_disk(sex, p_e_resnametab_rfo, &(disk->e_resnametab_rfo));
212  host_to_disk(sex, p_e_entrytab_rfo, &(disk->e_entrytab_rfo));
213  host_to_disk(sex, p_e_fmtdirtab_rfo, &(disk->e_fmtdirtab_rfo));
214  host_to_disk(sex, p_e_fmtdirtab_nentries, &(disk->e_fmtdirtab_nentries));
215  host_to_disk(sex, p_e_fixup_pagetab_rfo, &(disk->e_fixup_pagetab_rfo));
216  host_to_disk(sex, p_e_fixup_rectab_rfo, &(disk->e_fixup_rectab_rfo));
217  host_to_disk(sex, p_e_import_modtab_rfo, &(disk->e_import_modtab_rfo));
218  host_to_disk(sex, p_e_import_modtab_nentries, &(disk->e_import_modtab_nentries));
219  host_to_disk(sex, p_e_import_proctab_rfo, &(disk->e_import_proctab_rfo));
220  host_to_disk(sex, p_e_ppcksumtab_rfo, &(disk->e_ppcksumtab_rfo));
221  host_to_disk(sex, p_e_data_pages_offset, &(disk->e_data_pages_offset));
222  host_to_disk(sex, p_e_preload_npages, &(disk->e_preload_npages));
223  host_to_disk(sex, p_e_nonresnametab_offset, &(disk->e_nonresnametab_offset));
224  host_to_disk(sex, p_e_nonresnametab_size, &(disk->e_nonresnametab_size));
225  host_to_disk(sex, p_e_nonresnametab_cksum, &(disk->e_nonresnametab_cksum));
226  host_to_disk(sex, p_e_auto_ds_section, &(disk->e_auto_ds_section));
227  host_to_disk(sex, p_e_debug_info_rfo, &(disk->e_debug_info_rfo));
228  host_to_disk(sex, p_e_debug_info_size, &(disk->e_debug_info_size));
229  host_to_disk(sex, p_e_num_instance_preload, &(disk->e_num_instance_preload));
230  host_to_disk(sex, p_e_num_instance_demand, &(disk->e_num_instance_demand));
231  host_to_disk(sex, p_e_heap_size, &(disk->e_heap_size));
232  return disk;
233 }
234 
235 /* Write the LE file header back to disk and all that it references */
236 void
237 SgAsmLEFileHeader::unparse(std::ostream &f) const
238 {
240  encode(get_sex(), &fh);
241  write(f, 0, sizeof fh, &fh);
242 
243  /* The extended DOS header */
244  if (p_dos2_header)
245  p_dos2_header->unparse(f);
246 
247  /* The section table and all the non-synthesized sections */
248  if (p_section_table)
249  p_section_table->unparse(f);
250 
251  /* Sections defined in the file header */
252  if (p_page_table)
253  p_page_table->unparse(f);
254  if (p_resname_table)
255  p_resname_table->unparse(f);
256  if (p_nonresname_table)
257  p_nonresname_table->unparse(f);
258  if (p_entry_table)
259  p_entry_table->unparse(f);
260  if (p_reloc_table)
261  p_reloc_table->unparse(f);
262 }
263 
264 /* Format name */
265 const char *
266 SgAsmLEFileHeader::format_name() const
267 {
268  if (FAMILY_LE == p_exec_format->get_family()) {
269  return "LE";
270  } else {
271  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
272  return "LX";
273  }
274 }
275 
276 /* Print some debugging information */
277 void
278 SgAsmLEFileHeader::dump(FILE *f, const char *prefix, ssize_t idx) const
279 {
280  char p[4096];
281  if (idx>=0) {
282  sprintf(p, "%s%sFileHeader[%zd].", prefix, format_name(), idx);
283  } else {
284  sprintf(p, "%s%sFileHeader.", prefix, format_name());
285  }
286 
287  int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
288 
289  SgAsmGenericHeader::dump(f, p, -1);
290  fprintf(f, "%s%-*s = %u\n", p, w, "e_byte_order", p_e_byte_order);
291  fprintf(f, "%s%-*s = %u\n", p, w, "e_word_order", p_e_word_order);
292  fprintf(f, "%s%-*s = %u\n", p, w, "e_format_level", p_e_format_level);
293  fprintf(f, "%s%-*s = %u\n", p, w, "e_cpu_type", p_e_cpu_type);
294  fprintf(f, "%s%-*s = %u\n", p, w, "e_os_type", p_e_os_type);
295  fprintf(f, "%s%-*s = %u\n", p, w, "e_module_version", p_e_module_version);
296  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_flags", p_e_flags);
297  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_npages", p_e_npages);
298  fprintf(f, "%s%-*s = %u\n", p, w, "e_eip_section", p_e_eip_section);
299  fprintf(f, "%s%-*s = 0x%08" PRIx64 "\n", p, w, "e_eip", p_e_eip);
300  fprintf(f, "%s%-*s = %u\n", p, w, "e_esp_section", p_e_esp_section);
301  fprintf(f, "%s%-*s = 0x%08" PRIx64 "\n", p, w, "e_esp", p_e_esp);
302  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_page_size", p_e_page_size);
303  if (FAMILY_LE == p_exec_format->get_family()) {
304  fprintf(f, "%s%-*s = %u\n", p, w, "e_last_page_size", p_e_last_page_size);
305  } else {
306  ROSE_ASSERT(FAMILY_LX == p_exec_format->get_family());
307  fprintf(f, "%s%-*s = %u\n", p, w, "e_page_offset_shift", p_e_page_offset_shift);
308  }
309  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_fixup_sect_size", p_e_fixup_sect_size);
310  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_fixup_sect_cksum", p_e_fixup_sect_cksum);
311  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_loader_sect_size", p_e_loader_sect_size);
312  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_loader_sect_cksum", p_e_loader_sect_cksum);
313  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_secttab_rfo",
314  p_e_secttab_rfo, p_e_secttab_rfo+p_offset);
315  fprintf(f, "%s%-*s = %u\n", p, w, "e_secttab_nentries", p_e_secttab_nentries);
316  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_pagetab_rfo",
317  p_e_pagetab_rfo, p_e_pagetab_rfo+p_offset);
318  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_iterpages_offset", p_e_iterpages_offset);
319  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_rsrctab_rfo",
320  p_e_rsrctab_rfo, p_e_rsrctab_rfo+p_offset);
321  fprintf(f, "%s%-*s = %u\n", p, w, "e_rsrctab_nentries", p_e_rsrctab_nentries);
322  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_resnametab_rfo",
323  p_e_resnametab_rfo, p_e_resnametab_rfo+p_offset);
324  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_entrytab_rfo",
325  p_e_entrytab_rfo, p_e_entrytab_rfo+p_offset);
326  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_fmtdirtab_rfo",
327  p_e_fmtdirtab_rfo, p_e_fmtdirtab_rfo+p_offset);
328  fprintf(f, "%s%-*s = %u\n", p, w, "e_fmtdirtab_nentries", p_e_fmtdirtab_nentries);
329  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_fixup_pagetab_rfo",
330  p_e_fixup_pagetab_rfo, p_e_fixup_pagetab_rfo+p_offset);
331  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_fixup_rectab_rfo",
332  p_e_fixup_rectab_rfo, p_e_fixup_rectab_rfo+p_offset);
333  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_import_modtab_rfo",
334  p_e_import_modtab_rfo, p_e_import_modtab_rfo+p_offset);
335  fprintf(f, "%s%-*s = %u\n", p, w, "e_import_modtab_nentries", p_e_import_modtab_nentries);
336  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_import_proctab_rfo",
337  p_e_import_proctab_rfo, p_e_import_proctab_rfo+p_offset);
338  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_ppcksumtab_rfo",
339  p_e_ppcksumtab_rfo, p_e_ppcksumtab_rfo+p_offset);
340  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_data_pages_offset", p_e_data_pages_offset);
341  fprintf(f, "%s%-*s = %u\n", p, w, "e_preload_npages", p_e_preload_npages);
342  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "e_nonresnametab_offset", p_e_nonresnametab_offset);
343  fprintf(f, "%s%-*s = %u\n", p, w, "e_nonresnametab_size", p_e_nonresnametab_size);
344  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "e_nonresnametab_cksum", p_e_nonresnametab_cksum);
345  fprintf(f, "%s%-*s = %u\n", p, w, "e_auto_ds_section", p_e_auto_ds_section);
346  fprintf(f, "%s%-*s = %" PRIu64 " (%" PRIu64 " abs)\n", p, w, "e_debug_info_rfo",
347  p_e_debug_info_rfo, p_e_debug_info_rfo+p_offset);
348  fprintf(f, "%s%-*s = %u\n", p, w, "e_debug_info_size", p_e_debug_info_size);
349  fprintf(f, "%s%-*s = %u\n", p, w, "e_num_instance_preload", p_e_num_instance_preload);
350  fprintf(f, "%s%-*s = %u\n", p, w, "e_num_instance_demand", p_e_num_instance_demand);
351  fprintf(f, "%s%-*s = %u\n", p, w, "e_heap_size", p_e_heap_size);
352 
353  if (p_dos2_header) {
354  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "dos2_header",
355  p_dos2_header->get_id(), p_dos2_header->get_name()->get_string(true).c_str());
356  } else {
357  fprintf(f, "%s%-*s = none\n", p, w, "dos2_header");
358  }
359  if (p_section_table) {
360  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "section_table",
361  p_section_table->get_id(), p_section_table->get_name()->get_string(true).c_str());
362  } else {
363  fprintf(f, "%s%-*s = none\n", p, w, "section_table");
364  }
365  if (p_page_table) {
366  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "page_table",
367  p_page_table->get_id(), p_page_table->get_name()->get_string(true).c_str());
368  } else {
369  fprintf(f, "%s%-*s = none\n", p, w, "page_table");
370  }
371  if (p_resname_table) {
372  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "resname_table",
373  p_resname_table->get_id(), p_resname_table->get_name()->get_string(true).c_str());
374  } else {
375  fprintf(f, "%s%-*s = none\n", p, w, "resname_table");
376  }
377  if (p_nonresname_table) {
378  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "nonresname_table",
379  p_nonresname_table->get_id(), p_nonresname_table->get_name()->get_string(true).c_str());
380  } else {
381  fprintf(f, "%s%-*s = none\n", p, w, "nonresname_table");
382  }
383  if (p_entry_table) {
384  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "entry_table",
385  p_entry_table->get_id(), p_entry_table->get_name()->get_string(true).c_str());
386  } else {
387  fprintf(f, "%s%-*s = none\n", p, w, "entry_table");
388  }
389  if (p_reloc_table) {
390  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "reloc_table",
391  p_reloc_table->get_id(), p_reloc_table->get_name()->get_string(true).c_str());
392  } else {
393  fprintf(f, "%s%-*s = none\n", p, w, "reloc_table");
394  }
395 }
396 
398 // LE/LX Page Table
400 
401 /* Constructor */
402 void
403 SgAsmLEPageTableEntry::ctor(ByteOrder::Endianness sex, const SgAsmLEPageTableEntry::LEPageTableEntry_disk *disk)
404 {
405  unsigned pageno_lo = ByteOrder::disk_to_host(sex, disk->pageno_lo);
406  unsigned pageno_hi = ByteOrder::disk_to_host(sex, disk->pageno_hi);
407  p_pageno = (pageno_hi << 8) | pageno_lo;
408  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
409 }
410 
411 /* Encode page table entry to disk format */
412 void *
413 SgAsmLEPageTableEntry::encode(ByteOrder::Endianness sex, SgAsmLEPageTableEntry::LEPageTableEntry_disk *disk) const
414 {
415  host_to_disk(sex, (p_pageno & 0xff), &(disk->pageno_lo));
416  host_to_disk(sex, (p_pageno>>8)&0xffff, &(disk->pageno_hi));
417  host_to_disk(sex, p_flags, &(disk->flags));
418  return disk;
419 }
420 
421 /* Print some debugging information */
422 void
423 SgAsmLEPageTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
424 {
425  char p[4096];
426  if (idx>=0) {
427  sprintf(p, "%sPageTableEntry[%zd].", prefix, idx);
428  } else {
429  sprintf(p, "%sPageTableEntry.", prefix);
430  }
431 
432  int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
433 
434  fprintf(f, "%s%-*s = 0x%04x\n", p, w, "flags", p_flags);
435  fprintf(f, "%s%-*s = %u\n", p, w, "pageno", p_pageno);
436 }
437 
438 /* Constructor */
439 void
440 SgAsmLEPageTable::ctor(rose_addr_t offset, rose_addr_t size)
441 {
442  set_offset(offset);
443  set_size(size);
444  grab_content();
445 
446  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
447  ROSE_ASSERT(fhdr!=NULL);
448 
449  char section_name[64];
450  sprintf(section_name, "%s Page Table", fhdr->format_name());
451  set_synthesized(true);
452  set_name(new SgAsmBasicString(section_name));
454 
455  const rose_addr_t entry_size = sizeof(SgAsmLEPageTableEntry::LEPageTableEntry_disk);
456  for (rose_addr_t entry_offset=0; entry_offset+entry_size <= get_size(); entry_offset+=entry_size) {
458  read_content_local(entry_offset, &disk, entry_size);
459  p_entries.push_back(new SgAsmLEPageTableEntry(fhdr->get_sex(), &disk));
460  }
461 }
462 
463 /* Returns info about a particular page. Indices are 1-origin */
465 SgAsmLEPageTable::get_page(size_t idx)
466 {
467  ROSE_ASSERT(idx > 0);
468  ROSE_ASSERT(idx <= p_entries.size());
469  return p_entries[idx-1];
470 }
471 
472 /* Write page table back to disk */
473 void
474 SgAsmLEPageTable::unparse(std::ostream &f) const
475 {
476  rose_addr_t spos=0; /*section offset*/
477  for (size_t i=0; i < p_entries.size(); i++) {
479  p_entries[i]->encode(get_header()->get_sex(), &disk);
480  spos = write(f, spos, sizeof disk, &disk);
481  }
482 }
483 
484 /* Print some debugging information */
485 void
486 SgAsmLEPageTable::dump(FILE *f, const char *prefix, ssize_t idx) const
487 {
488  char p[4096];
489  if (idx>=0) {
490  sprintf(p, "%s%sPageTable[%zd].", prefix, get_header()->format_name(), idx);
491  } else {
492  sprintf(p, "%s%sPageTable.", prefix, get_header()->format_name());
493  }
494 
495  SgAsmGenericSection::dump(f, p, -1);
496  for (size_t i = 0; i < p_entries.size(); i++) {
497  p_entries[i]->dump(f, p, i);
498  }
499 }
500 
502 // LE/LX Section Table
504 
505 /* Constructor */
506 void
507 SgAsmLESectionTableEntry::ctor(ByteOrder::Endianness sex, const LESectionTableEntry_disk *disk)
508 {
509  p_mapped_size = ByteOrder::disk_to_host(sex, disk->mapped_size);
510  p_base_addr = ByteOrder::disk_to_host(sex, disk->base_addr);
511  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
512  p_pagemap_index = ByteOrder::disk_to_host(sex, disk->pagemap_index);
513  p_pagemap_nentries = ByteOrder::disk_to_host(sex, disk->pagemap_nentries);
514  p_res1 = ByteOrder::disk_to_host(sex, disk->res1);
515 }
516 
517 /* Encodes a section table entry back into disk format. */
518 void *
519 SgAsmLESectionTableEntry::encode(ByteOrder::Endianness sex, LESectionTableEntry_disk *disk) const
520 {
521  ByteOrder::host_to_disk(sex, p_mapped_size, &(disk->mapped_size));
522  ByteOrder::host_to_disk(sex, p_base_addr, &(disk->base_addr));
523  ByteOrder::host_to_disk(sex, p_flags, &(disk->flags));
524  ByteOrder::host_to_disk(sex, p_pagemap_index, &(disk->pagemap_index));
525  ByteOrder::host_to_disk(sex, p_pagemap_nentries, &(disk->pagemap_nentries));
526  ByteOrder::host_to_disk(sex, p_res1, &(disk->res1));
527  return disk;
528 }
529 
530 /* Prints some debugging info */
531 void
532 SgAsmLESectionTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
533 {
534  char p[4096];
535  if (idx>=0) {
536  sprintf(p, "%sLESectionTableEntry[%zd].", prefix, idx);
537  } else {
538  sprintf(p, "%sLESectionTableEntry.", prefix);
539  }
540 
541  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
542 
543  fprintf(f, "%s%-*s = %" PRIu64 " bytes\n", p, w, "mapped_size", p_mapped_size);
544  fprintf(f, "%s%-*s = 0x%08" PRIx64 "\n", p, w, "base_addr", p_base_addr);
545 
546  fprintf(f, "%s%-*s = 0x%08x", p, w, "flags", p_flags);
547  switch (p_flags & SF_TYPE_MASK) {
548  case SF_TYPE_NORMAL: fputs(" normal", f); break;
549  case SF_TYPE_ZERO: fputs(" zero", f); break;
550  case SF_TYPE_RESIDENT: fputs(" resident", f); break;
551  case SF_TYPE_RESCONT: fputs(" res-cont", f); break;
552  default: fprintf(f, "type=%u", p_flags & SF_TYPE_MASK); break;
553  }
554  fputs(" perm=", f);
555  fputc(p_flags & SF_READABLE ? 'r' : '-', f);
556  fputc(p_flags & SF_WRITABLE ? 'w' : '-', f);
557  fputc(p_flags & SF_EXECUTABLE ? 'x' : '-', f);
558  if (p_flags & SF_RESOURCE) fputs(" resource", f);
559  if (p_flags & SF_DISCARDABLE) fputs(" discardable", f);
560  if (p_flags & SF_SHARED) fputs(" shared", f);
561  if (p_flags & SF_PRELOAD_PAGES) fputs(" preload", f);
562  if (p_flags & SF_INVALID_PAGES) fputs(" invalid", f);
563  if (p_flags & SF_RES_LONG_LOCK) fputs(" res-long-lock", f);
564  if (p_flags & SF_1616_ALIAS) fputs(" 16:16-alias", f);
565  if (p_flags & SF_BIG_BIT) fputs(" big-bit", f);
566  if (p_flags & SF_CODE_CONFORM) fputs(" code-conform", f);
567  if (p_flags & SF_IO_PRIV) fputs(" io-priv", f);
568  fputc('\n', f);
569 
570  fprintf(f, "%s%-*s = %u\n", p, w, "pagemap_index", p_pagemap_index);
571  fprintf(f, "%s%-*s = %u entries\n", p, w, "pagemap_nentries", p_pagemap_nentries);
572  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "res1", p_res1);
573 }
574 
575 /* Print some debugging info. */
576 void
577 SgAsmLESection::dump(FILE *f, const char *prefix, ssize_t idx) const
578 {
579  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
580 
581  char p[4096];
582  if (idx>=0) {
583  sprintf(p, "%s%sSection[%zd].", prefix, fhdr->format_name(), idx);
584  } else {
585  sprintf(p, "%s%sSection.", prefix, fhdr->format_name());
586  }
587 
588  SgAsmGenericSection::dump(f, p, -1);
589  p_st_entry->dump(f, p, -1);
590 }
591 
592 /* Constructor */
593 void
594 SgAsmLESectionTable::ctor(rose_addr_t offset, rose_addr_t size)
595 {
596  set_offset(offset);
597  set_size(size);
598  grab_content();
599 
600  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
601  ROSE_ASSERT(fhdr!=NULL);
602 
603  set_synthesized(true);
604  char section_name[64];
605  sprintf(section_name, "%s Section Table", fhdr->format_name());
606  set_name(new SgAsmBasicString(section_name));
608 
609  SgAsmLEPageTable *pages = fhdr->get_page_table();
610 
611  const size_t entsize = sizeof(SgAsmLESectionTableEntry::LESectionTableEntry_disk);
612  for (size_t i = 0; i < fhdr->get_e_secttab_nentries(); i++) {
613  /* Parse the section table entry */
615  read_content_local(i*entsize, &disk, entsize);
616  SgAsmLESectionTableEntry *entry = new SgAsmLESectionTableEntry(fhdr->get_sex(), &disk);
617 
618  /* The section pages in the executable file. For now we require that the entries in the page table for the section
619  * being defined are contiguous in the executable file, otherwise we'd have to define more than one actual section to
620  * represent this section table entry. */
621  rose_addr_t section_offset, section_size; /*offset and size of section within file */
622  SgAsmLEPageTableEntry *page = pages->get_page(entry->get_pagemap_index());
623 #ifndef NDEBUG
624  for (size_t j = 1; j < entry->get_pagemap_nentries(); j++) {
625  SgAsmLEPageTableEntry *p2 = pages->get_page(entry->get_pagemap_index()+j);
626  ROSE_ASSERT(page->get_pageno()+j == p2->get_pageno());
627  }
628 #endif
629  rose_addr_t pageno = page->get_pageno();
630  ROSE_ASSERT(pageno>0);
631  if (FAMILY_LE==fhdr->get_exec_format()->get_family()) {
632  section_offset = fhdr->get_e_data_pages_offset() + (pageno-1) * fhdr->get_e_page_size();
633 
634  section_size = std::min(entry->get_mapped_size(), entry->get_pagemap_nentries() * fhdr->get_e_page_size());
635 
636  } else {
637  ROSE_ASSERT(FAMILY_LX==fhdr->get_exec_format()->get_family());
638  section_offset = fhdr->get_e_data_pages_offset() + ((pageno-1) << fhdr->get_e_page_offset_shift());
639 
640  section_size = std::min(entry->get_mapped_size(),
641  (rose_addr_t)(entry->get_pagemap_nentries() * (1<<fhdr->get_e_page_offset_shift())));
642 
643  }
644 
645  SgAsmLESection *section = new SgAsmLESection(fhdr);
646  section->set_offset(section_offset);
647  section->set_size(section_size);
648  section->parse();
649  section->set_synthesized(false);
650  section->set_id(i+1); /*numbered starting at 1, not zero*/
651  section->set_purpose(SP_PROGRAM);
652  section->set_st_entry(entry);
653 
654  /* Section permissions */
655  section->set_mapped_preferred_rva(entry->get_base_addr());
656  section->set_mapped_actual_va(0); /*assigned by Loader*/
657  section->set_mapped_size(entry->get_mapped_size());
658  section->set_mapped_rperm((entry->get_flags() & SgAsmLESectionTableEntry::SF_READABLE)
660  section->set_mapped_wperm((entry->get_flags() & SgAsmLESectionTableEntry::SF_WRITABLE)
662  section->set_mapped_xperm((entry->get_flags() & SgAsmLESectionTableEntry::SF_EXECUTABLE)
664 
665  unsigned section_type = entry->get_flags() & SgAsmLESectionTableEntry::SF_TYPE_MASK;
666  if (SgAsmLESectionTableEntry::SF_TYPE_ZERO==section_type) {
667  section->set_name(new SgAsmBasicString(".bss"));
668  } else if (entry->get_flags() & SgAsmLESectionTableEntry::SF_EXECUTABLE) {
669  section->set_name(new SgAsmBasicString(".text"));
670  }
671  }
672 }
673 
674 /* Writes the section table back to disk along with each of the sections. */
675 void
676 SgAsmLESectionTable::unparse(std::ostream &f) const
677 {
678  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
679  ROSE_ASSERT(fhdr!=NULL);
680  SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections();
681 
682  for (size_t i = 0; i < sections.size(); i++) {
683  if (sections[i]->get_id() >= 0) {
684  SgAsmLESection *section = dynamic_cast<SgAsmLESection*>(sections[i]);
685 
686  /* Write the table entry */
687  ROSE_ASSERT(section->get_id()>0); /*ID's are 1-origin in LE*/
688  size_t slot = section->get_id()-1;
689  SgAsmLESectionTableEntry *shdr = section->get_st_entry();
691  shdr->encode(get_header()->get_sex(), &disk);
692  write(f, slot*sizeof(disk), sizeof disk, &disk);
693 
694  /* Write the section */
695  section->unparse(f);
696  }
697  }
698 }
699 
700 /* Prints some debugging info */
701 void
702 SgAsmLESectionTable::dump(FILE *f, const char *prefix, ssize_t idx) const
703 {
704  char p[4096];
705  if (idx>=0) {
706  sprintf(p, "%s%sSectionTable[%zd].", prefix, get_header()->format_name(), idx);
707  } else {
708  sprintf(p, "%s%sSectionTable.", prefix, get_header()->format_name());
709  }
710  SgAsmGenericSection::dump(f, p, -1);
711 }
712 
714 // LE/LX Resident and Non-Resident Name Tables
716 
717 /* Constructor assumes SgAsmGenericSection is zero bytes long so far */
718 void
719 SgAsmLENameTable::ctor(rose_addr_t offset)
720 {
721  set_offset(offset);
722  set_size(0);
723  grab_content();
724 
725  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
726  ROSE_ASSERT(fhdr!=NULL);
727 
728  set_synthesized(true);
729  char section_name[64];
730  sprintf(section_name, "%s Name Table", fhdr->format_name());
731  set_name(new SgAsmBasicString(section_name));
733 
734  /* Resident exported procedure names, until we hit a zero length name. The first name
735  * is for the library itself and the corresponding ordinal has no meaning. */
736  rose_addr_t at = 0;
737  while (1) {
738  extend(1);
739  unsigned char byte;
740  read_content_local(at++, &byte, 1);
741  size_t length = byte;
742  if (0==length) break;
743 
744  extend(length);
745  char *buf = new char[length];
746  read_content_local(at, buf, length);
747  p_names.push_back(std::string(buf, length));
748  delete[] buf;
749  at += length;
750 
751  extend(2);
752  uint16_t u16_disk;
753  read_content_local(at, &u16_disk, 2);
754  p_ordinals.push_back(ByteOrder::le_to_host(u16_disk));
755  at += 2;
756  }
757 }
758 
759 /* Writes the section back to disk. */
760 void
761 SgAsmLENameTable::unparse(std::ostream &f) const
762 {
763  rose_addr_t spos=0; /*section offset*/
764  ROSE_ASSERT(p_names.size() == p_ordinals.size());
765  for (size_t i = 0; i < p_names.size(); i++) {
766  /* Name length */
767  ROSE_ASSERT(p_names[i].size() <= 0xff);
768  unsigned char len = p_names[i].size();
769  spos = write(f, spos, len);
770 
771  /* Name */
772  spos = write(f, spos, p_names[i]);
773 
774  /* Ordinal */
775  ROSE_ASSERT(p_ordinals[i] <= 0xffff);
776  uint16_t ordinal_le;
777  ByteOrder::host_to_le(p_ordinals[i], &ordinal_le);
778  spos = write(f, spos, sizeof ordinal_le, &ordinal_le);
779  }
780 
781  /* Zero-terminated */
782  write(f, spos, '\0');
783 }
784 
785 /* Prints some debugging info */
786 void
787 SgAsmLENameTable::dump(FILE *f, const char *prefix, ssize_t idx) const
788 {
789  char p[4096];
790  if (idx>=0) {
791  sprintf(p, "%sLENameTable[%zd].", prefix, idx);
792  } else {
793  sprintf(p, "%sLENameTable.", prefix);
794  }
795 
796  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
797 
798  SgAsmGenericSection::dump(f, p, -1);
799  ROSE_ASSERT(p_names.size() == p_ordinals.size());
800  for (size_t i = 0; i < p_names.size(); i++) {
801  fprintf(f, "%s%-*s = [%zd] \"%s\"\n", p, w, "names", i, escapeString(p_names[i]).c_str());
802  fprintf(f, "%s%-*s = [%zd] %u\n", p, w, "ordinals", i, p_ordinals[i]);
803  }
804 }
805 
807 // LE/LX Entry Table
809 
810 /* Constructor */
811 void
812 SgAsmLEEntryPoint::ctor(ByteOrder::Endianness sex, const SgAsmLEEntryPoint::LEEntryPoint_disk *disk)
813 {
814  p_flags = ByteOrder::disk_to_host(sex, disk->flags);
815  p_objnum = ByteOrder::disk_to_host(sex, disk->objnum);
816  p_entry_type = ByteOrder::disk_to_host(sex, disk->entry_type);
817  p_entry_offset = ByteOrder::disk_to_host(sex, disk->entry_offset);
818  p_res1 = ByteOrder::disk_to_host(sex, disk->res1);
819 }
820 
821 /* Write the entry information back to the disk at the specified section and section offset, returning the new section offset. */
822 rose_addr_t
823 SgAsmLEEntryPoint::unparse(std::ostream &f, ByteOrder::Endianness sex, const SgAsmGenericSection *section,
824  rose_addr_t spos) const
825 {
826  if (0==(p_flags & 0x01)) {
827  /* Empty entry; write only the flag byte */
828  uint8_t byte;
829  ByteOrder::host_to_disk(sex, p_flags, &byte);
830  spos = section->write(f, spos, byte);
831  } else {
832  /* Non-empty entry */
833  LEEntryPoint_disk disk;
834  ByteOrder::host_to_disk(sex, p_flags, &(disk.flags));
835  ByteOrder::host_to_disk(sex, p_objnum, &(disk.objnum));
836  ByteOrder::host_to_disk(sex, p_entry_type, &(disk.entry_type));
837  ByteOrder::host_to_disk(sex, p_entry_offset, &(disk.entry_offset));
838  ByteOrder::host_to_disk(sex, p_res1, &(disk.res1));
839  spos = section->write(f, spos, sizeof disk, &disk);
840  }
841  return spos;
842 }
843 
844 /* Print some debugging info */
845 void
846 SgAsmLEEntryPoint::dump(FILE *f, const char *prefix, ssize_t idx) const
847 {
848  char p[4096];
849  if (idx>=0) {
850  sprintf(p, "%sEntryPoint[%zd].", prefix, idx);
851  } else {
852  sprintf(p, "%sEntryPoint.", prefix);
853  }
854 
855  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
856 
857  fprintf(f, "%s%-*s = 0x%02x", p, w, "flags", p_flags);
858  if (p_flags & 0x01)
859  fprintf(f, " 32-bit");
860  if (p_flags & 0x01) {
861  fprintf(f, " non-empty\n");
862  fprintf(f, "%s%-*s = %u\n", p, w, "objnum", p_objnum);
863  fprintf(f, "%s%-*s = 0x%02x", p, w, "entry_type", p_entry_type);
864  if (p_entry_type & 0x01) fputs(" exported", f);
865  if (p_entry_type & 0x02) fputs(" shared-data", f);
866  fprintf(f, " stack-params=%u\n", (p_entry_type >> 3) & 0x1f);
867  fprintf(f, "%s%-*s = %" PRIu64 "\n", p, w, "entry_offset", p_entry_offset);
868  fprintf(f, "%s%-*s = 0x%04x\n", p, w, "res1", p_res1);
869  } else {
870  fprintf(f, " empty\n");
871  }
872 }
873 
874 /* Constructor. We don't know the size of the LE Entry table until after reading the first byte. Therefore the SgAsmGenericSection is
875  * created with an initial size of zero. */
876 void
877 SgAsmLEEntryTable::ctor(rose_addr_t offset)
878 {
879  set_offset(offset);
880  set_size(0);
881  grab_content();
882 
883  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
884  ROSE_ASSERT(fhdr!=NULL);
885 
886  set_synthesized(true);
887  char section_name[64];
888  sprintf(section_name, "%s Entry Table", fhdr->format_name());
889  set_name(new SgAsmBasicString(section_name));
891 
892  ROSE_ASSERT(0 == get_size());
893 
894  if (FAMILY_LX == fhdr->get_exec_format()->get_family()) {
895  /* FIXME: LX Entry tables have a different format than LE (they are similar to NE Entry Tables). See
896  * http://members.rediff.com/pguptaji/executable.htm (among others) for the format. We don't parse them
897  * at this time since it's not a Windows format and we leave the section size at zero to make this more
898  * obvious. */
899  return;
900  }
901 
902  rose_addr_t at = 0;
903  extend(1);
904  unsigned char byte;
905  read_content_local(at++, &byte, 1);
906  size_t nentries = byte;
907  for (size_t i = 0; i < nentries; i++) {
908  extend(1);
909  uint8_t flags;
910  read_content_local(at, &flags, 1);
911  if (flags & 0x01) {
914  read_content_local(at, &disk, sizeof disk);
915  p_entries.push_back(new SgAsmLEEntryPoint(fhdr->get_sex(), &disk));
916  } else {
917  p_entries.push_back(new SgAsmLEEntryPoint(fhdr->get_sex(), flags));
918  }
919  }
920 }
921 
922 /* Write entry table back to file */
923 void
924 SgAsmLEEntryTable::unparse(std::ostream &f) const
925 {
926  rose_addr_t spos=0; /*section offset*/
927  ROSE_ASSERT(p_entries.size()<=0xff);
928  uint8_t byte = p_entries.size();
929  spos = write(f, spos, byte);
930 
931  ByteOrder::Endianness sex = get_header()->get_sex();
932  for (size_t i = 0; i < p_entries.size(); i++) {
933  spos = p_entries[i]->unparse(f, sex, this, spos);
934  }
935 }
936 
937 /* Print some debugging info */
938 void
939 SgAsmLEEntryTable::dump(FILE *f, const char *prefix, ssize_t idx) const
940 {
941  char p[4096];
942  if (idx>=0) {
943  sprintf(p, "%s%sEntryTable[%zd].", prefix, get_header()->format_name(), idx);
944  } else {
945  sprintf(p, "%s%sEntryTable.", prefix, get_header()->format_name());
946  }
947 
948  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
949 
950  SgAsmGenericSection::dump(f, p, -1);
951  fprintf(f, "%s%-*s = %" PRIuPTR " entry points\n", p, w, "size", p_entries.size());
952  for (size_t i = 0; i < p_entries.size(); i++) {
953  p_entries[i]->dump(f, p, i);
954  }
955 }
956 
958 // LE/LX Relocation Table
960 
961 /* Constructor. */
962 void
963 SgAsmLERelocTable::ctor(rose_addr_t offset)
964 {
965  set_offset(offset);
966  set_size(0);
967  grab_content();
968 
969  SgAsmLEFileHeader *fhdr = dynamic_cast<SgAsmLEFileHeader*>(get_header());
970  ROSE_ASSERT(fhdr!=NULL);
971 
972  char name[64];
973  sprintf(name, "%s Relocation Table", fhdr->format_name());
974  set_synthesized(true);
975  set_name(new SgAsmBasicString(name));
977 
978  ROSE_ASSERT(0 == get_size());
979 
980 #if 0 /*FIXME: How do we know how many entries are in the relocation table? */
981  size_t nrelocs = 0;
982 
983  // DQ (12/8/2008): reloc_size was previously not initialized before use in the for loop.
984  rose_addr_t at = 0, reloc_size = 0;
985  for (size_t i = 0; i < nrelocs; i++, at+=reloc_size) {
986  p_entries.push_back(new SgAsmLERelocEntry(this, at, &reloc_size));
987  }
988 #endif
989 }
990 
991 #if 0 /*FIXME: not implemented yet*/
992 /* Write relocation table back to disk */
993 void
994 SgAsmLERelocTable::unparse(std::ostream &f)
995 {
996  ROSE_ASSERT(0==reallocate(false)); /*should have been called well before any unparsing started*/
997 }
998 #endif
999 
1000 /* Print some debugging info */
1001 void
1002 SgAsmLERelocTable::dump(FILE *f, const char *prefix, ssize_t idx) const
1003 {
1004  char p[4096];
1005  if (idx>=0) {
1006  sprintf(p, "%s%sRelocTable[%zd].", prefix, get_header()->format_name(), idx);
1007  } else {
1008  sprintf(p, "%s%sRelocTable.", prefix, get_header()->format_name());
1009  }
1010 
1011  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
1012 
1013  SgAsmGenericSection::dump(f, p, -1);
1014  fprintf(f, "%s%-*s = %" PRIuPTR " entries\n", p, w, "size", p_entries.size());
1015  for (size_t i = 0; i < p_entries.size(); i++) {
1016  p_entries[i]->dump(f, p, i);
1017  }
1018 }
1019 
1021 
1022 /* Parses the structure of an LE/LX file and adds the information to the SgAsmGenericFile. */
1024 SgAsmLEFileHeader::parse(SgAsmDOSFileHeader *dos_header)
1025 {
1026  ROSE_ASSERT(dos_header);
1027  SgAsmGenericFile *ef = dos_header->get_file();
1028  ROSE_ASSERT(ef);
1029 
1030  /* LE files extend the DOS header with some additional info */
1031  SgAsmDOSExtendedHeader *dos2_header = new SgAsmDOSExtendedHeader(dos_header);
1032  dos2_header->set_offset(dos_header->get_size());
1033  dos2_header->parse();
1034 
1035  /* The LE header */
1036  SgAsmLEFileHeader *le_header = new SgAsmLEFileHeader(ef, dos2_header->get_e_lfanew());
1037  le_header->set_dos2_header(dos2_header);
1038 
1039  /* Page Table */
1040  if (le_header->get_e_pagetab_rfo() > 0 && le_header->get_e_npages() > 0) {
1041  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_pagetab_rfo();
1042  rose_addr_t table_size = le_header->get_e_npages() * sizeof(SgAsmLEPageTableEntry::LEPageTableEntry_disk);
1043  SgAsmLEPageTable *table = new SgAsmLEPageTable(le_header, table_offset, table_size);
1044  le_header->set_page_table(table);
1045  }
1046 
1047  /* Section (Object) Table */
1048  if (le_header->get_e_secttab_rfo() > 0 && le_header->get_e_secttab_nentries() > 0) {
1049  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_secttab_rfo();
1050  rose_addr_t table_size = le_header->get_e_secttab_nentries() * sizeof(SgAsmLESectionTableEntry::LESectionTableEntry_disk);
1051  SgAsmLESectionTable *table = new SgAsmLESectionTable(le_header, table_offset, table_size);
1052  le_header->set_section_table(table);
1053  }
1054 
1055  /* Resource Table */
1056  if (le_header->get_e_rsrctab_rfo() > 0 && le_header->get_e_rsrctab_nentries() > 0) {
1057  /*FIXME*/
1058  }
1059 
1060  /* Resident Names Table */
1061  if (le_header->get_e_resnametab_rfo() > 0) {
1062  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_resnametab_rfo();
1063  SgAsmLENameTable *table = new SgAsmLENameTable(le_header, table_offset);
1064  char section_name[64];
1065  sprintf(section_name, "%s Resident Name Table", le_header->format_name());
1066  table->set_name(new SgAsmBasicString(section_name));
1067  le_header->set_resname_table(table);
1068  }
1069 
1070  /* Non-resident Names Table */
1071  if (le_header->get_e_nonresnametab_offset() > 0) {
1072  rose_addr_t table_offset = le_header->get_e_nonresnametab_offset();
1073  SgAsmLENameTable *table = new SgAsmLENameTable(le_header, table_offset);
1074  char section_name[64];
1075  sprintf(section_name, "%s Non-resident Name Table", le_header->format_name());
1076  table->set_name(new SgAsmBasicString(section_name));
1077  le_header->set_nonresname_table(table);
1078  }
1079 
1080  /* Entry Table */
1081  if (le_header->get_e_entrytab_rfo() > 0) {
1082  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_entrytab_rfo();
1083  SgAsmLEEntryTable *table = new SgAsmLEEntryTable(le_header, table_offset);
1084  le_header->set_entry_table(table);
1085  }
1086 
1087  /* Fixup (Relocation) Table */
1088  if (le_header->get_e_fixup_rectab_rfo() > 0) {
1089  rose_addr_t table_offset = le_header->get_offset() + le_header->get_e_fixup_rectab_rfo();
1090  SgAsmLERelocTable *table = new SgAsmLERelocTable(le_header, table_offset);
1091  le_header->set_reloc_table(table);
1092  }
1093 
1094 // /*
1095 // * The table locations are indicated in the header but sizes are not stored. Any table whose offset is zero or whose
1096 // * size, calculated from the location of the following table, is zero is not present. */
1097 // rose_addr_t end_rfo = le_header->get_size() + le_header->e_loader_sect_size;
1098 // if (le_header->e_ppcksumtab_rfo > 0 && le_header->e_ppcksumtab_rfo < end_rfo) {
1099 // /* Per-Page Checksum */
1100 // rose_addr_t table_offset = le_header->get_offset() + le_header->e_ppcksumtab_rfo;
1101 // rose_addr_t table_size = end_rfo - le_header->e_ppcksumtab_rfo;
1102 // SgAsmGenericSection *table = new SgAsmGenericSection(ef, table_offset, table_size);
1103 // table->set_synthesized(true);
1104 // char section_name[64];
1105 // sprintf(section_name, "%s Per-Page Checksum Table", le_header->format_name());
1106 // table->set_name(section_name);
1107 // table->set_purpose(SP_HEADER);
1108 // table->set_header(le_header);
1109 // end_rfo = le_header->e_ppcksumtab_rfo;
1110 // }
1111 // if (0) {
1112 // /* FIXME: "Resident Directives Data" goes here! */
1113 // }
1114 // if (le_header->e_fmtdirtab_rfo > 0 && le_header->e_fmtdirtab_rfo < end_rfo) {
1115 // /* Module Format Directives Table */
1116 // rose_addr_t table_offset = le_header->get_offset() + le_header->e_fmtdirtab_rfo;
1117 // rose_addr_t table_size = end_rfo - le_header->e_fmtdirtab_rfo;
1118 // SgAsmGenericSection *table = new SgAsmGenericSection(ef, table_offset, table_size);
1119 // table->set_synthesized(true);
1120 // char section_name[64];
1121 // sprintf(section_name, "%s Module Format Directives Table", le_header->format_name());
1122 // table->set_name(section_name);
1123 // table->set_purpose(SP_HEADER);
1124 // table->set_header(le_header);
1125 // end_rfo = le_header->e_fmtdirtab_rfo;
1126 // }
1127 
1128  return le_header;
1129 }
1130 
1131 // }; //namespace LE
1132 // }; //namespace Exec
1133 
1134 #endif
SgAsmGenericFile * get_file() const
Property: File to which this section belongs.
virtual void unparse(std::ostream &) const ROSE_OVERRIDE
Write a section back to the file.
Definition: ExecLE.C:761
16:16 alias required (80x86 specific)
String associated with a binary file.
size_t read_content(rose_addr_t offset, void *dst_buf, rose_addr_t size, bool strict=true)
Reads data from a file.
Contiguous region of a file.
rose_addr_t get_e_lfanew() const
Property: lfanew.
Microsft Linear Executable format.
void set_mapped_xperm(bool)
Property: Whether mapped with execute permission.
virtual void unparse(std::ostream &) const
Write a section back to the file.
Section is conforming for code (80x86 specific)
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:486
OS/2 LX (Windows 9x VxD device drivers, extension of LE).
Anything other than values below.
size_t read_content_local(rose_addr_t rel_offset, void *dst_buf, rose_addr_t size, bool strict=true)
Reads data from a file.
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:787
Section has zero-filled pages.
const SgCharList & get_magic() const
Property: Optional magic number in file byte order.
const SgAsmGenericSectionPtrList & get_sections() const
Property: List of section pointers.
void set_mapped_actual_va(rose_addr_t)
Property: Virtual address where ROSE maps this section.
rose_addr_t get_offset() const
Property: Offset to start of section in file.
virtual void set_mapped_preferred_rva(rose_addr_t)
Property: Relative virtual address where section prefers to be mapped.
Big/default bit setting (80x86 specific); see note above.
SgAsmGenericHeader * get_header() const
Property: File header that owns this section.
rose_addr_t write(std::ostream &f, rose_addr_t offset, size_t bufsize, const void *buf) const
Write data to a file section.
Architecture is something other than below.
void set_mapped_rperm(bool)
Property: Whether mapped with read permission.
virtual void unparse(std::ostream &) const ROSE_OVERRIDE
Write a section back to the file.
Definition: ExecLE.C:474
Section contains resource objects.
Section is resident and contiguous.
ExecFamily get_family() const
Property: Family.
Program-supplied data, code, etc.
Represents the file header for DOS executables.
Section I/O privilege level (80x86 specific; used only for 16:16 alias objects)
virtual void unparse(std::ostream &) const ROSE_OVERRIDE
Write a section back to the file.
Definition: ExecLE.C:676
virtual void set_offset(rose_addr_t)
Property: Offset to start of section in file.
Not specified in file and could not be inferred.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const
Print some debugging info.
virtual void unparse(std::ostream &) const ROSE_OVERRIDE
Write a section back to the file.
Definition: ExecLE.C:237
void set_synthesized(bool)
Property: Whether section really exists.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:577
Section is resident and "long-lockable" (VDDs and PDDs only)
risc-like pipelining, integrated FPU, on-chip cache
rose_addr_t get_size() const
Property: Size of section in file in bytes.
Write permission granted when mapped.
void grab_content()
Saves a reference to the original file data for a section based on the section's current offset and s...
void set_isa(SgAsmGenericFormat::InsSetArchitecture)
Property: Machine for which this header and its sections, etc.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:278
void set_mapped_wperm(bool)
Property: Whether mapped with write permission.
DOS exteded header.
virtual void set_size(rose_addr_t)
Property: Size of section in file in bytes.
Execute permission granted when mapped.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:702
void set_purpose(SectionPurpose)
Property: General contents of the section.
void set_id(int)
Property: Non-unique section ID or negative.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:1002
Section contains a header for the executable file format.
static bool is_LE(SgAsmGenericFile *)
Return true if the file looks like it might be an LE or LX file according to the magic number...
Definition: ExecLE.C:143
Read permission granted when mapped.
virtual void set_mapped_size(rose_addr_t)
Property: Mapped size.
virtual std::string get_string(bool escape=false) const
Property: String value.
SgAsmGenericString * get_name() const
Property: Non-unique name of section.
void extend(rose_addr_t nbytes)
Extend a section by some number of bytes during the construction and/or parsing phase.
Section is resident (valid for VDDs and PDDs only)
SgAsmGenericSectionList * get_sections() const
Property: List of file sections.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const ROSE_OVERRIDE
Print some debugging info.
Definition: ExecLE.C:939
int get_id() const
Property: Non-unique section ID or negative.
(code named N11) larger caches; 40-50MHz; same IS as XR
void set_name(SgAsmGenericString *s)
Property: Non-unique name of section.
SgAsmGenericFormat * get_exec_format() const
Property: General info about the executable format.
Base class for binary files.
virtual void unparse(std::ostream &) const ROSE_OVERRIDE
Write a section back to the file.
Definition: ExecLE.C:924