/** Tries to find a suitable offset for a string such that it overlaps with some other string already allocated. If the new * string is the same as the end of some other string (new="main", existing="domain") then we just use an offset into that * string since the space is already allocated for the existing string. If the new string ends with an existing string * (new="domain", existing="main") and there's enough free space before the existing string (two bytes in this case) then * we allocate some of that free space and use a suitable offset. In any case, upon return storage->get_offset() will return * the allocated offset if successful, or SgAsmGenericString::unallocated if we couldn't find an overlap. */ void SgAsmElfStrtab::allocate_overlap(SgAsmStringStorage *storage) { ROSE_ASSERT(storage->get_offset()==SgAsmGenericString::unallocated); size_t need = storage->get_string().size(); for (size_t i=0; i<p_storage_list.size(); i++) { SgAsmStringStorage *existing = p_storage_list[i]; if (existing->get_offset()!=SgAsmGenericString::unallocated) { size_t have = existing->get_string().size(); if (need<=have && 0==existing->get_string().compare(have-need, need, storage->get_string())) { /* An existing string ends with the new string. */ storage->set_offset(existing->get_offset() + (have-need)); return; } else if (need>have && existing->get_offset()>=need-have && 0==storage->get_string().compare(need-have, have, existing->get_string())) { /* New string ends with an existing string. Check for, and allocate, free space. */ rose_addr_t offset = existing->get_offset() - (need-have); /* positive diffs checked above */ AddressInterval allocationRequest = AddressInterval::baseSize(offset, need-have); if (get_freelist().contains(allocationRequest)) { get_freelist().erase(allocationRequest); storage->set_offset(offset); return; } } } } }
/** Write string table back to disk. Free space is zeroed out; holes are left as they are. */ void SgAsmElfStrtab::unparse(std::ostream &f) const { SgAsmGenericSection *container = get_container(); /* Write strings with NUL termination. Shared strings will be written more than once, but that's OK. */ for (size_t i=0; i<p_storage_list.size(); i++) { SgAsmStringStorage *storage = p_storage_list[i]; ROSE_ASSERT(storage->get_offset()!=SgAsmGenericString::unallocated); rose_addr_t at = container->write(f, storage->get_offset(), storage->get_string()); container->write(f, at, '\0'); } /* Fill free areas with zero */ BOOST_FOREACH (const AddressInterval &interval, get_freelist().intervals()) container->write(f, interval.least(), std::string(interval.size(), '\0')); }
/* Write string table back to disk. Free space is zeroed out; holes are left as they are. */ void SgAsmCoffStrtab::unparse(std::ostream &f) const { SgAsmGenericSection *container = get_container(); /* Write length coded strings. Shared strings will be written more than once, but that's OK. */ for (size_t i=0; i<p_storage_list.size(); i++) { SgAsmStringStorage *storage = p_storage_list[i]; ROSE_ASSERT(storage->get_offset()!=SgAsmGenericString::unallocated); rose_addr_t at = container->write(f, storage->get_offset(), storage->get_string()); container->write(f, at, '\0'); } /* Fill free areas with zero */ for (ExtentMap::const_iterator i=get_freelist().begin(); i!=get_freelist().end(); ++i) { container->write(f, i->first.first(), std::string(i->first.size(), '\0')); } }