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