ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElfSectionTable.C
Go to the documentation of this file.
1 /* ELF Section Tables (SgAsmElfSectionTable and related classes) */
2 #include "sage3basic.h"
3 #include "stringify.h"
4 
5 using namespace rose;
6 
8 void
10 {
11  p_sh_name = ByteOrder::disk_to_host(sex, disk->sh_name);
12  p_sh_type = (SectionType)ByteOrder::disk_to_host(sex, disk->sh_type);
13  p_sh_flags = ByteOrder::disk_to_host(sex, disk->sh_flags);
14  p_sh_addr = ByteOrder::disk_to_host(sex, disk->sh_addr);
15  p_sh_offset = ByteOrder::disk_to_host(sex, disk->sh_offset);
16  p_sh_size = ByteOrder::disk_to_host(sex, disk->sh_size);
17  p_sh_link = ByteOrder::disk_to_host(sex, disk->sh_link);
18  p_sh_info = ByteOrder::disk_to_host(sex, disk->sh_info);
19  p_sh_addralign = ByteOrder::disk_to_host(sex, disk->sh_addralign);
20  p_sh_entsize = ByteOrder::disk_to_host(sex, disk->sh_entsize);
21 }
22 
24 void
26 {
27  p_sh_name = ByteOrder::disk_to_host(sex, disk->sh_name);
28  p_sh_type = (SectionType)ByteOrder::disk_to_host(sex, disk->sh_type);
29  p_sh_flags = ByteOrder::disk_to_host(sex, disk->sh_flags);
30  p_sh_addr = ByteOrder::disk_to_host(sex, disk->sh_addr);
31  p_sh_offset = ByteOrder::disk_to_host(sex, disk->sh_offset);
32  p_sh_size = ByteOrder::disk_to_host(sex, disk->sh_size);
33  p_sh_link = ByteOrder::disk_to_host(sex, disk->sh_link);
34  p_sh_info = ByteOrder::disk_to_host(sex, disk->sh_info);
35  p_sh_addralign = ByteOrder::disk_to_host(sex, disk->sh_addralign);
36  p_sh_entsize = ByteOrder::disk_to_host(sex, disk->sh_entsize);
37 }
38 
40 void *
42 {
43  ByteOrder::host_to_disk(sex, p_sh_name, &(disk->sh_name));
44  ByteOrder::host_to_disk(sex, p_sh_type, &(disk->sh_type));
45  ByteOrder::host_to_disk(sex, p_sh_flags, &(disk->sh_flags));
46  ByteOrder::host_to_disk(sex, p_sh_addr, &(disk->sh_addr));
47  ByteOrder::host_to_disk(sex, p_sh_offset, &(disk->sh_offset));
48  ByteOrder::host_to_disk(sex, p_sh_size, &(disk->sh_size));
49  ByteOrder::host_to_disk(sex, p_sh_link, &(disk->sh_link));
50  ByteOrder::host_to_disk(sex, p_sh_info, &(disk->sh_info));
51  ByteOrder::host_to_disk(sex, p_sh_addralign, &(disk->sh_addralign));
52  ByteOrder::host_to_disk(sex, p_sh_entsize, &(disk->sh_entsize));
53 
54  return disk;
55 }
56 void *
58 {
59  ByteOrder::host_to_disk(sex, p_sh_name, &(disk->sh_name));
60  ByteOrder::host_to_disk(sex, p_sh_type, &(disk->sh_type));
61  ByteOrder::host_to_disk(sex, p_sh_flags, &(disk->sh_flags));
62  ByteOrder::host_to_disk(sex, p_sh_addr, &(disk->sh_addr));
63  ByteOrder::host_to_disk(sex, p_sh_offset, &(disk->sh_offset));
64  ByteOrder::host_to_disk(sex, p_sh_size, &(disk->sh_size));
65  ByteOrder::host_to_disk(sex, p_sh_link, &(disk->sh_link));
66  ByteOrder::host_to_disk(sex, p_sh_info, &(disk->sh_info));
67  ByteOrder::host_to_disk(sex, p_sh_addralign, &(disk->sh_addralign));
68  ByteOrder::host_to_disk(sex, p_sh_entsize, &(disk->sh_entsize));
69 
70  return disk;
71 }
72 
74 void
76 {
77  /* There can be only one ELF Section Table */
78  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
79  ROSE_ASSERT(fhdr);
80  ROSE_ASSERT(fhdr->get_section_table()==NULL);
81 
82  set_synthesized(true); /* the section table isn't really a section itself */
83  set_name(new SgAsmBasicString("ELF Section Table"));
84  set_purpose(SP_HEADER);
85 
86  /* Every section table has a first entry that's all zeros. We don't declare that section here (see parse()) but we do set
87  * the section count in the header in order to reserve that first slot. */
88  if (fhdr->get_e_shnum()<1)
89  fhdr->set_e_shnum(1);
90 
91  fhdr->set_section_table(this);
92 }
93 
98 {
100 
101  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
102  ROSE_ASSERT(fhdr!=NULL);
103  ByteOrder::Endianness sex = fhdr->get_sex();
104 
105  size_t ent_size, struct_size, opt_size, nentries;
106  calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries);
107  ROSE_ASSERT(opt_size==fhdr->get_shextrasz() && nentries==fhdr->get_e_shnum());
108 
109  /* If the current size is very small (0 or 1 byte) then we're coming straight from the constructor and the parsing should
110  * also extend this section to hold all the entries. Otherwise the caller must have assigned a specific size for a good
111  * reason and we should leave that alone, reading zeros if the entries extend beyond the defined size. */
112  if (get_size()<=1 && get_size()<nentries*ent_size)
113  extend(nentries*ent_size - get_size());
114 
115  /* Read all the section headers. */
116  std::vector<SgAsmElfSectionTableEntry*> entries;
117  rose_addr_t offset = 0;
118  for (size_t i=0; i<nentries; i++, offset+=ent_size) {
119  SgAsmElfSectionTableEntry *shdr = NULL;
120  if (4 == fhdr->get_word_size()) {
122  read_content_local(offset, &disk, struct_size);
123  shdr = new SgAsmElfSectionTableEntry(sex, &disk);
124  } else {
126  read_content_local(offset, &disk, struct_size);
127  shdr = new SgAsmElfSectionTableEntry(sex, &disk);
128  }
129  if (opt_size>0)
130  shdr->get_extra() = read_content_local_ucl(offset+struct_size, opt_size);
131  entries.push_back(shdr);
132  }
133 
134  /* This vector keeps track of which sections have already been parsed. We could get the same information by calling
135  * fhdr->get_section_by_id() and passing the entry number since entry numbers and IDs are one and the same in ELF. However,
136  * this is a bit easier. */
137  std::vector<SgAsmElfSection*> is_parsed;
138  is_parsed.resize(entries.size(), NULL);
139 
140  /* All sections implicitly depend on the section string table for their names. */
141  SgAsmElfStringSection *section_name_strings=NULL;
142  if (fhdr->get_e_shstrndx() > 0) {
143  SgAsmElfSectionTableEntry *entry = entries[fhdr->get_e_shstrndx()];
144  section_name_strings = new SgAsmElfStringSection(fhdr);
145  section_name_strings->init_from_section_table(entry, section_name_strings, fhdr->get_e_shstrndx());
146  section_name_strings->parse();
147  is_parsed[fhdr->get_e_shstrndx()] = section_name_strings;
148  }
149 
150  /* Read all the sections. Some sections depend on other sections, so we read them in such an order that all dependencies
151  * are satisfied first. */
152  while (1) {
153  bool try_again=false;
154  for (size_t i=0; i<entries.size(); i++) {
155  SgAsmElfSectionTableEntry *entry = entries[i];
156  ROSE_ASSERT(entry->get_sh_link()<entries.size());
157 
158  /* Some sections might reference another section through the sh_link member. */
159  bool need_linked = entry->get_sh_link() > 0;
160  ROSE_ASSERT(!need_linked || entry->get_sh_link()<entries.size());
161  SgAsmElfSection *linked = need_linked ? is_parsed[entry->get_sh_link()] : NULL;
162 
163  /* Relocation sections might have a second linked section stored in sh_info. */
164  bool need_info_linked = (entry->get_sh_type() == SgAsmElfSectionTableEntry::SHT_REL ||
166  entry->get_sh_info() > 0;
167  ROSE_ASSERT(!need_info_linked || entry->get_sh_info()<entries.size());
168  SgAsmElfSection *info_linked = need_info_linked ? is_parsed[entry->get_sh_info()] : NULL;
169 
170  if (is_parsed[i]) {
171  /* This section has already been parsed. */
172  } else if ((need_linked && !linked) || (need_info_linked && !info_linked)) {
173  /* Don't parse this section yet because it depends on something that's not parsed yet. */
174  try_again = true;
175  } else {
176  switch (entry->get_sh_type()) {
178  /* Null entry. We still create the section just to hold the section header. */
179  is_parsed[i] = new SgAsmElfSection(fhdr);
180  break;
182  /* These types of sections don't occupy any file space (e.g., BSS) */
183  is_parsed[i] = new SgAsmElfSection(fhdr);
184  break;
186  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
187  ROSE_ASSERT(strsec);
188  is_parsed[i] = new SgAsmElfDynamicSection(fhdr, strsec);
189  break;
190  }
192  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
193  ROSE_ASSERT(strsec);
194  SgAsmElfSymbolSection *symsec = new SgAsmElfSymbolSection(fhdr, strsec);
195  symsec->set_is_dynamic(true);
196  is_parsed[i] = symsec;
197  break;
198  }
200  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
201  ROSE_ASSERT(strsec);
202  SgAsmElfSymbolSection *symsec = new SgAsmElfSymbolSection(fhdr, strsec);
203  symsec->set_is_dynamic(false);
204  is_parsed[i] = symsec;
205  break;
206  }
208  is_parsed[i] = new SgAsmElfStringSection(fhdr);
209  break;
211  SgAsmElfSymbolSection *symbols = dynamic_cast<SgAsmElfSymbolSection*>(linked);
212  SgAsmElfRelocSection *relocsec = new SgAsmElfRelocSection(fhdr, symbols, info_linked);
213  relocsec->set_uses_addend(false);
214  is_parsed[i] = relocsec;
215  break;
216  }
218  SgAsmElfSymbolSection *symbols = dynamic_cast<SgAsmElfSymbolSection*>(linked);
219  SgAsmElfRelocSection *relocsec = new SgAsmElfRelocSection(fhdr, symbols, info_linked);
220  relocsec->set_uses_addend(true);
221  is_parsed[i] = relocsec;
222  break;
223  }
225  if (!section_name_strings) {
226  fprintf(stderr, "SgAsmElfSectionTable::parse(): no string table for section table\n");
227  is_parsed[i] = new SgAsmElfSection(fhdr);
228  } else {
229  std::string section_name = section_name_strings->read_content_local_str(entry->get_sh_name());
230  if (section_name == ".eh_frame") {
231  is_parsed[i] = new SgAsmElfEHFrameSection(fhdr);
232  } else {
233  is_parsed[i] = new SgAsmElfSection(fhdr);
234  }
235  }
236  break;
237  }
239  is_parsed[i] = new SgAsmElfSymverSection(fhdr);
240  break;
241  }
243  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
244  ROSE_ASSERT(strsec);
245  is_parsed[i] = new SgAsmElfSymverDefinedSection(fhdr,strsec);
246  break;
247  }
249  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
250  ROSE_ASSERT(strsec);
251  is_parsed[i] = new SgAsmElfSymverNeededSection(fhdr,strsec);
252  break;
253  }
254  default:
255  is_parsed[i] = new SgAsmElfSection(fhdr);
256  break;
257  }
258  is_parsed[i]->init_from_section_table(entry, section_name_strings, i);
259  is_parsed[i]->parse();
260  }
261  }
262  if (!try_again)
263  break;
264  }
265 
266  /* Initialize links between sections */
267  for (size_t i = 0; i < entries.size(); i++) {
268  SgAsmElfSectionTableEntry *shdr = entries[i];
269  if (shdr->get_sh_link() > 0) {
272  assert(source); /* because we created it above */
273  source->set_linked_section(target);
274  }
275  }
276 
277  /* Finish parsing sections now that we have basic info for all the sections. */
278  for (size_t i=0; i<is_parsed.size(); i++)
279  is_parsed[i]->finish_parsing();
280 
281  return this;
282 }
283 
294 {
295  ROSE_ASSERT(section!=NULL);
296  ROSE_ASSERT(section->get_file()==get_file());
297  ROSE_ASSERT(section->get_header()==get_header());
298  ROSE_ASSERT(section->get_section_entry()==NULL); /* must not be in the section table yet */
299 
300  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
301  ROSE_ASSERT(fhdr!=NULL);
302 
303  /* Assign an ID if there isn't one yet */
304  if (section->get_id()<0) {
305  int id = fhdr->get_e_shnum();
306  fhdr->set_e_shnum(id+1);
307  section->set_id(id);
308  }
309 
310  /* If the supplied section is a string table and the ELF Section Table doesn't have a string table associated with it yet,
311  * then use the supplied section as the string table to hold the names of the sections. When this happens, all sections
312  * that are already defined in the ELF Section Table should have their names moved into the new string table. */
313  SgAsmElfStringSection *strsec = NULL;
314  if (fhdr->get_e_shstrndx()==0) {
315  strsec = dynamic_cast<SgAsmElfStringSection*>(section);
316  if (strsec) {
317  fhdr->set_e_shstrndx(section->get_id());
318  SgAsmGenericSectionList *all = fhdr->get_sections();
319  for (size_t i=0; i<all->get_sections().size(); i++) {
320  SgAsmElfSection *s = dynamic_cast<SgAsmElfSection*>(all->get_sections()[i]);
321  if (s && s->get_id()>=0 && s->get_section_entry()!=NULL) {
322  s->allocate_name_to_storage(strsec);
323  }
324  }
325  }
326  } else {
327  strsec = dynamic_cast<SgAsmElfStringSection*>(fhdr->get_section_by_id(fhdr->get_e_shstrndx()));
328  ROSE_ASSERT(strsec!=NULL);
329  }
330 
331  /* Make sure the name is in the correct string table */
332  if (strsec)
333  section->allocate_name_to_storage(strsec);
334 
335  /* Create a new section table entry. */
337  shdr->update_from_section(section);
338  section->set_section_entry(shdr);
339 
340  return shdr;
341 }
342 
344 void
346 {
347  if (get_name()) {
348  SgAsmStoredString *old_stored = dynamic_cast<SgAsmStoredString*>(get_name());
349  if (!old_stored || old_stored->get_strtab()!=strsec->get_strtab()) {
350  /* Reallocate string to new string table */
351  SgAsmStoredString *new_stored = new SgAsmStoredString(strsec->get_strtab(), 0);
352  new_stored->set_string(get_name()->get_string());
353  get_name()->set_string(""); /*free old string*/
354  set_name(new_stored);
355  }
356  }
357 }
358 
362 SgAsmElfSectionTable::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
363 {
364  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
365  ROSE_ASSERT(fhdr!=NULL);
366 
367  size_t struct_size = 0;
368  size_t extra_size = fhdr->get_shextrasz();
369  size_t entry_size = 0;
370  size_t nentries = 0;
371 
372  /* Size of required part of each entry */
373  if (4==fhdr->get_word_size()) {
375  } else if (8==fhdr->get_word_size()) {
377  } else {
378  throw FormatError("bad ELF word size");
379  }
380 
381  /* Entire entry should be at least large enough for the required part. */
382  entry_size = struct_size;
383 
384  /* Size of optional parts. If we've parsed the table then use the largest optional part, otherwise assume the entry from
385  * the ELF File Header is correct. */
387  for (size_t i=0; i<sections.size(); i++) {
388  SgAsmElfSection *elfsec = dynamic_cast<SgAsmElfSection*>(sections[i]);
389  if (elfsec && elfsec->get_section_entry()) {
390  ROSE_ASSERT(elfsec->get_id()>=0);
391  nentries = std::max(nentries, (size_t)elfsec->get_id()+1);
392  extra_size = std::max(extra_size, elfsec->get_section_entry()->get_extra().size());
393  }
394  }
395 
396  /* Total number of entries. Either we haven't parsed the section table yet (nor created the sections it defines) or we
397  * have. In the former case we use the setting from the ELF File Header. Otherwise the table has to be large enough to
398  * store the section with the largest ID (ID also serves as the index into the ELF Section Table). */
399  if (0==nentries)
400  nentries = fhdr->get_e_shnum();
401 
402  /* Return values */
403  if (entsize)
404  *entsize = entry_size;
405  if (required)
406  *required = struct_size;
407  if (optional)
408  *optional = extra_size;
409  if (entcount)
410  *entcount = nentries;
411  return entry_size * nentries;
412 }
413 
415 void
417 {
419  p_sh_name = 0; /*not a stored string after all*/
420  } else {
421  p_sh_name = section->get_name()->get_offset();
422  }
423 
424  set_sh_offset(section->get_offset());
425  if (get_sh_type()==SHT_NOBITS && section->is_mapped()) {
426  set_sh_size(section->get_mapped_size());
427  } else {
428  set_sh_size(section->get_size());
429  }
430 
431  if (section->is_mapped()) {
432  set_sh_addr(section->get_mapped_preferred_rva());
433  set_sh_addralign(section->get_mapped_alignment());
434  if (section->get_mapped_wperm()) {
435  p_sh_flags |= SHF_WRITE;
436  } else {
437  p_sh_flags &= ~SHF_WRITE;
438  }
439  if (section->get_mapped_xperm()) {
440  p_sh_flags |= SHF_EXECINSTR;
441  } else {
442  p_sh_flags &= ~SHF_EXECINSTR;
443  }
444  } else {
445  set_sh_addr(0);
446  p_sh_flags &= ~(SHF_WRITE | SHF_EXECINSTR); /*clear write & execute bits*/
447  }
448 
449  SgAsmElfSection *linked_to = section->get_linked_section();
450  if (linked_to) {
451  ROSE_ASSERT(linked_to->get_id()>0);
452  set_sh_link(linked_to->get_id());
453  } else {
454  set_sh_link(0);
455  }
456 }
457 
459 std::string
461 {
462 #ifndef _MSC_VER
463  std::string retval = stringifySgAsmElfSectionTableEntrySectionType(t);
464 #else
465  ROSE_ASSERT(false);
466  std::string retval = "";
467 #endif
468  if ('('!=retval[0])
469  return retval;
470 
471  char buf[128];
472  if(t>=SHT_LOOS && t <= SHT_HIOS) {
473  snprintf(buf,sizeof(buf),"os-specific (%zu)",size_t(t)) ;
474  return buf;
475  }
476  if (t>=SHT_LOPROC && t<=SHT_HIPROC) {
477  snprintf(buf,sizeof(buf),"processor-specific (%zu)",size_t(t)) ;
478  return buf;
479  }
480  if (t>=SHT_LOUSER && t<=SHT_HIUSER) {
481  snprintf(buf,sizeof(buf),"application-specific (%zu)",size_t(t)) ;
482  return buf;
483  }
484  snprintf(buf,sizeof(buf),"unknown section type (%zu)",size_t(t)) ;
485  return buf;
486 }
487 
488 std::string
490 {
491  std::string str;
492  static const uint32_t kBaseMask=0x3ff;
493  for( size_t i=0; (1u <<i) <= SHF_TLS; ++i){
494  if( i!= 0)
495  str += ' ';
496  if(val & (1 << i)){
497  switch(1 << i){
498  case SHF_NULL: str += "NULL";break;
499  case SHF_WRITE: str += "WRITE";break;
500  case SHF_ALLOC: str += "ALLOC";break;
501  case SHF_EXECINSTR: str += "CODE";break;
502  case SHF_MERGE: str += "MERGE";break;
503  case SHF_STRINGS: str += "STRINGS";break;
504  case SHF_INFO_LINK: str += "INFO_LINK";break;
505  case SHF_LINK_ORDER:str += "LINK_ORDER";break;
506  case SHF_OS_NONCONFORMING:str += "OS SPECIAL";break;
507  case SHF_GROUP: str += "GROUP";break;
508  case SHF_TLS: str += "TLS";break;
509  };
510  }
511  }
512  uint32_t os = (val & ~(uint32_t)(SHF_MASKOS));
513  uint32_t proc = (val & ~(uint32_t)(SHF_MASKPROC));
514  uint32_t rest = (val & ~(uint32_t)(kBaseMask | SHF_MASKOS | SHF_MASKPROC));
515 
516  if(os){
517  char buf[64];
518  snprintf(buf,sizeof(buf),"os flags(%2x)", os >> 20);
519  str += buf;
520  }
521 
522  if(proc){
523  char buf[64];
524  snprintf(buf,sizeof(buf),"proc flags(%1x)", proc >> 28);
525  str += buf;
526  }
527 
528  if(rest){
529  char buf[64];
530  snprintf(buf,sizeof(buf),"unknown(%x)", rest);
531  str += buf;
532  }
533 
534  return str;
535 }
536 
538 void
539 SgAsmElfSectionTableEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
540 {
541  char p[4096];
542  if (idx>=0) {
543  sprintf(p, "%sElfSectionTableEntry[%zd].", prefix, idx);
544  } else {
545  sprintf(p, "%sElfSectionTableEntry.", prefix);
546  }
547  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
548 
549  fprintf(f, "%s%-*s = %u bytes into strtab\n", p, w, "sh_name", p_sh_name);
550  fprintf(f, "%s%-*s = 0x%x (%d) %s\n", p, w, "sh_type",
551  p_sh_type, p_sh_type, to_string(p_sh_type).c_str());
552  fprintf(f, "%s%-*s = %lu\n", p, w, "sh_link", p_sh_link);
553  fprintf(f, "%s%-*s = %lu\n", p, w, "sh_info", p_sh_info);
554  fprintf(f, "%s%-*s = 0x%08"PRIx64"\n", p, w, "sh_flags", p_sh_flags);
555  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64")\n", p, w, "sh_addr", p_sh_addr, p_sh_addr);
556  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64") bytes into file\n", p, w, "sh_offset", p_sh_offset, p_sh_offset);
557  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64") bytes\n", p, w, "sh_size", p_sh_size, p_sh_size);
558  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64") bytes\n", p, w, "sh_addralign", p_sh_addralign, p_sh_addralign);
559  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64") bytes\n", p, w, "sh_entsize", p_sh_entsize, p_sh_entsize);
560  if (p_extra.size()>0) {
561  fprintf(f, "%s%-*s = %zu bytes\n", p, w, "extra", p_extra.size());
562  hexdump(f, 0, std::string(p)+"extra at ", p_extra);
563  }
564 }
565 
566 
568 bool
570 {
571  bool reallocated = false;
572 
573  /* Resize based on word size from ELF File Header */
574  size_t opt_size, nentries;
575  rose_addr_t need = calculate_sizes(NULL, NULL, &opt_size, &nentries);
576  if (need < get_size()) {
577  if (is_mapped()) {
578  ROSE_ASSERT(get_mapped_size()==get_size());
579  set_mapped_size(need);
580  }
581  set_size(need);
582  reallocated = true;
583 
584  } else if (need > get_size()) {
585  get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE);
586  reallocated = true;
587  }
588 
589  /* Update data members in the ELF File Header. No need to return true for these changes. */
590  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
591  fhdr->set_shextrasz(opt_size);
592  fhdr->set_e_shnum(nentries);
593 
594  return reallocated;
595 }
596 
598 void
599 SgAsmElfSectionTable::unparse(std::ostream &f) const
600 {
601  SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
602  ROSE_ASSERT(fhdr!=NULL);
603  ByteOrder::Endianness sex = fhdr->get_sex();
605 
606  /* Write the sections first */
607  for (size_t i=0; i<sections.size(); i++)
608  sections[i]->unparse(f);
609  unparse_holes(f);
610 
611  /* Calculate sizes. The ELF File Header should have been updated in reallocate() prior to unparsing. */
612  size_t ent_size, struct_size, opt_size, nentries;
613  calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries);
614  ROSE_ASSERT(fhdr->get_shextrasz()==opt_size);
615  ROSE_ASSERT(fhdr->get_e_shnum()==nentries);
616 
617  /* Write the section table entries */
618  for (size_t i=0; i<sections.size(); ++i) {
619  SgAsmElfSection *section = dynamic_cast<SgAsmElfSection*>(sections[i]);
620  ROSE_ASSERT(section!=NULL);
621  SgAsmElfSectionTableEntry *shdr = section->get_section_entry();
622  ROSE_ASSERT(shdr!=NULL);
623  ROSE_ASSERT(shdr->get_sh_offset()==section->get_offset());/*section table entry should have been updated in reallocate()*/
624 
625  int id = section->get_id();
626  ROSE_ASSERT(id>=0 && (size_t)id<nentries);
627 
630  void *disk = NULL;
631 
632  if (4==fhdr->get_word_size()) {
633  disk = shdr->encode(sex, &disk32);
634  } else if (8==fhdr->get_word_size()) {
635  disk = shdr->encode(sex, &disk64);
636  } else {
637  ROSE_ASSERT(!"invalid word size");
638  }
639 
640  /* The disk struct */
641  rose_addr_t spos = write(f, id*ent_size, struct_size, disk);
642  if (shdr->get_extra().size() > 0) {
643  ROSE_ASSERT(shdr->get_extra().size()<=opt_size);
644  write(f, spos, shdr->get_extra());
645  }
646  }
647 }
648 
650 void
651 SgAsmElfSectionTable::dump(FILE *f, const char *prefix, ssize_t idx) const
652 {
653  char p[4096];
654  if (idx>=0) {
655  sprintf(p, "%sSectionTable[%zd].", prefix, idx);
656  } else {
657  sprintf(p, "%sSectionTable.", prefix);
658  }
659 
660  SgAsmGenericSection::dump(f, p, -1);
661 
662  if (variantT() == V_SgAsmElfSectionTable) //unless a base class
663  hexdump(f, 0, std::string(p)+"data at ", p_data);
664 }
665