Пример #1
0
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;
}
Пример #2
0
/** 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;
}
Пример #3
0
void
SgAsmElfRelocSection::unparse(std::ostream &f) const
{
    SgAsmElfFileHeader *fhdr = get_elf_header();
    ROSE_ASSERT(fhdr);
    ByteOrder::Endianness 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++) {
        SgAsmElfRelocEntry::Elf32RelaEntry_disk diska32;
        SgAsmElfRelocEntry::Elf64RelaEntry_disk diska64;
        SgAsmElfRelocEntry::Elf32RelEntry_disk  disk32;
        SgAsmElfRelocEntry::Elf64RelEntry_disk  disk64;
        void *disk  = NULL;

        SgAsmElfRelocEntry *entry = p_entries->get_entries()[i];

        if (4==fhdr->get_word_size()) {
            if (p_uses_addend) {
                disk = entry->encode(sex, &diska32);
            } else {
                disk = entry->encode(sex, &disk32);
            }
        } else if (8==fhdr->get_word_size()) {
            if (p_uses_addend) {
                disk = entry->encode(sex, &diska64);
            } else {
                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 0 /*FIXME: padding not supported here yet (RPM 2008-10-13)*/
        if (entry->get_extra().size()>0) {
            ROSE_ASSERT(entry->get_extra().size()<=extra_size);
            write(f, spos, entry->get_extra());
        }
