示例#1
0
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;
}
示例#2
0
/** 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;
}
示例#3
0
/** Attaches a previously unattached ELF Section to the section table. If @p section is an  ELF String Section
 *  (SgAsmElfStringSection) that contains an ELF String Table (SgAsmElfStringTable) and the ELF Section Table has no
 *  associated string table then the @p section will be used as the string table to hold the section names.
 *
 *  This method complements SgAsmElfSection::init_from_section_table. This method initializes the section table from the
 *  section while init_from_section_table() initializes the section from the section table.
 *
 *  Returns the new section table entry linked into the AST. */
SgAsmElfSectionTableEntry *
SgAsmElfSectionTable::add_section(SgAsmElfSection *section)
{
    ROSE_ASSERT(section!=NULL);
    ROSE_ASSERT(section->get_file()==get_file());
    ROSE_ASSERT(section->get_header()==get_header());
    ROSE_ASSERT(section->get_section_entry()==NULL);            /* must not be in the section table yet */
    
    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);

    /* Assign an ID if there isn't one yet */
    if (section->get_id()<0) {
        int id = fhdr->get_e_shnum();
        fhdr->set_e_shnum(id+1);
        section->set_id(id);
    }

    /* If the supplied section is a string table and the ELF Section Table doesn't have a string table associated with it yet,
     * then use the supplied section as the string table to hold the names of the sections. When this happens, all sections
     * that are already defined in the ELF Section Table should have their names moved into the new string table. */
    SgAsmElfStringSection *strsec = NULL;
    if (fhdr->get_e_shstrndx()==0) {
        strsec = dynamic_cast<SgAsmElfStringSection*>(section);
        if (strsec) {
            fhdr->set_e_shstrndx(section->get_id());
            SgAsmGenericSectionList *all = fhdr->get_sections();
            for (size_t i=0; i<all->get_sections().size(); i++) {
                SgAsmElfSection *s = dynamic_cast<SgAsmElfSection*>(all->get_sections()[i]);
                if (s && s->get_id()>=0 && s->get_section_entry()!=NULL) {
                    s->allocate_name_to_storage(strsec);
                }
            }
        }
    } else {
        strsec = dynamic_cast<SgAsmElfStringSection*>(fhdr->get_section_by_id(fhdr->get_e_shstrndx()));
        ROSE_ASSERT(strsec!=NULL);
    }

    /* Make sure the name is in the correct string table */
    if (strsec)
        section->allocate_name_to_storage(strsec);

    /* Create a new section table entry. */
    SgAsmElfSectionTableEntry *shdr = new SgAsmElfSectionTableEntry;
    shdr->update_from_section(section);
    section->set_section_entry(shdr);

    return shdr;
}
示例#4
0
bool
SgAsmElfRelocSection::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_uses_addend ?
                            SgAsmElfSectionTableEntry::SHT_RELA :
                            SgAsmElfSectionTableEntry::SHT_REL);

    return reallocated;
}
示例#5
0
/** 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;
}
示例#6
0
/** 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;
}
示例#7
0
/** 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());
        }
    }
}
示例#8
0
/** Parses an ELF Section Table and constructs and parses all sections reachable from the table. The section is extended as
 *  necessary based on the number of entries and the size of each entry. */
