/** Returns the file offset associated with the virtual address of a mapped section. * * NOTE: The MemoryMap class is a better interface to this same information. [RPM 2009-09-09] */ rose_addr_t SgAsmGenericSection::get_va_offset(rose_addr_t va) const { ROSE_ASSERT(is_mapped()); ROSE_ASSERT(va >= get_base_va()); rose_addr_t rva = va - get_base_va(); ROSE_ASSERT(rva >= get_mapped_preferred_rva()); return get_offset() + (rva - get_mapped_preferred_rva()); }
/** Returns (non-relative) virtual address if mapped, zero otherwise. */ rose_addr_t SgAsmGenericSection::get_mapped_preferred_va() const { ROSE_ASSERT(this != NULL); if (is_mapped()) return get_base_va() + get_mapped_preferred_rva(); return 0; }
void * SgAsmPEFileHeader::encode(PE64OptHeader_disk *disk) const { host_to_le(p_e_opt_magic, &(disk->e_opt_magic)); host_to_le(p_e_lmajor, &(disk->e_lmajor)); host_to_le(p_e_lminor, &(disk->e_lminor)); host_to_le(p_e_code_size, &(disk->e_code_size)); host_to_le(p_e_data_size, &(disk->e_data_size)); host_to_le(p_e_bss_size, &(disk->e_bss_size)); host_to_le(get_entry_rva(), &(disk->e_entrypoint_rva)); host_to_le(p_e_code_rva, &(disk->e_code_rva)); // host_to_le(p_e_data_rva, &(disk->e_data_rva)); /* not present in PE32+ */ host_to_le(get_base_va(), &(disk->e_image_base)); host_to_le(p_e_section_align, &(disk->e_section_align)); host_to_le(p_e_file_align, &(disk->e_file_align)); host_to_le(p_e_os_major, &(disk->e_os_major)); host_to_le(p_e_os_minor, &(disk->e_os_minor)); host_to_le(p_e_user_major, &(disk->e_user_major)); host_to_le(p_e_user_minor, &(disk->e_user_minor)); host_to_le(p_e_subsys_major, &(disk->e_subsys_major)); host_to_le(p_e_subsys_minor, &(disk->e_subsys_minor)); host_to_le(p_e_reserved9, &(disk->e_reserved9)); host_to_le(p_e_image_size, &(disk->e_image_size)); host_to_le(p_e_header_size, &(disk->e_header_size)); host_to_le(p_e_file_checksum, &(disk->e_file_checksum)); host_to_le(p_e_subsystem, &(disk->e_subsystem)); host_to_le(p_e_dll_flags, &(disk->e_dll_flags)); host_to_le(p_e_stack_reserve_size, &(disk->e_stack_reserve_size)); host_to_le(p_e_stack_commit_size, &(disk->e_stack_commit_size)); host_to_le(p_e_heap_reserve_size, &(disk->e_heap_reserve_size)); host_to_le(p_e_heap_commit_size, &(disk->e_heap_commit_size)); host_to_le(p_e_loader_flags, &(disk->e_loader_flags)); host_to_le(p_e_num_rvasize_pairs, &(disk->e_num_rvasize_pairs)); return disk; }
/* Looks at the RVA/Size pairs in the PE header and creates an SgAsmGenericSection object for each one. This must be done * after we build the mapping from virtual addresses to file offsets. */ void SgAsmPEFileHeader::create_table_sections() { /* First, only create the sections. */ for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) { SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i]; if (0==pair->get_e_size()) continue; /* Table names come from PE file specification and are hard coded by RVA/Size pair index */ const char *tabname_short; std::string tabname = rvasize_pair_name((PairPurpose)i, &tabname_short); /* Find the starting offset in the file. * FIXME: We have a potential problem here in that ROSE sections are always contiguous in the file but a section created * from an RVA/Size pair is not necessarily contiguous in the file. Normally such sections are in fact * contiguous and we'll just ignore this for now. In any case, as long as these sections only ever read their * data via the same MemoryMap that we use here, everything should be fine. [RPM 2009-08-17] */ MemoryMap *map = get_loader_map(); ROSE_ASSERT(map!=NULL); const MemoryMap::MapElement *elmt = map->find(get_base_va() + pair->get_e_rva()); if (!elmt) { fprintf(stderr, "SgAsmPEFileHeader::create_table_sections: warning: pair-%zu, rva=0x%08"PRIx64", size=%"PRIu64 " bytes \"%s\": unable to find a mapping for the virtual address (skipping)\n", i, pair->get_e_rva().get_rva(), pair->get_e_size(), tabname.c_str()); continue; } rose_addr_t file_offset = elmt->is_anonymous() ? 0 : elmt->get_va_offset(get_base_va() + pair->get_e_rva(), 1); /* Create the new section */ SgAsmGenericSection *tabsec = NULL; switch (i) { case 0: { /* Sometimes export sections are represented by a ".edata" section, and sometimes they're represented by an * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the exports duplicated * in the AST, so we only create this table as exports if we haven't already seen some other export section. */ SgAsmGenericSectionPtrList §ions = get_sections()->get_sections(); bool seen_exports = false; for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_exports && si!=sections.end(); ++si) seen_exports = isSgAsmPEExportSection(*si); if (seen_exports) { tabsec = new SgAsmGenericSection(get_file(), this); } else { tabsec = new SgAsmPEExportSection(this); } break; } case 1: { /* Sometimes import sections are represented by a ".idata" section, and sometimes they're represented by an * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the imports duplicated * in the AST, so we only create this table as imports if we haven't already seen some other import section. */ SgAsmGenericSectionPtrList §ions = get_sections()->get_sections(); bool seen_imports = false; for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_imports && si!=sections.end(); ++si) seen_imports = isSgAsmPEImportSection(*si); if (seen_imports) { tabsec = new SgAsmGenericSection(get_file(), this); } else { tabsec = new SgAsmPEImportSection(this); } break; } default: { tabsec = new SgAsmGenericSection(get_file(), this); break; } } tabsec->set_name(new SgAsmBasicString(tabname)); tabsec->set_short_name(tabname_short); tabsec->set_synthesized(true); tabsec->set_purpose(SP_HEADER); tabsec->set_offset(file_offset); tabsec->set_size(pair->get_e_size()); tabsec->set_file_alignment(1); tabsec->set_mapped_alignment(1); tabsec->set_mapped_preferred_rva(pair->get_e_rva().get_rva()); tabsec->set_mapped_actual_va(pair->get_e_rva().get_rva()+get_base_va()); /*FIXME: not sure this is correct. [RPM 2009-09-11]*/ tabsec->set_mapped_size(pair->get_e_size()); tabsec->set_mapped_rperm(true); tabsec->set_mapped_wperm(false); tabsec->set_mapped_xperm(false); pair->set_section(tabsec); pair->set_e_rva(pair->get_e_rva().set_section(tabsec)); } /* Now parse the sections */ for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) { SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i]; SgAsmGenericSection *tabsec = pair->get_section(); if (tabsec) tabsec->parse(); } }
/** Returns the file offset associated with the relative virtual address of a mapped section. * * NOTE: The MemoryMap class is a better interface to this same information. [RPM 2009-09-09] */ rose_addr_t SgAsmGenericSection::get_rva_offset(rose_addr_t rva) const { return get_va_offset(rva + get_base_va()); }