void SgAsmElfSection::dump(FILE *f, const char *prefix, ssize_t idx) const { char p[4096]; if (idx>=0) { sprintf(p, "%sElfSection[%zd].", prefix, idx); } else { sprintf(p, "%sElfSection.", prefix); } int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p)); SgAsmGenericSection::dump(f, p, -1); if (get_section_entry()) get_section_entry()->dump(f, p, -1); if (get_segment_entry()) get_segment_entry()->dump(f, p, -1); if (p_linked_section) { fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "linked_to", p_linked_section->get_id(), p_linked_section->get_name()->get_string(true).c_str()); } else { fprintf(f, "%s%-*s = NULL\n", p, w, "linked_to"); } if (variantT() == V_SgAsmElfSection) //unless a base class hexdump(f, 0, std::string(p)+"data at ", p_data); }
rose_addr_t SgAsmElfSection::calculate_sizes(size_t r32size, size_t r64size, /*size of required parts*/ const std::vector<size_t> &optsizes, /*size of optional parts and number of parts parsed*/ size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const { size_t struct_size = 0; size_t extra_size = 0; size_t entry_size = 0; size_t nentries = 0; SgAsmElfFileHeader *fhdr = get_elf_header(); /* Assume ELF Section Table Entry is correct for now for the size of each entry in the table. */ ROSE_ASSERT(get_section_entry()!=NULL); entry_size = get_section_entry()->get_sh_entsize(); /* Size of required part of each entry */ if (0==r32size && 0==r64size) { /* Probably called by four-argument SgAsmElfSection::calculate_sizes and we don't know the sizes of the required parts * because there isn't a parser for this type of section, or the section doesn't contain a table. In the latter case * the ELF Section Table has a zero sh_entsize and we'll treat the section as if it were a table with one huge entry. * Otherwise we'll assume that the struct size is the same as the sh_entsize and there's no optional data. */ struct_size = entry_size>0 ? entry_size : get_size(); } else if (4==fhdr->get_word_size()) { struct_size = r32size; } else if (8==fhdr->get_word_size()) { struct_size = r64size; } else { throw FormatError("bad ELF word size"); } /* Entire entry should be at least large enough for the required part. This also takes care of the case when the ELF * Section Table Entry has a zero-valued sh_entsize */ entry_size = std::max(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 Section Table is correct. */ nentries = optsizes.size(); if (nentries>0) { for (size_t i=0; i<nentries; i++) { extra_size = std::max(extra_size, optsizes[i]); } entry_size = std::min(entry_size, struct_size+extra_size); } else { extra_size = entry_size - struct_size; nentries = entry_size>0 ? get_size() / entry_size : 0; } /* 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; }
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; }
/** Called prior to unparsing. Updates symbol entries with name offsets */ bool SgAsmElfSymbolSection::reallocate() { bool reallocated = SgAsmElfSection::reallocate(); /* Update parts of the section and segment tables not updated by superclass */ SgAsmElfSectionTableEntry *secent = get_section_entry(); if (secent) secent->set_sh_type(p_is_dynamic ? SgAsmElfSectionTableEntry::SHT_DYNSYM : SgAsmElfSectionTableEntry::SHT_SYMTAB); return reallocated; }
/** Reallocate space for the string section if necessary. Note that reallocation is lazy here -- we don't shrink the section, * we only enlarge it (if you want the section to shrink then call SgAsmGenericStrtab::reallocate(bool) with a true value * rather than calling this function. SgAsmElfStringSection::reallocate is called in response to unparsing a file and gives * the string table a chance to extend its container section if it needs to allocate more space for strings. */ bool SgAsmElfStringSection::reallocate() { bool reallocated = SgAsmElfSection::reallocate(); if (get_strtab()->reallocate(false)) reallocated = true; /* Update parts of the section and segment tables not updated by superclass */ SgAsmElfSectionTableEntry *secent = get_section_entry(); if (secent) secent->set_sh_type(SgAsmElfSectionTableEntry::SHT_STRTAB); return reallocated; }
/** 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); }
/** Initializes this ELF Symbol Section by parsing a file. */ SgAsmElfSymbolSection * SgAsmElfSymbolSection::parse() { SgAsmElfSection::parse(); SgAsmElfFileHeader *fhdr = get_elf_header(); ROSE_ASSERT(fhdr!=NULL); SgAsmElfSectionTableEntry *shdr = get_section_entry(); ROSE_ASSERT(shdr!=NULL); SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(get_linked_section()); ROSE_ASSERT(strsec!=NULL); size_t entry_size, struct_size, extra_size, nentries; calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries); ROSE_ASSERT(entry_size==shdr->get_sh_entsize()); /* Parse each entry */ for (size_t i=0; i<nentries; i++) { SgAsmElfSymbol *entry=0; if (4==fhdr->get_word_size()) { entry = new SgAsmElfSymbol(this); /*adds symbol to this symbol table*/ SgAsmElfSymbol::Elf32SymbolEntry_disk disk; read_content_local(i*entry_size, &disk, struct_size); entry->parse(fhdr->get_sex(), &disk); } else if (8==fhdr->get_word_size()) { entry = new SgAsmElfSymbol(this); /*adds symbol to this symbol table*/ SgAsmElfSymbol::Elf64SymbolEntry_disk disk; read_content_local(i*entry_size, &disk, struct_size); entry->parse(fhdr->get_sex(), &disk); } else { throw FormatError("unsupported ELF word size"); } if (extra_size>0) entry->get_extra() = read_content_local_ucl(i*entry_size+struct_size, extra_size); } return this; }
virtual bool reallocate() { bool retval = SgAsmElfSection::reallocate(); /* returns true if size or position of any section changed */ SgAsmElfSectionTableEntry *ste = get_section_entry(); ste->set_sh_flags(ste->get_sh_flags() | SgAsmElfSectionTableEntry::SHF_ALLOC); /* set the SHF_ALLOC bit */ return retval; }