#endif
    }

    unparse_holes(f);
}
Пример #4
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());
        }
    }
}
Пример #5
0
SgAsmElfRelocSection *
SgAsmElfRelocSection::parse()
{
    SgAsmElfSection::parse();

    SgAsmElfFileHeader *fhdr = get_elf_header();
    ROSE_ASSERT(fhdr);

    size_t entry_size, struct_size, extra_size, nentries;
    calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
    ROSE_ASSERT(extra_size==0);
    
    /* Parse each entry */
    for (size_t i=0; i<nentries; i++) {
        SgAsmElfRelocEntry *entry = 0;
        if (4==fhdr->get_word_size()) {
            if (p_uses_addend) {
                SgAsmElfRelocEntry::Elf32RelaEntry_disk disk;
                read_content_local(i*entry_size, &disk, struct_size);
                entry = new SgAsmElfRelocEntry(this);
                entry->parse(fhdr->get_sex(), &disk);
            } else {
                SgAsmElfRelocEntry::Elf32RelEntry_disk disk;
                read_content_local(i*entry_size, &disk, struct_size);
                entry = new SgAsmElfRelocEntry(this);
                entry->parse(fhdr->get_sex(), &disk);
            }
        } else if (8==fhdr->get_word_size()) {
            if (p_uses_addend) {
                SgAsmElfRelocEntry::Elf64RelaEntry_disk disk;
                read_content_local(i*entry_size, &disk, struct_size);
                entry = new SgAsmElfRelocEntry(this);
                entry->parse(fhdr->get_sex(), &disk);
            } else {
                SgAsmElfRelocEntry::Elf64RelEntry_disk disk;
                read_content_local(i*entry_size, &disk, struct_size);
                entry = new SgAsmElfRelocEntry(this);
                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;
}
Пример #6
0
/** 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);
}
Пример #7
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;
}
Пример #8
0
void
MyTraversal::visit(SgNode* astNode)
{
    SgAsmElfFileHeader *fhdr = isSgAsmElfFileHeader(astNode);
    if (fhdr) {
        size_t oldsize = fhdr->get_word_size();
        if (8==oldsize) {
            size_t newsize = 4;
            printf("*** Changing ELF word size from %zu bits to %zu bits\n", 8*oldsize, 8*newsize);
            fhdr->get_exec_format()->set_word_size(newsize);
        } else if (4==oldsize) {
            size_t newsize = 8;
            printf("*** Changing ELF word size from %zu bits to %zu bits\n", 8*oldsize, 8*newsize);
            fhdr->get_exec_format()->set_word_size(newsize);
        }
    }
}
Пример #9
0
/** Parses an ELF Segment (Program Header) Table and constructs and parses all segments reachable from the table. The section
 *  is extended as necessary based on the number of entries and teh size of each entry. */
SgAsmElfSegmentTable *
SgAsmElfSegmentTable::parse()
{
    SgAsmGenericSection::parse();

    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);
    ByteOrder 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_phextrasz() && nentries==fhdr->get_e_phnum());

    /* 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());
    
    rose_addr_t offset=0;                                /* w.r.t. the beginning of this section */
    for (size_t i=0; i<nentries; i++, offset+=ent_size) {
        /* Read/decode the segment header */
        SgAsmElfSegmentTableEntry *shdr = NULL;
        if (4==fhdr->get_word_size()) {
            SgAsmElfSegmentTableEntry::Elf32SegmentTableEntry_disk disk;
            read_content_local(offset, &disk, struct_size);
            shdr = new SgAsmElfSegmentTableEntry(sex, &disk);
        } else {
            SgAsmElfSegmentTableEntry::Elf64SegmentTableEntry_disk disk;
            read_content_local(offset, &disk, struct_size);
            shdr = new SgAsmElfSegmentTableEntry(sex, &disk);
        }
        shdr->set_index(i);
        if (opt_size>0)
            shdr->get_extra() = read_content_local_ucl(offset+struct_size, opt_size);

        /* Null segments are just unused slots in the table; no real section to create */
        if (SgAsmElfSegmentTableEntry::PT_NULL == shdr->get_type())
            continue;

        /* Create SgAsmElfSection objects for each ELF Segment. However, if the ELF Segment Table describes a segment
         * that's the same offset and size as a section from the Elf Section Table (and the memory mappings are
         * consistent) then use the preexisting section instead of creating a new one. */
        SgAsmElfSection *s = NULL;
        SgAsmGenericSectionPtrList possible = fhdr->get_file()->get_sections_by_offset(shdr->get_offset(), shdr->get_filesz());
        for (size_t j=0; !s && j<possible.size(); j++) {
            if (possible[j]->get_offset()!=shdr->get_offset() || possible[j]->get_size()!=shdr->get_filesz())
                continue; /*different file extent*/
            if (possible[j]->is_mapped()) {
                if (possible[j]->get_mapped_preferred_rva()!=shdr->get_vaddr() ||
                    possible[j]->get_mapped_size()!=shdr->get_memsz())
                    continue; /*different mapped address or size*/
                unsigned section_perms = (possible[j]->get_mapped_rperm() ? 0x01 : 0x00) |
                                         (possible[j]->get_mapped_wperm() ? 0x02 : 0x00) |
                                         (possible[j]->get_mapped_xperm() ? 0x04 : 0x00);
                unsigned segment_perms = (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_RPERM ? 0x01 : 0x00) |
                                         (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_WPERM ? 0x02 : 0x00) |
                                         (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_XPERM ? 0x04 : 0x00);
                if (section_perms != segment_perms)
                    continue; /*different mapped permissions*/
            }

            /* Found a match. Set memory mapping params only. */
            s = dynamic_cast<SgAsmElfSection*>(possible[j]);
            if (!s) continue; /*potential match was not from the ELF Section or Segment table*/
            if (s->get_segment_entry()) continue; /*potential match is assigned to some other segment table entry*/
            s->init_from_segment_table(shdr, true); /*true=>set memory mapping params only*/
        }

        /* Create a new segment if no matching section was found. */
        if (!s) {
            if (SgAsmElfSegmentTableEntry::PT_NOTE == shdr->get_type()) {
                s = new SgAsmElfNoteSection(fhdr);
            } else {
                s = new SgAsmElfSection(fhdr);
            }
            s->init_from_segment_table(shdr);
            s->parse();
        }
    }
    return this;
}
Пример #10
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;
}
Пример #11
0
/** Unparse one Common Information Entry (CIE) without unparsing the Frame Description Entries (FDE) to which it points. The
 *  initial length fields are not included in the result string. */
