/** Write ELF contents back to a file. */ void SgAsmElfFileHeader::unparse(std::ostream &f) const { /* Write unreferenced areas back to the file before anything else. */ unparse_holes(f); /* Write the ELF segment table and segments first since they generally overlap with more specific things which may have * been modified when walking the AST. (We generally don't modify segments, just the more specific sections.) */ if (p_segment_table) { ROSE_ASSERT(p_segment_table->get_header()==this); p_segment_table->unparse(f); } /* Write the ELF section table and, indirectly, the sections themselves. */ if (p_section_table) { ROSE_ASSERT(p_section_table->get_header()==this); p_section_table->unparse(f); } /* Encode and write the ELF file header */ Elf32FileHeader_disk disk32; Elf64FileHeader_disk disk64; void *disk = NULL; size_t struct_size = 0; if (4 == get_word_size()) { disk = encode(get_sex(), &disk32); struct_size = sizeof(disk32); } else if (8 == get_word_size()) { disk = encode(get_sex(), &disk64); struct_size = sizeof(disk64); } else { ROSE_ASSERT(!"unsupported word size"); } write(f, 0, struct_size, disk); }
/** Write the section table section back to disk */ void SgAsmElfSectionTable::unparse(std::ostream &f) const { SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header()); ROSE_ASSERT(fhdr!=NULL); ByteOrder sex = fhdr->get_sex(); SgAsmGenericSectionPtrList sections = fhdr->get_sectab_sections(); /* Write the sections first */ for (size_t i=0; i<sections.size(); i++) sections[i]->unparse(f); unparse_holes(f); /* Calculate sizes. The ELF File Header should have been updated in reallocate() prior to unparsing. */ size_t ent_size, struct_size, opt_size, nentries; calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries); ROSE_ASSERT(fhdr->get_shextrasz()==opt_size); ROSE_ASSERT(fhdr->get_e_shnum()==nentries); /* Write the section table entries */ for (size_t i=0; i<sections.size(); ++i) { SgAsmElfSection *section = dynamic_cast<SgAsmElfSection*>(sections[i]); ROSE_ASSERT(section!=NULL); SgAsmElfSectionTableEntry *shdr = section->get_section_entry(); ROSE_ASSERT(shdr!=NULL); ROSE_ASSERT(shdr->get_sh_offset()==section->get_offset());/*section table entry should have been updated in reallocate()*/ int id = section->get_id(); ROSE_ASSERT(id>=0 && (size_t)id<nentries); SgAsmElfSectionTableEntry::Elf32SectionTableEntry_disk disk32; SgAsmElfSectionTableEntry::Elf64SectionTableEntry_disk disk64; void *disk = NULL; if (4==fhdr->get_word_size()) { disk = shdr->encode(sex, &disk32); } else if (8==fhdr->get_word_size()) { disk = shdr->encode(sex, &disk64); } else { ROSE_ASSERT(!"invalid word size"); } /* The disk struct */ rose_addr_t spos = write(f, id*ent_size, struct_size, disk); if (shdr->get_extra().size() > 0) { ROSE_ASSERT(shdr->get_extra().size()<=opt_size); write(f, spos, shdr->get_extra()); } } }
/** Write symbol table sections back to disk */ void SgAsmElfSymbolSection::unparse(std::ostream &f) const { SgAsmElfFileHeader *fhdr = get_elf_header(); ROSE_ASSERT(fhdr); ByteOrder sex = fhdr->get_sex(); size_t entry_size, struct_size, extra_size, nentries; calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries); /* Adjust the entry size stored in the ELF Section Table */ get_section_entry()->set_sh_entsize(entry_size); /* Write each entry's required part followed by the optional part */ for (size_t i=0; i<nentries; i++) { SgAsmElfSymbol::Elf32SymbolEntry_disk disk32; SgAsmElfSymbol::Elf64SymbolEntry_disk disk64; void *disk=NULL; SgAsmElfSymbol *entry = p_symbols->get_symbols()[i]; if (4==fhdr->get_word_size()) { disk = entry->encode(sex, &disk32); } else if (8==fhdr->get_word_size()) { disk = entry->encode(sex, &disk64); } else { ROSE_ASSERT(!"unsupported word size"); } rose_addr_t spos = i * entry_size; spos = write(f, spos, struct_size, disk); if (entry->get_extra().size()>0) { ROSE_ASSERT(entry->get_extra().size()<=extra_size); write(f, spos, entry->get_extra()); } } unparse_holes(f); }
/* Write the PE file header back to disk and all that it references */ void SgAsmPEFileHeader::unparse(std::ostream &f) const { /* Write unreferenced areas back to the file before anything else. */ unparse_holes(f); /* Write sections in the order of specialization, from least specialized to most specialized. This gives more specialized * sections a chance to overwrite the less specialized sections. */ const SgAsmGenericSectionPtrList §ions = get_sections()->get_sections(); for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) { if (V_SgAsmGenericSection==(*si)->variantT()) (*si)->unparse(f); } for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) { if (V_SgAsmPESection==(*si)->variantT()) (*si)->unparse(f); } for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) { if (V_SgAsmGenericSection!=(*si)->variantT() && V_SgAsmPESection!=(*si)->variantT()) (*si)->unparse(f); } /* Encode the "NT Optional Header" before the COFF Header since the latter depends on the former. Adjust the COFF Header's * e_nt_hdr_size to accommodate the NT Optional Header in such a way that EXEs from tinype.com don't change (i.e., don't * increase e_nt_hdr_size if the bytes beyond it are zero anyway, and if they aren't then adjust it as little as possible. * The RVA/Size pairs are considered to be part of the NT Optional Header. */ size_t oh_size = p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk); size_t rvasize_offset; /*offset with respect to "oh" buffer allocated below*/ if (4==get_word_size()) { oh_size += sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { oh_size += sizeof(PE64OptHeader_disk); } else { throw FormatError("unsupported PE word size"); } unsigned char *oh = new unsigned char[oh_size]; if (4==get_word_size()) { encode((PE32OptHeader_disk*)oh); rvasize_offset = sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { encode((PE64OptHeader_disk*)oh); rvasize_offset = sizeof(PE64OptHeader_disk); } else { throw FormatError("unsupported PE word size"); } for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++, rvasize_offset+=sizeof(SgAsmPERVASizePair::RVASizePair_disk)) { SgAsmPERVASizePair::RVASizePair_disk *rvasize_disk = (SgAsmPERVASizePair::RVASizePair_disk*)(oh+rvasize_offset); p_rvasize_pairs->get_pairs()[i]->encode(rvasize_disk); } while (oh_size>p_e_nt_hdr_size) { if (0!=oh[oh_size-1]) break; --oh_size; } ROSE_ASSERT(p_e_nt_hdr_size==oh_size); /*set in reallocate()*/ /* Write the fixed-length COFF Header */ PEFileHeader_disk fh; encode(&fh); rose_addr_t spos = write(f, 0, sizeof fh, &fh); /* Write the following "NT Optional Header" */ spos = write(f, spos, oh_size, oh); }
/* Unparse an ElfStringSection by unparsing the ElfStrtab */ void SgAsmPEStringSection::unparse(std::ostream &f) const { get_strtab()->unparse(f); unparse_holes(f); }