ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PeSectionTable.C
Go to the documentation of this file.
1 /* Windows PE Section Tables (SgAsmPESectionTable and related classes) */
2 #include "sage3basic.h"
3 #include "BinaryLoader.h"
4 #include "MemoryMap.h"
5 
6 void
8 {
9  char name[9];
10  strncpy(name, disk->name, 8);
11  name[8] = '\0';
12  this->set_name( name );
13 
14  /* Decode file format */
23 }
24 
26 void
28 {
29  SgAsmPEFileHeader *fhdr = SageInterface::getEnclosingNode<SgAsmPEFileHeader>(section);
30  ROSE_ASSERT(fhdr!=NULL);
31 
32  p_virtual_size = section->get_mapped_size();
33  p_rva = section->get_mapped_preferred_rva();
34  p_physical_size = section->get_size();
35  p_physical_offset = section->get_offset();
36  p_name = section->get_name()->get_string();
37 
38  /* Mapping permissions */
39  if (section->get_mapped_rperm()) {
41  } else {
43  }
44  if (section->get_mapped_wperm()) {
46  } else {
48  }
49  if (section->get_mapped_xperm()) {
51  } else {
53  }
54 
55  /* Mapping alignment */
56  if (section->is_mapped() && section->get_mapped_alignment()!=fhdr->get_e_section_align()) {
57  switch (section->get_mapped_alignment()) {
58  case 0:
59  case 1:
62  break;
63  case 2:
66  break;
67  case 4:
70  break;
71  case 8:
74  break;
75  case 16:
78  break;
79  case 32:
82  break;
83  case 64:
86  break;
87  case 128:
90  break;
91  case 256:
94  break;
95  case 512:
98  break;
99  case 1024:
102  break;
103  case 2048:
106  break;
107  case 4096:
110  break;
111  case 8192:
114  break;
115  default:
116  break; /* leave as is */
117  }
118  }
119 
120 #if 0 /*FIXME*/
121  p_coff_line_nums = 0;
122  p_n_relocs = 0;
123  p_n_coff_line_nums = 0;
124 #endif
125 }
126 
127 /* Encodes a section table entry back into disk format. */
128 void *
130 {
131  /* The file can hold up to eight characters of the name. The name is NUL-padded, not necessarily NUL-terminated. */
132  if (p_name.size()>8) {
133  fprintf(stderr, "warning: section name too long to store in PE file: \"%s\" (truncated)\n",
134  escapeString(p_name).c_str());
135  }
136  memset(disk->name, 0, sizeof(disk->name));
137 
138 #ifdef USE_ROSE
139  // DQ (1/27/2010): std::min() does not appear to be handle different type of arguments for ROSE. Need to look into this later.
140  // memcpy(disk->name, p_name.c_str(), std::min(sizeof(disk->name), (size_t)p_name.size()));
141  memcpy(disk->name, p_name.c_str(), std::min( (size_t)(sizeof(disk->name)), (size_t)(p_name.size()) ));
142 #else
143  memcpy(disk->name, p_name.c_str(), std::min(sizeof(disk->name), p_name.size()));
144 #endif
145 
147  ByteOrder::host_to_le(p_rva, &(disk->rva));
154 
155  return disk;
156 }
157 
158 /* Prints some debugging info */
159 void
160 SgAsmPESectionTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
161 {
162  char p[4096];
163  if (idx>=0) {
164  sprintf(p, "%sPESectionTableEntry[%zd].", prefix, idx);
165  } else {
166  sprintf(p, "%sPESectionTableEntry.", prefix);
167  }
168 
169  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
170 
171  fprintf(f, "%s%-*s = %" PRIu64 " bytes\n", p, w, "virtual_size", p_virtual_size);
172  fprintf(f, "%s%-*s = 0x%08" PRIx64 "\n", p, w, "rva", p_rva);
173  fprintf(f, "%s%-*s = %" PRIu64 " bytes\n", p, w, "physical_size", p_physical_size);
174  fprintf(f, "%s%-*s = %" PRIu64 " file byte offset\n", p, w, "physical_offset", p_physical_offset);
175  fprintf(f, "%s%-*s = %u byte offset\n", p, w, "coff_line_nums", p_coff_line_nums);
176  fprintf(f, "%s%-*s = %u\n", p, w, "n_relocs", p_n_relocs);
177  fprintf(f, "%s%-*s = %u\n", p, w, "n_coff_line_nums", p_n_coff_line_nums);
178  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "flags", p_flags);
179 }
180 
181 /* Constructor */
182 void
184 {
185  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
186  ROSE_ASSERT(fhdr!=NULL);
187  fhdr->set_section_table(this);
188 
189  set_synthesized(true);
190  set_name(new SgAsmBasicString("PE Section Table"));
192 }
193 
194 /* Parser */
197 {
199 
200  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
201  ROSE_ASSERT(fhdr!=NULL);
202 
203  /* Parse section table and construct section objects, but do not parse the sections yet. */
205  const size_t entsize = sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk);
206  for (size_t i=0; i<fhdr->get_e_nsections(); i++) {
208  if (entsize!=read_content_local(i * entsize, &disk, entsize, false))
209  fprintf(stderr, "SgAsmPESectionTable::parse: warning: section table entry %zu at file offset 0x%08"PRIx64
210  " extends beyond end of defined section table.\n",
211  i, get_offset()+i*entsize);
213 
214  SgAsmPESection *section = NULL;
215  if (entry->get_name() == ".idata") {
216  section = new SgAsmPEImportSection(fhdr);
217  } else {
218  section = new SgAsmPESection(fhdr);
219  }
220  section->init_from_section_table(entry, i+1);
221  pending.push_back(section);
222  }
223 
224  /* Build the memory mapping like the real loader would do. This is the same code used by
225  * SgAsmExecutableFileFormat::parseBinaryFormat() except we're doing it here early because we need it in the rest of the
226  * PE parser. */
227  ROSE_ASSERT(NULL==fhdr->get_loader_map());
228  BinaryLoader *loader = BinaryLoader::lookup(fhdr); /*no need to clone; we're not changing any settings*/
229  ROSE_ASSERT(loader!=NULL);
230  MemoryMap *loader_map = new MemoryMap;
231  loader->remap(loader_map, fhdr);
232  fhdr->set_loader_map(loader_map);
233 
234  /* Parse each section after the loader map is created */
235  for (size_t i=0; i<pending.size(); i++)
236  pending[i]->parse();
237 
238  return this;
239 }
240 
244 void
246 {
247  ROSE_ASSERT(section!=NULL);
248  ROSE_ASSERT(section->get_file()==get_file());
249  ROSE_ASSERT(section->get_header()==get_header());
250  ROSE_ASSERT(section->get_section_entry()==NULL); /* must not be in the section table yet */
251 
252  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
253  ROSE_ASSERT(fhdr!=NULL);
254 
255  /* Assign an ID if there isn't one yet. */
256  if (section->get_id()<0) {
257  SgAsmGenericSectionList *seclist = fhdr->get_sections();;
258  int max_id=0; /*assume zero is used so we start at one*/
259  for (size_t i=0; i<seclist->get_sections().size(); i++) {
260  SgAsmGenericSection *s = seclist->get_sections()[i];
261 
262  max_id = std::max(max_id, s->get_id());
263 
264  }
265  section->set_id(max_id+1);
266  }
267 
268  /* Create a new section table entry. */
270  entry->update_from_section(section);
271  section->set_section_entry(entry);
272 }
273 
274 /* Pre-unparsing updates */
275 bool
277 {
278  bool reallocated = false;
279 
280  /* Resize based on section having largest ID */
281  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
282  ROSE_ASSERT(fhdr != NULL);
284  int max_id = 0;
285  for (size_t i=0; i<sections.size(); i++) {
286 
287  max_id = std::max(max_id, sections[i]->get_id());
288 
289  }
290 
291  size_t nsections = max_id; /*PE section IDs are 1-origin*/
292  size_t need = nsections * sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk);
293  if (need < get_size()) {
294  if (is_mapped()) {
295  ROSE_ASSERT(get_mapped_size()==get_size());
296  set_mapped_size(need);
297  }
298  set_size(need);
299  reallocated = true;
300  } else if (need > get_size()) {
302  reallocated = true;
303  }
304 
305  return reallocated;
306 }
307 
308 /* Writes the section table back to disk. */
309 void
310 SgAsmPESectionTable::unparse(std::ostream &f) const
311 {
312  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
313  ROSE_ASSERT(fhdr != NULL);
315 
316  for (size_t i = 0; i < sections.size(); i++) {
317  if (sections[i]->get_id()>=0) {
318  SgAsmPESection *section = isSgAsmPESection(sections[i]);
319  ROSE_ASSERT(section!=NULL);
320 
321  /* Write the table entry */
322  ROSE_ASSERT(section->get_id() > 0); /*ID's are 1-origin in PE*/
323  size_t slot = section->get_id() - 1;
324  SgAsmPESectionTableEntry *shdr = section->get_section_entry();
326  shdr->encode(&disk);
327  write(f, slot*sizeof(disk), sizeof disk, &disk);
328  }
329  }
330 }
331 
332 /* Prints some debugging info */
333 void
334 SgAsmPESectionTable::dump(FILE *f, const char *prefix, ssize_t idx) const
335 {
336  char p[4096];
337  if (idx>=0) {
338  sprintf(p, "%sPESectionTable[%zd].", prefix, idx);
339  } else {
340  sprintf(p, "%sPESectionTable.", prefix);
341  }
342 
343  SgAsmGenericSection::dump(f, p, -1);
344 
345  if (variantT() == V_SgAsmPESectionTable) //unless a base class
346  hexdump(f, 0, std::string(p)+"data at ", p_data);
347 }