std::string
SgAsmElfEHFrameEntryCI::unparse(const SgAsmElfEHFrameSection *ehframe) const 
{
    SgAsmElfFileHeader *fhdr = ehframe->get_elf_header();
    ROSE_ASSERT(fhdr!=NULL);

    /* Allocate worst-case size for results */
    size_t worst_size = (4+
                         1+
                         get_augmentation_string().size()+1+
                         10+
                         10+
                         10+
                         get_augmentation_data_length()+
                         get_instructions().size()+
                         fhdr->get_word_size());
    unsigned char *buf = new unsigned char[worst_size];

    rose_addr_t at = 0;
    uint32_t u32_disk;
    unsigned char u8_disk;

    /* CIE back offset (always zero) */
    u32_disk=0;
    memcpy(buf+at, &u32_disk, 4); at+=4;

    /* Version */
    u8_disk = get_version();
    memcpy(buf+at, &u8_disk, 1); at+=1;

    /* NUL-terminated Augmentation String */
    size_t sz = get_augmentation_string().size()+1;
    memcpy(buf+at, get_augmentation_string().c_str(), sz); at+=sz;

    /* Alignment factors */
    at = ehframe->write_uleb128(buf, at, get_code_alignment_factor());
    at = ehframe->write_sleb128(buf, at, get_data_alignment_factor());

    /* Augmentation data */
    at = ehframe->write_uleb128(buf, at, get_augmentation_data_length());
    std::string astr = get_augmentation_string();
    if (!astr.empty() && astr[0]=='z') {
        for (size_t i=1; i<astr.size(); i++) {
            if ('L'==astr[i]) {
                u8_disk = get_lsda_encoding();
                buf[at++] = u8_disk;
            } else if ('P'==astr[i]) {
                u8_disk = get_prh_encoding();
                buf[at++] = u8_disk;
                switch (get_prh_encoding()) {
                    case 0x05:
                    case 0x06:
                    case 0x07:
                        buf[at++] = get_prh_arg();
                        ByteOrder::host_to_le(get_prh_addr(), &u32_disk);
                        memcpy(buf+at, &u32_disk, 4); at+=4;
                        break;
                    default:
                        /* See parser */
                        if (++nwarnings<=WARNING_LIMIT) {
                            fprintf(stderr, "%s:%u: warning: unknown PRH encoding (0x%02x)\n",
                                    __FILE__, __LINE__, get_prh_encoding());
                            if (WARNING_LIMIT==nwarnings)
                                fprintf(stderr, "    (additional frame warnings will be suppressed)\n");
                        }
                        break;
                }
            } else if ('R'==astr[i]) {
                u8_disk = get_addr_encoding();
                buf[at++] = u8_disk;
            } else if ('S'==astr[i]) {
                /* Signal frame; no auxilliary data */
            } else {
                ROSE_ASSERT(!"invalid .eh_frame augmentation string");
                abort();
            }
        }
    }

    /* Initial instructions */
    sz = get_instructions().size();
    if (sz>0) {
        memcpy(buf+at, &(get_instructions()[0]), sz);
        at += sz;
    }

    std::string retval((char*)buf, at);
    delete[] buf;
    return retval;
}
Пример #12
0
/** Unparse the Frame Description Entry (FDE) into a string but do not include the leading length field(s) or the CIE back
 *  pointer. */
std::string
SgAsmElfEHFrameEntryFD::unparse(const SgAsmElfEHFrameSection *ehframe, SgAsmElfEHFrameEntryCI *cie) const
{
    SgAsmElfFileHeader *fhdr = ehframe->get_elf_header();
    ROSE_ASSERT(fhdr!=NULL);

    /* Allocate worst-case size for results */
    size_t worst_size = 8 + get_augmentation_data().size() + get_instructions().size() + fhdr->get_word_size();
    unsigned char *buf = new unsigned char[worst_size];

    size_t sz;
    rose_addr_t at = 0;
    uint32_t u32_disk;

    /* PC Begin (begin_rva) and size */
    switch (cie->get_addr_encoding()) {
        case -1:          /* No address encoding specified */
        case 0x01:
        case 0x03:
        case 0x1b: {
            ByteOrder::host_to_le(get_begin_rva().get_rva(), &u32_disk);
            memcpy(buf+at, &u32_disk, 4); at+=4;
            ByteOrder::host_to_le(get_size(), &u32_disk);
            memcpy(buf+at, &u32_disk, 4); at+=4;
            break;
        }
        default:
            /* See parser */
            if (++nwarnings<=WARNING_LIMIT) {
                fprintf(stderr, "%s:%u: warning: unknown FDE address encoding (0x%02x)\n",
                        __FILE__, __LINE__, cie->get_addr_encoding());
                if (WARNING_LIMIT==nwarnings)
                    fprintf(stderr, "    (additional frame warnings will be suppressed)\n");
            }
            break;
    }

    /* Augmentation Data */
    std::string astr = cie->get_augmentation_string();
    if (astr.size()>0 && astr[0]=='z') {
        at = ehframe->write_uleb128(buf, at, get_augmentation_data().size());
        sz = get_augmentation_data().size();
        if (sz>0) {
            memcpy(buf+at, &(get_augmentation_data()[0]), sz);
            at += sz;
        }
    }

    /* Call frame instructions */
    sz = get_instructions().size();
    if (sz>0) {
        memcpy(buf+at, &(get_instructions()[0]), sz);
        at += sz;
    }

    std::string retval((char*)buf, at);
    delete[] buf;
    return retval;
}