SgAsmElfSectionTable *
SgAsmElfSectionTable::parse()
{
    SgAsmGenericSection::parse();

    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);
    ByteOrder::Endianness sex = fhdr->get_sex();

    size_t ent_size, struct_size, opt_size, nentries;
    calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries);
    ROSE_ASSERT(opt_size==fhdr->get_shextrasz() && nentries==fhdr->get_e_shnum());

    /* If the current size is very small (0 or 1 byte) then we're coming straight from the constructor and the parsing should
     * also extend this section to hold all the entries. Otherwise the caller must have assigned a specific size for a good
     * reason and we should leave that alone, reading zeros if the entries extend beyond the defined size. */
    if (get_size()<=1 && get_size()<nentries*ent_size)
        extend(nentries*ent_size - get_size());

    // Read all the section headers.  Section headers are not essential to the Unix loader, which uses only segments. Therefore
    // we should be prepared to handle bad entries.
    std::vector<SgAsmElfSectionTableEntry*> entries;
    rose_addr_t offset = 0;
    try {
        for (size_t i=0; i<nentries; i++, offset+=ent_size) {
            SgAsmElfSectionTableEntry *shdr = NULL;
            if (4 == fhdr->get_word_size()) {
                SgAsmElfSectionTableEntry::Elf32SectionTableEntry_disk disk;
                read_content_local(offset, &disk, struct_size);
                shdr = new SgAsmElfSectionTableEntry(sex, &disk);
            } else {
                SgAsmElfSectionTableEntry::Elf64SectionTableEntry_disk disk;
                read_content_local(offset, &disk, struct_size);
                shdr = new SgAsmElfSectionTableEntry(sex, &disk);
            }
            if (opt_size>0)
                shdr->get_extra() = read_content_local_ucl(offset+struct_size, opt_size);
            entries.push_back(shdr);
        }
    } catch (const ShortRead &error) {
        mlog[ERROR] <<"short read for elf section header #" <<entries.size()
                    <<" at file offset " <<StringUtility::addrToString(error.offset)
                    <<" when reading " <<StringUtility::plural(error.size, "bytes") <<"\n";
        mlog[ERROR] <<"expected " <<StringUtility::plural(nentries, "sections") <<", but bailing out early\n";
        nentries = entries.size();
    }

    /* This vector keeps track of which sections have already been parsed. We could get the same information by calling
     * fhdr->get_section_by_id() and passing the entry number since entry numbers and IDs are one and the same in ELF. However,
     * this is a bit easier. */
    std::vector<SgAsmElfSection*> is_parsed;
    is_parsed.resize(entries.size(), NULL);

    /* All sections implicitly depend on the section string table for their names. */
    SgAsmElfStringSection *section_name_strings=NULL;
    if (fhdr->get_e_shstrndx() > 0 && fhdr->get_e_shstrndx() < entries.size()) {
        SgAsmElfSectionTableEntry *entry = entries[fhdr->get_e_shstrndx()];
        ASSERT_not_null(entry);
        section_name_strings = new SgAsmElfStringSection(fhdr);
        section_name_strings->init_from_section_table(entry, section_name_strings, fhdr->get_e_shstrndx());
        section_name_strings->parse();
        is_parsed[fhdr->get_e_shstrndx()] = section_name_strings;
    }

    /* Read all the sections. Some sections depend on other sections, so we read them in such an order that all dependencies
     * are satisfied first. */
    while (1) {
        bool try_again=false;
        for (size_t i=0; i<entries.size(); i++) {
            SgAsmElfSectionTableEntry *entry = entries[i];
            ROSE_ASSERT(entry->get_sh_link()<entries.size());

            /* Some sections might reference another section through the sh_link member. */
            bool need_linked = entry->get_sh_link() > 0;
            ROSE_ASSERT(!need_linked || entry->get_sh_link()<entries.size());
            SgAsmElfSection *linked = need_linked ? is_parsed[entry->get_sh_link()] : NULL;

            /* Relocation sections might have a second linked section stored in sh_info. */
            bool need_info_linked = (entry->get_sh_type() == SgAsmElfSectionTableEntry::SHT_REL ||
                                     entry->get_sh_type() == SgAsmElfSectionTableEntry::SHT_RELA) &&
                                    entry->get_sh_info() > 0;
            ROSE_ASSERT(!need_info_linked || entry->get_sh_info()<entries.size());
            SgAsmElfSection *info_linked = need_info_linked ? is_parsed[entry->get_sh_info()] : NULL;

            if (is_parsed[i]) {
                /* This section has already been parsed. */
            } else if ((need_linked && !linked) || (need_info_linked && !info_linked)) {
                /* Don't parse this section yet because it depends on something that's not parsed yet. */
                try_again = true;
            } else {
                switch (entry->get_sh_type()) {
                    case SgAsmElfSectionTableEntry::SHT_NULL:
                        /* Null entry. We still create the section just to hold the section header. */
                        is_parsed[i] = new SgAsmElfSection(fhdr);
                        break;
                    case SgAsmElfSectionTableEntry::SHT_NOBITS:
                        /* These types of sections don't occupy any file space (e.g., BSS) */
                        is_parsed[i] = new SgAsmElfSection(fhdr);
                        break;
                    case SgAsmElfSectionTableEntry::SHT_DYNAMIC: {
                        SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
                        ROSE_ASSERT(strsec);
                        is_parsed[i] = new SgAsmElfDynamicSection(fhdr, strsec);
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_DYNSYM: {
                        SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
                        ROSE_ASSERT(strsec);
                        SgAsmElfSymbolSection *symsec = new SgAsmElfSymbolSection(fhdr, strsec);
                        symsec->set_is_dynamic(true);
                        is_parsed[i] = symsec;
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_SYMTAB: {
                        SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
                        ROSE_ASSERT(strsec);
                        SgAsmElfSymbolSection *symsec = new SgAsmElfSymbolSection(fhdr, strsec);
                        symsec->set_is_dynamic(false);
                        is_parsed[i] = symsec;
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_STRTAB:
                        is_parsed[i] = new SgAsmElfStringSection(fhdr);
                        break;
                    case SgAsmElfSectionTableEntry::SHT_REL: {
                        SgAsmElfSymbolSection *symbols = dynamic_cast<SgAsmElfSymbolSection*>(linked);
                        SgAsmElfRelocSection *relocsec = new SgAsmElfRelocSection(fhdr, symbols, info_linked);
                        relocsec->set_uses_addend(false);
                        is_parsed[i] = relocsec;
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_RELA: {
                        SgAsmElfSymbolSection *symbols = dynamic_cast<SgAsmElfSymbolSection*>(linked);
                        SgAsmElfRelocSection *relocsec = new SgAsmElfRelocSection(fhdr, symbols, info_linked);
                        relocsec->set_uses_addend(true);
                        is_parsed[i] = relocsec;
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_PROGBITS: {
                        if (!section_name_strings) {
                            fprintf(stderr, "SgAsmElfSectionTable::parse(): no string table for section table\n");
                            is_parsed[i] = new SgAsmElfSection(fhdr);
                        } else {
                            std::string section_name = section_name_strings->read_content_local_str(entry->get_sh_name());
                            if (section_name == ".eh_frame") {
                                is_parsed[i] = new SgAsmElfEHFrameSection(fhdr);
                            } else {
                                is_parsed[i] = new SgAsmElfSection(fhdr);
                            }
                        }
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_GNU_versym: {
                        is_parsed[i] = new SgAsmElfSymverSection(fhdr);
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_GNU_verdef: {
                        SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
                        ROSE_ASSERT(strsec);
                        is_parsed[i] = new SgAsmElfSymverDefinedSection(fhdr,strsec);
                        break;
                    }
                    case SgAsmElfSectionTableEntry::SHT_GNU_verneed: {
                        SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(linked);
                        ROSE_ASSERT(strsec);
                        is_parsed[i] = new SgAsmElfSymverNeededSection(fhdr,strsec);
                        break;
                    }
                    default:
                        is_parsed[i] = new SgAsmElfSection(fhdr);
                        break;
                }
                is_parsed[i]->init_from_section_table(entry, section_name_strings, i);
                is_parsed[i]->parse();
            }
        }
        if (!try_again)
            break;
    }

    /* Initialize links between sections */
    for (size_t i = 0; i < entries.size(); i++) {
        SgAsmElfSectionTableEntry *shdr = entries[i];
        if (shdr->get_sh_link() > 0) {
            SgAsmElfSection *source = isSgAsmElfSection(fhdr->get_file()->get_section_by_id(i));
            SgAsmElfSection *target = isSgAsmElfSection(fhdr->get_file()->get_section_by_id(shdr->get_sh_link()));
            assert(source);     /* because we created it above */
            source->set_linked_section(target);
        }
    }

    /* Finish parsing sections now that we have basic info for all the sections. */
    for (size_t i=0; i<is_parsed.size(); i++)
        is_parsed[i]->finish_parsing();

    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;
 }