/** Pre-unparsing updates */ bool SgAsmElfSegmentTable::reallocate() { bool reallocated = false; /* Resize based on word size from ELF File Header */ size_t opt_size, nentries; rose_addr_t need = calculate_sizes(NULL, NULL, &opt_size, &nentries); if (need < get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need > get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } /* Update data members in the ELF File Header. No need to return true for these changes. */ SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header()); fhdr->set_phextrasz(opt_size); fhdr->set_e_phnum(nentries); return reallocated; }
/* Pre-unparsing updates */ bool SgAsmPESectionTable::reallocate() { bool reallocated = false; /* Resize based on section having largest ID */ SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header()); ROSE_ASSERT(fhdr != NULL); SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections(); int max_id = 0; for (size_t i=0; i<sections.size(); i++) { max_id = std::max(max_id, sections[i]->get_id()); } size_t nsections = max_id; /*PE section IDs are 1-origin*/ size_t need = nsections * sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk); if (need < get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need > get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } return reallocated; }
/** Pre-unparsing adjustments */ bool SgAsmElfNoteSection::reallocate() { bool reallocated = SgAsmElfSection::reallocate(); /* How much space is needed by the notes? */ rose_addr_t need = 0; for (size_t i=0; i<p_entries->get_entries().size(); i++) { SgAsmElfNoteEntry *ent = p_entries->get_entries()[i]; need += ent->calculate_size(); } /* Adjust the section/segment size */ if (need < get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need > get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } return reallocated; }
bool SgAsmElfSection::reallocate() { bool reallocated = false; SgAsmElfSectionTableEntry *sechdr = get_section_entry(); SgAsmElfSegmentTableEntry *seghdr = get_segment_entry(); /* Change section size if this section was defined in the ELF Section Table */ if (sechdr!=NULL) { rose_addr_t need = calculate_sizes(NULL, NULL, NULL, NULL); if (need < get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need > get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } } /* Update entry in the ELF Section Table and/or ELF Segment Table */ if (sechdr) sechdr->update_from_section(this); if (seghdr) seghdr->update_from_section(this); return reallocated; }
/** Causes section to not be mapped to memory. */ void SgAsmGenericSection::clear_mapped() { set_mapped_size(0); set_mapped_preferred_rva(0); set_mapped_actual_va(0); set_mapped_rperm(false); set_mapped_wperm(false); set_mapped_xperm(false); }
SgAsmElfSection * SgAsmElfSection::init_from_segment_table(SgAsmElfSegmentTableEntry *shdr, bool mmap_only) { if (!mmap_only) { /* Purpose */ set_purpose(SP_HEADER); /* File mapping */ set_offset(shdr->get_offset()); set_size(shdr->get_filesz()); set_file_alignment(shdr->get_align()); grab_content(); /* Name */ char name[128]; switch (shdr->get_type()) { case SgAsmElfSegmentTableEntry::PT_LOAD: strcpy(name, "LOAD"); break; case SgAsmElfSegmentTableEntry::PT_DYNAMIC: strcpy(name, "DYNAMIC"); break; case SgAsmElfSegmentTableEntry::PT_INTERP: strcpy(name, "INTERP"); break; case SgAsmElfSegmentTableEntry::PT_NOTE: strcpy(name, "NOTE"); break; case SgAsmElfSegmentTableEntry::PT_SHLIB: strcpy(name, "SHLIB"); break; case SgAsmElfSegmentTableEntry::PT_PHDR: strcpy(name, "PHDR"); break; case SgAsmElfSegmentTableEntry::PT_TLS: strcpy(name, "TLS"); break; case SgAsmElfSegmentTableEntry::PT_GNU_EH_FRAME: strcpy(name, "EH_FRAME"); break; case SgAsmElfSegmentTableEntry::PT_GNU_STACK: strcpy(name, "GNU_STACK"); break; case SgAsmElfSegmentTableEntry::PT_GNU_RELRO: strcpy(name, "GNU_RELRO"); break; case SgAsmElfSegmentTableEntry::PT_PAX_FLAGS: strcpy(name, "PAX_FLAGS"); break; case SgAsmElfSegmentTableEntry::PT_SUNWBSS: strcpy(name, "SUNWBSS"); break; case SgAsmElfSegmentTableEntry::PT_SUNWSTACK: strcpy(name, "SUNWSTACK"); break; default: sprintf(name, "PT_0x%08x", shdr->get_type()); break; } sprintf(name+strlen(name), "#%" PRIuPTR "", shdr->get_index()); set_name(new SgAsmBasicString(name)); } /* Memory mapping */ set_mapped_preferred_rva(shdr->get_vaddr()); set_mapped_actual_va(0); /*will be assigned by Loader*/ set_mapped_size(shdr->get_memsz()); set_mapped_alignment(shdr->get_align()); set_mapped_rperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_RPERM ? true : false); set_mapped_wperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_WPERM ? true : false); set_mapped_xperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_XPERM ? true : false); /* Add segment table entry to section */ set_segment_entry(shdr); shdr->set_parent(this); return this; }
/* Change size of PE header based on word size */ bool SgAsmPEFileHeader::reallocate() { bool reallocated = SgAsmGenericHeader::reallocate(); /* Resize if necessary */ rose_addr_t need = sizeof(PEFileHeader_disk); if (4==get_word_size()) { need += sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { need += sizeof(PE64OptHeader_disk); } else { throw FormatError("unsupported PE word size"); } need += p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk); if (need<get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need>get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } /* Make sure the RVA/Size pairs at the end of the header are consistent with the sections to which they point. Reallocate() * has already been called recursively for the sections. */ update_rvasize_pairs(); /* Make sure header is consistent with sections. Reallocate() has already been called recursively for the sections. * Count the number of sections in the table and update the header's e_nsections member. */ if (p_section_table) { ROSE_ASSERT(p_section_table->get_header()==this); SgAsmGenericSectionList *all = get_sections(); p_e_nsections = 0; for (size_t i=0; i<all->get_sections().size(); i++) { SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]); if (pesec && pesec->get_section_entry()!=NULL) p_e_nsections++; } rose_addr_t header_size = ALIGN_UP(p_section_table->get_offset() + p_section_table->get_size(), p_e_file_align>0 ? p_e_file_align : 1); #if 1 /* The PE Specification regarding e_header_size (known as "SizeOfHeader" on page 14 of "Microsoft Portable Executable * and Common Object File Format Specification: Revision 8.1 February 15, 2008" is not always followed. We recompute * it here as being the minimum RVA from all the sections defined in the PE Section Table, but not smaller * than the value according to the specification. This alternate value is kept if it's already in the parse tree, * otherwise we use the correct value. (RPM 2008-10-21) */ rose_addr_t min_offset = 0; for (size_t i=0, nfound=0; i<all->get_sections().size(); i++) { SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]); if (pesec && pesec->get_section_entry()!=NULL) { if (0==nfound++) { min_offset = pesec->get_offset(); } else { min_offset = std::min(min_offset, pesec->get_offset() ); } } } rose_addr_t header_size2 = std::max(header_size, min_offset); if (p_e_header_size==header_size2) header_size = header_size2; /* If the original header size was zero then don't change that--leave it at zero. Some tiny executables have a zero * value here and as a result, since this is near the end of the NT Optional Header, they can truncate the file and * the loader will fill the optional header with zeros when reading. (RPM 2008-11-11) */ if (p_e_header_size==0) header_size = 0; #endif p_e_header_size = header_size; } /* The size of the optional header. If there's a section table then we use its offset to calculate the optional header * size in order to be compatible with the PE loader. Otherwise use the actual optional header size. */ if (p_section_table) { ROSE_ASSERT(p_section_table->get_offset() >= get_offset() + sizeof(PEFileHeader_disk)); p_e_nt_hdr_size = p_section_table->get_offset() - (get_offset() + sizeof(PEFileHeader_disk)); } else if (4==get_word_size()) { p_e_nt_hdr_size = sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { p_e_nt_hdr_size = sizeof(PE64OptHeader_disk); } else { throw FormatError("invalid PE word size"); } /* Update COFF symbol table related data members in the file header */ if (get_coff_symtab()) { ROSE_ASSERT(get_coff_symtab()->get_header()==this); set_e_coff_symtab(get_coff_symtab()->get_offset()); set_e_coff_nsyms(get_coff_symtab()->get_nslots()); } /* Update some additional header fields */ set_e_num_rvasize_pairs(get_rvasize_pairs()->get_pairs().size()); set_e_opt_magic(4==get_word_size() ? 0x010b : 0x020b); set_e_lmajor((get_exec_format()->get_version() >> 16) & 0xffff); set_e_lminor(get_exec_format()->get_version() & 0xffff); /* 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 { delete[] oh; throw FormatError("unsupported PE word size"); } while (oh_size>p_e_nt_hdr_size) { if (0!=oh[oh_size-1]) break; --oh_size; } set_e_nt_hdr_size(oh_size); return reallocated; }
/** Initialize the header with information parsed from the file and construct and parse everything that's reachable from the * header. The PE File Header should have been constructed such that SgAsmPEFileHeader::ctor() was called. */ SgAsmPEFileHeader* SgAsmPEFileHeader::parse() { SgAsmGenericHeader::parse(); /* Read header, zero padding if the file isn't large enough */ PEFileHeader_disk fh; if (sizeof(fh)>get_size()) extend(sizeof(fh)-get_size()); if (sizeof(fh)!=read_content_local(0, &fh, sizeof fh, false)) fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE header at byte 0x%08"PRIx64"\n", get_offset()); /* Check magic number before getting too far */ if (fh.e_magic[0]!='P' || fh.e_magic[1]!='E' || fh.e_magic[2]!='\0' || fh.e_magic[3]!='\0') throw FormatError("Bad PE magic number"); /* Decode COFF file header */ p_e_cpu_type = le_to_host(fh.e_cpu_type); p_e_nsections = le_to_host(fh.e_nsections); p_e_time = le_to_host(fh.e_time); p_e_coff_symtab = le_to_host(fh.e_coff_symtab); p_e_coff_nsyms = le_to_host(fh.e_coff_nsyms); p_e_nt_hdr_size = le_to_host(fh.e_nt_hdr_size); p_e_flags = le_to_host(fh.e_flags); /* Read the "Optional Header" (optional in the sense that not all files have one, but required for an executable), the * size of which is stored in the e_nt_hdr_size of the main PE file header. According to * http://www.phreedom.org/solar/code/tinype the Windows loader honors the e_nt_hdr_size even when set to smaller than the * smallest possible documented size of the optional header. Also it's possible for the optional header to extend beyond * the end of the file, in which case that part should be read as zero. */ PE32OptHeader_disk oh32; rose_addr_t need32 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh32)); if (need32>get_size()) extend(need32-get_size()); if (sizeof(oh32)!=read_content_local(sizeof fh, &oh32, sizeof oh32, false)) fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n", get_offset() + sizeof(fh)); p_e_opt_magic = le_to_host(oh32.e_opt_magic); /* File format changes from ctor() */ p_exec_format->set_purpose(p_e_flags & HF_PROGRAM ? PURPOSE_EXECUTABLE : PURPOSE_LIBRARY); p_exec_format->set_word_size(0x010b==p_e_opt_magic? 4 : 8); /* Decode the optional header. */ rose_addr_t entry_rva; if (4==p_exec_format->get_word_size()) { p_e_lmajor = le_to_host(oh32.e_lmajor); p_e_lminor = le_to_host(oh32.e_lminor); p_e_code_size = le_to_host(oh32.e_code_size); p_e_data_size = le_to_host(oh32.e_data_size); p_e_bss_size = le_to_host(oh32.e_bss_size); entry_rva = le_to_host(oh32.e_entrypoint_rva); p_e_code_rva = le_to_host(oh32.e_code_rva); p_e_data_rva = le_to_host(oh32.e_data_rva); p_base_va = le_to_host(oh32.e_image_base); p_e_section_align = le_to_host(oh32.e_section_align); p_e_file_align = le_to_host(oh32.e_file_align); p_e_os_major = le_to_host(oh32.e_os_major); p_e_os_minor = le_to_host(oh32.e_os_minor); p_e_user_major = le_to_host(oh32.e_user_major); p_e_user_minor = le_to_host(oh32.e_user_minor); p_e_subsys_major = le_to_host(oh32.e_subsys_major); p_e_subsys_minor = le_to_host(oh32.e_subsys_minor); p_e_reserved9 = le_to_host(oh32.e_reserved9); p_e_image_size = le_to_host(oh32.e_image_size); p_e_header_size = le_to_host(oh32.e_header_size); p_e_file_checksum = le_to_host(oh32.e_file_checksum); p_e_subsystem = le_to_host(oh32.e_subsystem); p_e_dll_flags = le_to_host(oh32.e_dll_flags); p_e_stack_reserve_size = le_to_host(oh32.e_stack_reserve_size); p_e_stack_commit_size = le_to_host(oh32.e_stack_commit_size); p_e_heap_reserve_size = le_to_host(oh32.e_heap_reserve_size); p_e_heap_commit_size = le_to_host(oh32.e_heap_commit_size); p_e_loader_flags = le_to_host(oh32.e_loader_flags); p_e_num_rvasize_pairs = le_to_host(oh32.e_num_rvasize_pairs); } else if (8==p_exec_format->get_word_size()) { /* We guessed wrong. This is a 64-bit header, not 32-bit. */ PE64OptHeader_disk oh64; rose_addr_t need64 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh64)); if (need64>get_size()) extend(need64-get_size()); if (sizeof(oh64)!=read_content_local(sizeof fh, &oh64, sizeof oh64)) fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n", get_offset() + sizeof(fh)); p_e_lmajor = le_to_host(oh64.e_lmajor); p_e_lminor = le_to_host(oh64.e_lminor); p_e_code_size = le_to_host(oh64.e_code_size); p_e_data_size = le_to_host(oh64.e_data_size); p_e_bss_size = le_to_host(oh64.e_bss_size); entry_rva = le_to_host(oh64.e_entrypoint_rva); p_e_code_rva = le_to_host(oh64.e_code_rva); // p_e_data_rva = le_to_host(oh.e_data_rva); /* not in PE32+ */ p_base_va = le_to_host(oh64.e_image_base); p_e_section_align = le_to_host(oh64.e_section_align); p_e_file_align = le_to_host(oh64.e_file_align); p_e_os_major = le_to_host(oh64.e_os_major); p_e_os_minor = le_to_host(oh64.e_os_minor); p_e_user_major = le_to_host(oh64.e_user_major); p_e_user_minor = le_to_host(oh64.e_user_minor); p_e_subsys_major = le_to_host(oh64.e_subsys_major); p_e_subsys_minor = le_to_host(oh64.e_subsys_minor); p_e_reserved9 = le_to_host(oh64.e_reserved9); p_e_image_size = le_to_host(oh64.e_image_size); p_e_header_size = le_to_host(oh64.e_header_size); p_e_file_checksum = le_to_host(oh64.e_file_checksum); p_e_subsystem = le_to_host(oh64.e_subsystem); p_e_dll_flags = le_to_host(oh64.e_dll_flags); p_e_stack_reserve_size = le_to_host(oh64.e_stack_reserve_size); p_e_stack_commit_size = le_to_host(oh64.e_stack_commit_size); p_e_heap_reserve_size = le_to_host(oh64.e_heap_reserve_size); p_e_heap_commit_size = le_to_host(oh64.e_heap_commit_size); p_e_loader_flags = le_to_host(oh64.e_loader_flags); p_e_num_rvasize_pairs = le_to_host(oh64.e_num_rvasize_pairs); } else { throw FormatError("unrecognized Windows PE optional header magic number"); } /* Magic number */ p_magic.clear(); for (size_t i = 0; i < sizeof(fh.e_magic); ++i) p_magic.push_back(fh.e_magic[i]); /* File format */ ROSE_ASSERT(p_e_lmajor <= 0xffff && p_e_lminor <= 0xffff); p_exec_format->set_version((p_e_lmajor << 16) | p_e_lminor); p_exec_format->set_is_current_version(true); /*FIXME*/ /* Target architecture */ switch (p_e_cpu_type) { case 0x0000: set_isa(ISA_UNSPECIFIED); break; case 0x014c: set_isa(ISA_IA32_386); break; case 0x014d: set_isa(ISA_IA32_486); break; case 0x014e: set_isa(ISA_IA32_Pentium); break; case 0x0162: set_isa(ISA_MIPS_MarkI); /* R2000, R3000 */ break; case 0x0163: set_isa(ISA_MIPS_MarkII); /* R6000 */ break; case 0x0166: set_isa(ISA_MIPS_MarkIII); /* R4000 */ break; case 0x01a2: /*Hitachi SH3*/ case 0x01a3: /*Hitachi SH3 with FPU*/ case 0x01a6: /*Hitachi SH4*/ case 0x01a8: /*Hitachi SH5*/ set_isa(ISA_Hitachi_SH); break; case 0x01c0: set_isa(ISA_ARM_Family); break; case 0x01d3: set_isa(ISA_Matsushita_AM33); break; case 0x01f0: /*w/o FPU*/ case 0x01f1: /*with FPU*/ set_isa(ISA_PowerPC); break; case 0x0200: set_isa(ISA_IA64_Family); break; case 0x0266: set_isa(ISA_MIPS_16); break; case 0x0366: set_isa(ISA_MIPS_FPU); break; case 0x0466: set_isa(ISA_MIPS_16FPU); break; case 0x0ebc: set_isa(ISA_EFI_ByteCode); break; case 0x8664: set_isa(ISA_X8664_Family); break; case 0x9041: set_isa(ISA_Mitsubishi_M32R); break; default: fprintf(stderr, "SgAsmPEFileHeader::parse: warning: unrecognized e_cputype = 0x%x (%u)\n", p_e_cpu_type, p_e_cpu_type); set_isa(ISA_OTHER); break; } /* The NT loader normally maps this file header at the header's base virtual address. */ set_mapped_preferred_rva(0); set_mapped_actual_va(0); /* will be assigned by BinaryLoader */ set_mapped_size(p_e_header_size); set_mapped_alignment(0); set_mapped_rperm(true); set_mapped_wperm(false); set_mapped_xperm(false); /* Entry point. We will eventually bind the entry point to a particular section (in SgAsmPEFileHeader::parse) so that if * sections are rearranged, extended, etc. the entry point will be updated automatically. */ add_entry_rva(entry_rva); /* The PE File Header has a fixed-size component followed by some number of RVA/Size pairs. The add_rvasize_pairs() will * extend the header and parse the RVA/Size pairs. */ if (get_e_num_rvasize_pairs() > 1000) { fprintf(stderr, "warning: PE File Header contains an unreasonable number of Rva/Size pairs. Limiting to 1000.\n"); set_e_num_rvasize_pairs(1000); } add_rvasize_pairs(); /* Construct the section table and its sections (non-synthesized sections). The specification says that the section table * comes after the optional (NT) header, which in turn comes after the fixed part of the PE header. The size of the * optional header is indicated in the fixed header. */ rose_addr_t secttab_offset = get_offset() + sizeof(PEFileHeader_disk) + get_e_nt_hdr_size(); rose_addr_t secttab_size = get_e_nsections() * sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk); SgAsmPESectionTable *secttab = new SgAsmPESectionTable(this); secttab->set_offset(secttab_offset); secttab->set_size(secttab_size); secttab->parse(); set_section_table(secttab); /* Parse the COFF symbol table */ if (get_e_coff_symtab() && get_e_coff_nsyms()) { SgAsmCoffSymbolTable *symtab = new SgAsmCoffSymbolTable(this); symtab->set_offset(get_e_coff_symtab()); symtab->parse(); set_coff_symtab(symtab); } /* Associate RVAs with particular sections so that if a section's mapping is changed the RVA gets adjusted automatically. */ ROSE_ASSERT(get_entry_rvas().size()==1); get_entry_rvas()[0].bind(this); set_e_code_rva(get_e_code_rva().bind(this)); set_e_data_rva(get_e_data_rva().bind(this)); /* Turn header-specified tables (RVA/Size pairs) into generic sections */ create_table_sections(); return this; }
/** Update prior to unparsing */ bool SgAsmElfFileHeader::reallocate() { /* Reallocate superclass. This also calls reallocate() for all the sections associated with this ELF File Header. */ bool reallocated = SgAsmGenericHeader::reallocate(); /* Resize header based on current word size */ rose_addr_t need; if (4==get_word_size()) { need = sizeof(Elf32FileHeader_disk); } else if (8==get_word_size()) { need = sizeof(Elf64FileHeader_disk); } else { throw FormatError("unsupported ELF word size"); } if (need < get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need > get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } /* Update ELF-specific file class data member from generic data. */ switch(get_word_size()) { case 4: p_e_ident_file_class = 1; break; case 8: p_e_ident_file_class = 2; break; default: ROSE_ASSERT(!"invalid word size"); break; } /* Byte order. According to the spec, valid values are 1 (little-endian) and 2 (big-endian). However, we've seen cases * where a value of zero is used to indicate "native" order (loader assumes words are in the order of the machine on which * the loader is running, and the ROSE ELF parser determines the order by looking at other fields in the header). Any * original value other than 1 or 2 will be written to the new output; otherwise we choose 1 or 2 based on the currently * defined byte order. */ if (p_e_ident_data_encoding==1 || p_e_ident_data_encoding==2) { p_e_ident_data_encoding = ByteOrder::ORDER_LSB==get_sex() ? 1 : 2; } /* Update ELF-specific file type from generic data. */ switch (p_exec_format->get_purpose()) { case PURPOSE_UNSPECIFIED: case PURPOSE_PROC_SPECIFIC: case PURPOSE_OS_SPECIFIC: case PURPOSE_OTHER: /* keep as is */ break; case PURPOSE_LIBRARY: if (p_e_type==1 || p_e_type==3) { /* keep as is */ } else { p_e_type = 1; } break; case PURPOSE_EXECUTABLE: p_e_type = 2; break; case PURPOSE_CORE_DUMP: p_e_type = 4; } /* Update ELF machine type. */ p_e_machine = isa_to_machine(get_isa()); /* The ELF header stores its own size */ p_e_ehsize = get_size(); return reallocated; }
SgAsmElfSection * SgAsmElfSection::init_from_section_table(SgAsmElfSectionTableEntry *shdr, SgAsmElfStringSection *strsec, int id) { ROSE_ASSERT(shdr); ROSE_ASSERT(strsec); ROSE_ASSERT(id>=0); /* Purpose */ switch (shdr->get_sh_type()) { case SgAsmElfSectionTableEntry::SHT_PROGBITS: set_purpose(SP_PROGRAM); break; case SgAsmElfSectionTableEntry::SHT_STRTAB: set_purpose(SP_HEADER); break; case SgAsmElfSectionTableEntry::SHT_DYNSYM: case SgAsmElfSectionTableEntry::SHT_SYMTAB: set_purpose(SP_SYMTAB); break; default: set_purpose(SP_OTHER); break; } /* File mapping */ set_offset(shdr->get_sh_offset()); if (SgAsmElfSectionTableEntry::SHT_NULL==shdr->get_sh_type() || SgAsmElfSectionTableEntry::SHT_NOBITS==shdr->get_sh_type()) { set_size(0); } else { set_size(shdr->get_sh_size()); } set_file_alignment(shdr->get_sh_addralign()); grab_content(); /* Memory mapping */ if (shdr->get_sh_addr() > 0) { set_mapped_preferred_rva(shdr->get_sh_addr()); set_mapped_actual_va(0); /*will be assigned by Loader*/ set_mapped_size(shdr->get_sh_size()); set_mapped_rperm(true); set_mapped_wperm((shdr->get_sh_flags() & 0x01) == 0x01); set_mapped_xperm((shdr->get_sh_flags() & 0x04) == 0x04); set_mapped_alignment(shdr->get_sh_addralign()); } else { set_mapped_preferred_rva(0); set_mapped_actual_va(0); /*will be assigned by Loader*/ set_mapped_size(0); set_mapped_rperm(false); set_mapped_wperm(false); set_mapped_xperm(false); set_mapped_alignment(shdr->get_sh_addralign()); } /* Name. This has to be near the end because possibly strsec==this, in which case we have to call set_size() to extend the * section to be large enough before we can try to look up the name. */ set_id(id); set_name(new SgAsmStoredString(strsec->get_strtab(), shdr->get_sh_name())); /* Add section table entry to section */ set_section_entry(shdr); shdr->set_parent(this); return this; }