SgAsmGenericSection * SgAsmGenericFile::get_section_by_id(int id, size_t *nfound/*optional*/) const { SgAsmGenericSectionPtrList possible = get_sections_by_id(id); if (nfound) *nfound = possible.size(); return possible.size()==1 ? possible[0] : NULL; }
/* 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; }
SgAsmGenericSection * SgAsmGenericFile::get_section_by_name(const std::string &name, char sep/*or NUL*/, size_t *nfound/*optional*/) const { SgAsmGenericSectionPtrList possible = get_sections_by_name(name, sep); if (nfound) *nfound = possible.size(); return possible.size()==1 ? possible[0] : NULL; }
/** Returns the section having a preferred or actual mapping that includes the specified virtual address. If @p use_preferred * is set, then the condition is evaluated by looking at the section's preferred mapping, otherwise the actual mapping is * used. If an actual mapping is used, the specified virtual address must be part of the actual mapped section, not merely in * the memory region that was also mapped to satisfy alignment constraints. If there are no sections or multiple sections * satisfying this condition then a null pointer is returned. */ SgAsmGenericSection * SgAsmGenericHeader::get_section_by_va(rose_addr_t va, bool use_preferred, size_t *nfound/*optional*/) const { SgAsmGenericSectionPtrList possible = get_sections_by_va(va, use_preferred); if (nfound) *nfound = possible.size(); return possible.size()==1 ? possible[0] : NULL; }
SgAsmGenericSection * SgAsmGenericFile::get_section_by_offset(rose_addr_t offset, rose_addr_t size, size_t *nfound) const { SgAsmGenericSectionPtrList possible = get_sections_by_offset(offset, size); if (nfound) *nfound = possible.size(); return possible.size()==1 ? possible[0] : NULL; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections_by_va(rose_addr_t va) const { SgAsmGenericSectionPtrList retval; /* Holes (probably not mapped anyway) */ for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) { rose_addr_t rva = va; /* Holes don't belong to any header and therefore have a zero base_va */ if ((*i)->is_mapped() && rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size()) retval.push_back(*i); } /* Headers and their sections */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { /* Headers probably aren't mapped, but just in case... */ rose_addr_t rva = va; /* Headers don't belong to any header and therefore have a zero base_va */ if ((*i)->is_mapped() && rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size()) retval.push_back(*i); /* Header sections */ const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_va(va, true); retval.insert(retval.end(), recurse.begin(), recurse.end()); } return retval; }
SgAsmGenericSection * SgAsmGenericFile::get_section_by_va(rose_addr_t va, size_t *nfound/*optional*/) const { SgAsmGenericSectionPtrList possible = get_sections_by_va(va); if (nfound) *nfound = possible.size(); return possible.size()==1 ? possible[0] : NULL; }
void BinaryLoader::addSectionsForRemap(SgAsmGenericHeader* header, SgAsmGenericSectionPtrList &allSections) { allSections.insert(allSections.end(), header->get_sections()->get_sections().begin(), header->get_sections()->get_sections().end()); }
rose_addr_t SgAsmGenericFile::get_current_size() const { rose_addr_t retval=0; SgAsmGenericSectionPtrList sections = get_sections(); for (SgAsmGenericSectionPtrList::iterator i=sections.begin(); i!=sections.end(); ++i) { retval = std::max(retval, (*i)->get_end_offset()); } return retval; }
/** Returns sections in this header that have the specified ID. */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_sections_by_id(int id) const { SgAsmGenericSectionPtrList retval; for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) { if ((*i)->get_id() == id) { retval.push_back(*i); } } return retval; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_mapped_sections() const { SgAsmGenericSectionPtrList retval; SgAsmGenericSectionPtrList all = get_sections(true); for (size_t i=0; i<all.size(); i++) { if (all[i]->is_mapped()) retval.push_back(all[i]); } return retval; }
/** Returns the list of sections that are memory mapped */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_mapped_sections() const { SgAsmGenericSectionPtrList retval; for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) { if ((*i)->is_mapped()) { retval.push_back(*i); } } return retval; }
/** Get the list of sections defined in the ELF Segment Table */ SgAsmGenericSectionPtrList SgAsmElfFileHeader::get_segtab_sections() { SgAsmGenericSectionPtrList retval; SgAsmGenericSectionPtrList sections = get_sections()->get_sections(); for (size_t i=0; i<sections.size(); i++) { SgAsmElfSection *elfsec = dynamic_cast<SgAsmElfSection*>(sections[i]); if (elfsec && elfsec->get_segment_entry()!=NULL) retval.push_back(elfsec); } return retval; }
/* Same as parent, but also includes sections that aren't mapped but which contain code. */ SgAsmGenericSectionPtrList BinaryLoaderElfObj::get_remap_sections(SgAsmGenericHeader *header) { SgAsmGenericSectionPtrList retval = BinaryLoaderElf::get_remap_sections(header); const SgAsmGenericSectionPtrList §ions = header->get_sections()->get_sections(); for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) { SgAsmGenericSection *section = *si; if (!section->is_mapped() && section->get_contains_code()) retval.push_back(section); } return retval; }
/** Returns info about the size of the entries based on information already available. Any or all arguments may be null * pointers if the caller is not interested in the value. */ rose_addr_t SgAsmElfSectionTable::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const { SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header()); ROSE_ASSERT(fhdr!=NULL); size_t struct_size = 0; size_t extra_size = fhdr->get_shextrasz(); size_t entry_size = 0; size_t nentries = 0; /* Size of required part of each entry */ if (4==fhdr->get_word_size()) { struct_size = sizeof(SgAsmElfSectionTableEntry::Elf32SectionTableEntry_disk); } else if (8==fhdr->get_word_size()) { struct_size = sizeof(SgAsmElfSectionTableEntry::Elf64SectionTableEntry_disk); } else { throw FormatError("bad ELF word size"); } /* Entire entry should be at least large enough for the required part. */ entry_size = struct_size; /* Size of optional parts. If we've parsed the table then use the largest optional part, otherwise assume the entry from * the ELF File Header is correct. */ SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections(); for (size_t i=0; i<sections.size(); i++) { SgAsmElfSection *elfsec = dynamic_cast<SgAsmElfSection*>(sections[i]); if (elfsec && elfsec->get_section_entry()) { ROSE_ASSERT(elfsec->get_id()>=0); nentries = std::max(nentries, (size_t)elfsec->get_id()+1); extra_size = std::max(extra_size, elfsec->get_section_entry()->get_extra().size()); } } /* Total number of entries. Either we haven't parsed the section table yet (nor created the sections it defines) or we * have. In the former case we use the setting from the ELF File Header. Otherwise the table has to be large enough to * store the section with the largest ID (ID also serves as the index into the ELF Section Table). */ if (0==nentries) nentries = fhdr->get_e_shnum(); /* Return values */ if (entsize) *entsize = entry_size; if (required) *required = struct_size; if (optional) *optional = extra_size; if (entcount) *entcount = nentries; return entry_size * nentries; }
/** Returns sections that have a preferred mapping that includes the specified relative virtual address. */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_sections_by_rva(rose_addr_t rva) const { SgAsmGenericSectionPtrList retval; for (SgAsmGenericSectionPtrList::iterator i = p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) { SgAsmGenericSection *section = *i; if (section->is_mapped() && rva >= section->get_mapped_preferred_rva() && rva < section->get_mapped_preferred_rva() + section->get_mapped_size()) { retval.push_back(section); } } return retval; }
/** Returns sectons in this header that contain all of the specified portion of the file. */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_sections_by_offset(rose_addr_t offset, rose_addr_t size) const { SgAsmGenericSectionPtrList retval; for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) { SgAsmGenericSection *section = *i; if (offset >= section->get_offset() && offset < section->get_offset()+section->get_size() && offset-section->get_offset() + size <= section->get_size()) retval.push_back(section); } return retval; }
/** 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::Endianness 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()); } } }
/* Parser */ SgAsmPESectionTable* SgAsmPESectionTable::parse() { SgAsmGenericSection::parse(); SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header()); ROSE_ASSERT(fhdr!=NULL); /* Parse section table and construct section objects, but do not parse the sections yet. */ SgAsmGenericSectionPtrList pending; const size_t entsize = sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk); for (size_t i=0; i<fhdr->get_e_nsections(); i++) { SgAsmPESectionTableEntry::PESectionTableEntry_disk disk; if (entsize!=read_content_local(i * entsize, &disk, entsize, false)) fprintf(stderr, "SgAsmPESectionTable::parse: warning: section table entry %" PRIuPTR " at file offset 0x%08"PRIx64 " extends beyond end of defined section table.\n", i, get_offset()+i*entsize); SgAsmPESectionTableEntry *entry = new SgAsmPESectionTableEntry(&disk); SgAsmPESection *section = NULL; if (entry->get_name() == ".idata") { section = new SgAsmPEImportSection(fhdr); } else { section = new SgAsmPESection(fhdr); } section->init_from_section_table(entry, i+1); pending.push_back(section); } /* Build the memory mapping like the real loader would do. This is the same code used by * SgAsmExecutableFileFormat::parseBinaryFormat() except we're doing it here early because we need it in the rest of the * PE parser. */ ROSE_ASSERT(NULL==fhdr->get_loader_map()); BinaryLoader *loader = BinaryLoader::lookup(fhdr); /*no need to clone; we're not changing any settings*/ ROSE_ASSERT(loader!=NULL); MemoryMap *loader_map = new MemoryMap; loader->remap(loader_map, fhdr); fhdr->set_loader_map(loader_map); /* Parse each section after the loader map is created */ for (size_t i=0; i<pending.size(); i++) pending[i]->parse(); return this; }
/** Returns sections having a preferred or actual mapping that includes the specified virtual address. If @p use_preferred is * set, then the condition is evaluated by looking at the section's preferred mapping, otherwise the actual mapping is used. * If an actual mapping is used, the specified virtual address must be part of the actual mapped section, not merely in the * memory region that was also mapped to satisfy alignment constraints. */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_sections_by_va(rose_addr_t va, bool use_preferred) const { if (use_preferred) { if (va < get_base_va()) return SgAsmGenericSectionPtrList(); rose_addr_t rva = va - get_base_va(); return get_sections_by_rva(rva); } SgAsmGenericSectionPtrList retval; for (size_t i=0; i<p_sections->get_sections().size(); i++) { SgAsmGenericSection *section = p_sections->get_sections()[i]; if (section->is_mapped() && va>=section->get_mapped_actual_va() && va<section->get_mapped_actual_va()+section->get_mapped_size()) retval.push_back(section); } return retval; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections_by_id(int id) const { SgAsmGenericSectionPtrList retval; /* Holes */ for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) { if ((*i)->get_id()==id) retval.push_back(*i); } /* Headers and their sections */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { if ((*i)->get_id()==id) retval.push_back(*i); const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_id(id); retval.insert(retval.end(), recurse.begin(), recurse.end()); } return retval; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections_by_name(std::string name, char sep/*or NUL*/) const { SgAsmGenericSectionPtrList retval; /* Truncate name */ if (sep) { size_t pos = name.find(sep); if (pos!=name.npos) name.erase(pos); } /* Holes */ for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) { std::string secname = (*i)->get_name()->get_string(); if (sep) { size_t pos = secname.find(sep); if (pos!=secname.npos) secname.erase(pos); } if (0==secname.compare(name)) retval.push_back(*i); } /* Headers and their sections */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { std::string secname = (*i)->get_name()->get_string(); if (sep) { size_t pos = secname.find(sep); if (pos!=secname.npos) secname.erase(pos); } if (0==secname.compare(name)) retval.push_back(*i); const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_name(name, sep); retval.insert(retval.end(), recurse.begin(), recurse.end()); } return retval; }
/** Returns sections in this header that have the specified name. If 'SEP' is a non-null string then ignore any part of name at * and after SEP. */ SgAsmGenericSectionPtrList SgAsmGenericHeader::get_sections_by_name(std::string name, char sep/*or NUL*/) const { if (sep) { size_t pos = name.find(sep); if (pos!=name.npos) name.erase(pos); } SgAsmGenericSectionPtrList retval; for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) { std::string secname = (*i)->get_name()->get_string(); if (sep) { size_t pos = secname.find(sep); if (pos!=secname.npos) secname.erase(pos); } if (0==secname.compare(name)) retval.push_back(*i); } return retval; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections_by_rva(rose_addr_t rva) const { SgAsmGenericSectionPtrList retval; /* Holes (probably not mapped anyway) */ for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) { if ((*i)->is_mapped() && rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size()) retval.push_back(*i); } /* Headers and their sections */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { if ((*i)->is_mapped() && rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size()) retval.push_back(*i); const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_rva(rva); retval.insert(retval.end(), recurse.begin(), recurse.end()); } return retval; }
/* Returns sections to be mapped */ SgAsmGenericSectionPtrList BinaryLoaderPe::get_remap_sections(SgAsmGenericHeader *header) { SgAsmGenericSectionPtrList retval; /* The NT loader always loads the PE header, so we include that first in the list. */ retval.push_back(header); /* Add the sections in the order they appear in the section table */ const SgAsmGenericSectionPtrList §ions = header->get_sections()->get_sections(); std::map<int, SgAsmGenericSection*> candidates; for (size_t i=0; i<sections.size(); i++) { if (sections[i]->get_id()>=0) { ROSE_ASSERT(candidates.find(sections[i]->get_id())==candidates.end()); candidates.insert(std::make_pair(sections[i]->get_id(), sections[i])); } } for (std::map<int, SgAsmGenericSection*>::iterator ci=candidates.begin(); ci!=candidates.end(); ++ci) { retval.push_back(ci->second); } return retval; }
/* Writes the section table back to disk. */ void SgAsmPESectionTable::unparse(std::ostream &f) const { SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header()); ROSE_ASSERT(fhdr != NULL); SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections(); for (size_t i = 0; i < sections.size(); i++) { if (sections[i]->get_id()>=0) { SgAsmPESection *section = isSgAsmPESection(sections[i]); ROSE_ASSERT(section!=NULL); /* Write the table entry */ ROSE_ASSERT(section->get_id() > 0); /*ID's are 1-origin in PE*/ size_t slot = section->get_id() - 1; SgAsmPESectionTableEntry *shdr = section->get_section_entry(); SgAsmPESectionTableEntry::PESectionTableEntry_disk disk; shdr->encode(&disk); write(f, slot*sizeof(disk), sizeof disk, &disk); } } }
/** Class method that prints info about offsets into known sections */ void SgAsmGenericSection::dump_containing_sections(FILE *f, const std::string &prefix, rose_rva_t rva, const SgAsmGenericSectionPtrList &slist) { for (size_t i=0; i<slist.size(); i++) { SgAsmGenericSection *s = slist[i]; if (s->is_mapped() && rva>=s->get_mapped_preferred_rva() && rva<s->get_mapped_preferred_rva()+s->get_mapped_size()) { rose_addr_t offset = rva - s->get_mapped_preferred_rva(); fprintf(f, "%-*s is 0x%08"PRIx64" (%"PRIu64") bytes into section [%d] \"%s\"\n", DUMP_FIELD_WIDTH, prefix.c_str(), offset, offset, s->get_id(), s->get_name()->get_string(true).c_str()); } } }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections_by_offset(rose_addr_t offset, rose_addr_t size) const { SgAsmGenericSectionPtrList retval; /* Holes */ for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) { if (offset >= (*i)->get_offset() && offset < (*i)->get_offset()+(*i)->get_size() && offset-(*i)->get_offset() + size <= (*i)->get_size()) retval.push_back(*i); } /* Headers and their sections */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { if (offset >= (*i)->get_offset() && offset < (*i)->get_offset()+(*i)->get_size() && offset-(*i)->get_offset() + size <= (*i)->get_size()) retval.push_back(*i); const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_offset(offset, size); retval.insert(retval.end(), recurse.begin(), recurse.end()); } return retval; }
SgAsmGenericSectionPtrList SgAsmGenericFile::get_sections(bool include_holes) const { SgAsmGenericSectionPtrList retval; /* Start with headers and holes */ retval.insert(retval.end(), p_headers->get_headers().begin(), p_headers->get_headers().end()); if (include_holes) retval.insert(retval.end(), p_holes->get_sections().begin(), p_holes->get_sections().end()); /* Add sections pointed to by headers. */ for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) { if ((*i)->get_sections()!=NULL) { const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections()->get_sections(); retval.insert(retval.end(), recurse.begin(), recurse.end()); } } return retval; }
void SgAsmGenericFile::shift_extend(SgAsmGenericSection *s, rose_addr_t sa, rose_addr_t sn, AddressSpace space, Elasticity elasticity) { ROSE_ASSERT(s!=NULL); ROSE_ASSERT(s->get_file()==this); ROSE_ASSERT((space & (ADDRSP_FILE|ADDRSP_MEMORY)) != 0); const bool debug = false; static size_t ncalls=0; char p[256]; if (debug) { const char *space_s="unknown"; if (space & ADDRSP_FILE) { space_s = "file"; } else if (space & ADDRSP_MEMORY) { space_s = "memory"; } sprintf(p, "SgAsmGenericFile::shift_extend[%" PRIuPTR "]: ", ncalls++); fprintf(stderr, "%s -- START --\n", p); fprintf(stderr, "%s S = [%d] \"%s\"\n", p, s->get_id(), s->get_name()->get_string(true).c_str()); fprintf(stderr, "%s %s Sa=0x%08" PRIx64 " (%" PRIu64 "), Sn=0x%08" PRIx64 " (%" PRIu64 ")\n", p, space_s, sa, sa, sn, sn); fprintf(stderr, "%s elasticity = %s\n", p, (ELASTIC_NONE==elasticity ? "none" : ELASTIC_UNREF==elasticity ? "unref" : ELASTIC_HOLE==elasticity ? "unref+holes" : "unknown")); } /* No-op case */ if (0==sa && 0==sn) { if (debug) { fprintf(stderr, "%s No change necessary.\n", p); fprintf(stderr, "%s -- END --\n", p); } return; } bool filespace = (space & ADDRSP_FILE)!=0; bool memspace = (space & ADDRSP_MEMORY)!=0; rose_addr_t align=1, aligned_sa, aligned_sasn; SgAsmGenericSectionPtrList neighbors, villagers; ExtentMap amap; /* address mappings for all extents */ Extent sp; /* Get a list of all sections that may need to be adjusted. */ SgAsmGenericSectionPtrList all; switch (elasticity) { case ELASTIC_NONE: case ELASTIC_UNREF: all = filespace ? get_sections() : get_mapped_sections(); break; case ELASTIC_HOLE: all = filespace ? get_sections(false) : get_mapped_sections(); break; } if (debug) { fprintf(stderr, "%s Following sections are in 'all' set:\n", p); for (size_t i=0; i<all.size(); i++) { Extent ep; if (filespace) { ep = all[i]->get_file_extent(); } else { ROSE_ASSERT(all[i]->is_mapped()); ep = all[i]->get_mapped_preferred_extent(); } fprintf(stderr, "%s 0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64 " [%d] \"%s\"\n", p, ep.relaxed_first(), ep.size(), ep.relaxed_first()+ep.size(), all[i]->get_id(), all[i]->get_name()->get_string(true).c_str()); } } for (size_t pass=0; pass<2; pass++) { if (debug) { fprintf(stderr, "%s -- %s --\n", p, 0==pass?"FIRST PASS":"******"); } /* S offset and size in file or memory address space */ if (filespace) { sp = s->get_file_extent(); } else if (!memspace || !s->is_mapped()) { return; /*nothing to do*/ } else { sp = s->get_mapped_preferred_extent(); } /* Build address map */ for (size_t i=0; i<all.size(); i++) { if (filespace) { amap.insert(all[i]->get_file_extent()); } else { ROSE_ASSERT(all[i]->is_mapped()); amap.insert(all[i]->get_mapped_preferred_extent()); } } if (debug) { fprintf(stderr, "%s Address map:\n", p); amap.dump_extents(stderr, (std::string(p)+" ").c_str(), "amap"); fprintf(stderr, "%s Extent of S:\n", p); fprintf(stderr, "%s start=0x%08" PRIx64 " size=0x%08" PRIx64 " end=0x%08" PRIx64 "\n", p, sp.relaxed_first(), sp.size(), sp.relaxed_first()+sp.size()); } /* Neighborhood (nhs) of S is a single extent. However, if S is zero size then nhs might be empty. The neighborhood of * S is S plus all sections that overlap with S and all sections that are right-contiguous with S. */ ExtentMap nhs_map; for (ExtentMap::iterator amapi=amap.begin(); amapi!=amap.end(); ++amapi) { if (amapi->first.relaxed_first() <= sp.relaxed_first()+sp.size() && amapi->first.relaxed_first()+amapi->first.size() > sp.relaxed_first()) nhs_map.insert(amapi->first, amapi->second); } if (debug) { fprintf(stderr, "%s Neighborhood of S:\n", p); nhs_map.dump_extents(stderr, (std::string(p)+" ").c_str(), "nhs_map"); } Extent nhs; if (nhs_map.size()>0) { assert(nhs_map.nranges()==1); nhs = nhs_map.begin()->first; } else { nhs = sp; } /* What sections are in the neighborhood (including S), and right of the neighborhood? */ neighbors.clear(); /*sections in neighborhood*/ neighbors.push_back(s); villagers.clear(); /*sections right of neighborhood*/ if (debug) fprintf(stderr, "%s Ignoring left (L) sections:\n", p); for (size_t i=0; i<all.size(); i++) { SgAsmGenericSection *a = all[i]; if (a==s) continue; /*already pushed onto neighbors*/ Extent ap; if (filespace) { ap = a->get_file_extent(); } else if (!a->is_mapped()) { continue; } else { ap = a->get_mapped_preferred_extent(); } switch (ExtentMap::category(ap, nhs)) { case 'L': if (debug) fprintf(stderr, "%s L 0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64 " [%d] \"%s\"\n", p, ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size(), a->get_id(), a->get_name()->get_string(true).c_str()); break; case 'R': if (ap.relaxed_first()==nhs.relaxed_first()+nhs.size() && 0==ap.size()) { /* Empty sections immediately right of the neighborhood of S should actually be considered part of the * neighborhood rather than right of it. */ neighbors.push_back(a); } else if (elasticity!=ELASTIC_NONE) { /* If holes are elastic then treat things right of the hole as being part of the right village; otherwise * add those sections to the neighborhood of S even though they fall outside 'nhs' (it's OK because this * partitioning of sections is the only thing we use 'nhs' for anyway. */ villagers.push_back(a); } else if ('L'==ExtentMap::category(ap, sp)) { /*ignore sections left of S*/ } else { neighbors.push_back(a); } break; default: if ('L'!=ExtentMap::category(ap, sp)) /*ignore sections left of S*/ neighbors.push_back(a); break; } } if (debug) { fprintf(stderr, "%s Neighbors:\n", p); for (size_t i=0; i<neighbors.size(); i++) { SgAsmGenericSection *a = neighbors[i]; Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); rose_addr_t align = filespace ? a->get_file_alignment() : a->get_mapped_alignment(); char cat = ExtentMap::category(ap, sp); fprintf(stderr, "%s %c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64, p, cat, 0==ap.relaxed_first() % (align?align:1) ? ' ' : '!', ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size()); if (strchr("RICE", cat)) { fprintf(stderr, " align=0x%08" PRIx64, align); } else { fputs(" ", stderr); } fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str()); } if (villagers.size()>0) fprintf(stderr, "%s Villagers:\n", p); for (size_t i=0; i<villagers.size(); i++) { SgAsmGenericSection *a = villagers[i]; Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); rose_addr_t align = filespace ? a->get_file_alignment() : a->get_mapped_alignment(); fprintf(stderr, "%s %c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64, p, ExtentMap::category(ap, sp), /*cat should always be R*/ 0==ap.relaxed_first() % (align?align:1) ? ' ' : '!', ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size()); fputs(" ", stderr); fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str()); } } /* Adjust Sa to satisfy all alignment constraints in neighborhood(S) for sections that will move (cats R, I, C, and E). */ align = 1; for (size_t i=0; i<neighbors.size(); i++) { SgAsmGenericSection *a = neighbors[i]; Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); if (strchr("RICE", ExtentMap::category(ap, sp))) { rose_addr_t x = filespace ? a->get_file_alignment() : a->get_mapped_alignment(); #if BOOST_VERSION < 106900 align = boost::math::lcm(align, x?x:1); // deprecated in boost-1.69.0 #else align = boost::integer::lcm(align, x?x:1); // not present before boost-1.60.0 #endif } } aligned_sa = (sa/align + (sa%align?1:0))*align; aligned_sasn = ((sa+sn)/align + ((sa+sn)%align?1:0))*align; if (debug) { fprintf(stderr, "%s Alignment LCM = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, align, align); fprintf(stderr, "%s Aligned Sa = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, aligned_sa, aligned_sa); fprintf(stderr, "%s Aligned Sa+Sn = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, aligned_sasn, aligned_sasn); } /* Are there any sections to the right of neighborhood(S)? If so, find the one with the lowest start address and use * that to define the size of the hole right of neighborhood(S). */ if (0==villagers.size()) break; SgAsmGenericSection *after_hole = NULL; Extent hp(0, 0); for (size_t i=0; i<villagers.size(); i++) { SgAsmGenericSection *a = villagers[i]; Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); if (!after_hole || ap.relaxed_first()<hp.relaxed_first()) { after_hole = a; hp = ap; } } ROSE_ASSERT(after_hole); ROSE_ASSERT(hp.relaxed_first() > nhs.relaxed_first()+nhs.size()); rose_addr_t hole_size = hp.relaxed_first() - (nhs.relaxed_first()+nhs.size()); if (debug) { fprintf(stderr, "%s hole size = 0x%08" PRIx64 " (%" PRIu64 "); need 0x%08" PRIx64 " (%" PRIu64 "); %s\n", p, hole_size, hole_size, aligned_sasn, aligned_sasn, hole_size>=aligned_sasn ? "large enough" : "not large enough"); } if (hole_size >= aligned_sasn) break; rose_addr_t need_more = aligned_sasn - hole_size; /* Hole is not large enough. We need to recursively move things that are right of our neighborhood, then recompute the * all-sections address map and neighborhood(S). */ ROSE_ASSERT(0==pass); /*logic problem since the recursive call should have enlarged the hole enough*/ if (debug) { fprintf(stderr, "%s Calling recursively to increase hole size by 0x%08" PRIx64 " (%" PRIu64 ") bytes\n", p, need_more, need_more); } shift_extend(after_hole, need_more, 0, space, elasticity); if (debug) fprintf(stderr, "%s Returned from recursive call\n", p); } /* Consider sections that are in the same neighborhood as S */ if (debug) fprintf(stderr, "%s -- ADJUSTING --\n", p); bool resized_mem = false; for (size_t i=0; i<neighbors.size(); i++) { SgAsmGenericSection *a = neighbors[i]; Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); switch (ExtentMap::category(ap, sp)) { case 'L': break; case 'R': if (filespace) { a->set_offset(a->get_offset()+aligned_sasn); } else { a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sasn); } break; case 'C': /*including S itself*/ case 'E': if (filespace) { a->set_offset(a->get_offset()+aligned_sa); a->set_size(a->get_size()+sn); if (memspace && !resized_mem && a->is_mapped()) { shift_extend(a, 0, sn, ADDRSP_MEMORY, elasticity); resized_mem = true; } } else { a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa); a->set_mapped_size(a->get_mapped_size()+sn); } break; case 'O': if (ap.relaxed_first()==sp.relaxed_first()) { if (filespace) { a->set_offset(a->get_offset()+aligned_sa); a->set_size(a->get_size()+sn); } else { a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa); a->set_mapped_size(a->get_mapped_size()+sn); } } else { if (filespace) { a->set_size(a->get_size()+aligned_sasn); if (memspace && !resized_mem && a->is_mapped()) { shift_extend(a, 0, aligned_sasn, ADDRSP_MEMORY, elasticity); resized_mem = true; } } else { a->set_mapped_size(a->get_mapped_size()+aligned_sasn); } } break; case 'I': if (filespace) { a->set_offset(a->get_offset()+aligned_sa); } else { a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa); } break; case 'B': if (filespace) { a->set_size(a->get_size()+sn); if (memspace && !resized_mem && a->is_mapped()) { shift_extend(a, 0, sn, ADDRSP_MEMORY, elasticity); resized_mem = true; } } else { a->set_mapped_size(a->get_size()+sn); } break; default: ROSE_ASSERT(!"invalid extent category"); break; } if (debug) { const char *space_name = filespace ? "file" : "mem"; rose_addr_t x = filespace ? a->get_file_alignment() : a->get_mapped_alignment(); fprintf(stderr, "%s %4s-%c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64, p, space_name, ExtentMap::category(ap, sp), 0==ap.relaxed_first()%(x?x:1)?' ':'!', ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size()); Extent newap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent(); fprintf(stderr, " -> %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64, 0==newap.relaxed_first()%(x?x:1)?' ':'!', newap.relaxed_first(), newap.size(), newap.relaxed_first()+newap.size()); fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str()); } } if (debug) fprintf(stderr, "%s -- END --\n", p); }