Exemplo n.º 1
0
/** Pre-unparsing updates */
bool
SgAsmElfSegmentTable::reallocate()
{
    bool reallocated = false;

    /* Resize based on word size from ELF File Header */
    size_t opt_size, nentries;
    rose_addr_t need = calculate_sizes(NULL, NULL, &opt_size, &nentries);
    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 data members in the ELF File Header. No need to return true for these changes. */
    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    fhdr->set_phextrasz(opt_size);
    fhdr->set_e_phnum(nentries);

    return reallocated;
}
Exemplo n.º 2
0
/* 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;
}
Exemplo n.º 3
0
Arquivo: ElfNote.C Projeto: KurSh/rose
/** Pre-unparsing adjustments */
bool
SgAsmElfNoteSection::reallocate()
{
    bool reallocated = SgAsmElfSection::reallocate();
    
    /* How much space is needed by the notes? */
    rose_addr_t need = 0;
    for (size_t i=0; i<p_entries->get_entries().size(); i++) {
        SgAsmElfNoteEntry *ent = p_entries->get_entries()[i];
        need += ent->calculate_size();
    }

    /* Adjust the section/segment size */
    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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
/** Causes section to not be mapped to memory. */
void
SgAsmGenericSection::clear_mapped()
{
    set_mapped_size(0);
    set_mapped_preferred_rva(0);
    set_mapped_actual_va(0);
    set_mapped_rperm(false);
    set_mapped_wperm(false);
    set_mapped_xperm(false);
}
Exemplo n.º 6
0
SgAsmElfSection *
SgAsmElfSection::init_from_segment_table(SgAsmElfSegmentTableEntry *shdr, bool mmap_only)
{
    if (!mmap_only) {
        /* Purpose */
        set_purpose(SP_HEADER);

        /* File mapping */
        set_offset(shdr->get_offset());
        set_size(shdr->get_filesz());
        set_file_alignment(shdr->get_align());
        grab_content();
    
        /* Name */
        char name[128];
        switch (shdr->get_type()) {
            case SgAsmElfSegmentTableEntry::PT_LOAD:         strcpy(name, "LOAD");        break;
            case SgAsmElfSegmentTableEntry::PT_DYNAMIC:      strcpy(name, "DYNAMIC");     break;
            case SgAsmElfSegmentTableEntry::PT_INTERP:       strcpy(name, "INTERP");      break;
            case SgAsmElfSegmentTableEntry::PT_NOTE:         strcpy(name, "NOTE");        break;
            case SgAsmElfSegmentTableEntry::PT_SHLIB:        strcpy(name, "SHLIB");       break;
            case SgAsmElfSegmentTableEntry::PT_PHDR:         strcpy(name, "PHDR");        break;
            case SgAsmElfSegmentTableEntry::PT_TLS:          strcpy(name, "TLS");         break;
            case SgAsmElfSegmentTableEntry::PT_GNU_EH_FRAME: strcpy(name, "EH_FRAME");    break;
            case SgAsmElfSegmentTableEntry::PT_GNU_STACK:    strcpy(name, "GNU_STACK");   break;
            case SgAsmElfSegmentTableEntry::PT_GNU_RELRO:    strcpy(name, "GNU_RELRO");   break;
            case SgAsmElfSegmentTableEntry::PT_PAX_FLAGS:    strcpy(name, "PAX_FLAGS");   break;
            case SgAsmElfSegmentTableEntry::PT_SUNWBSS:      strcpy(name, "SUNWBSS");     break;
            case SgAsmElfSegmentTableEntry::PT_SUNWSTACK:    strcpy(name, "SUNWSTACK");   break;
            default:                                         sprintf(name, "PT_0x%08x", shdr->get_type()); break;
        }
        sprintf(name+strlen(name), "#%" PRIuPTR "", shdr->get_index());
        set_name(new SgAsmBasicString(name));
    }
    
    /* Memory mapping */
    set_mapped_preferred_rva(shdr->get_vaddr());
    set_mapped_actual_va(0); /*will be assigned by Loader*/
    set_mapped_size(shdr->get_memsz());
    set_mapped_alignment(shdr->get_align());
    set_mapped_rperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_RPERM ? true : false);
    set_mapped_wperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_WPERM ? true : false);
    set_mapped_xperm(shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_XPERM ? true : false);

    /* Add segment table entry to section */
    set_segment_entry(shdr);
    shdr->set_parent(this);

    return this;
}
Exemplo n.º 7
0
/* Change size of PE header based on word size */
bool
SgAsmPEFileHeader::reallocate()
{
    bool reallocated = SgAsmGenericHeader::reallocate();
    
    /* Resize if necessary */
    rose_addr_t need = sizeof(PEFileHeader_disk);
    if (4==get_word_size()) {
        need += sizeof(PE32OptHeader_disk);
    } else if (8==get_word_size()) {
        need += sizeof(PE64OptHeader_disk);
    } else {
        throw FormatError("unsupported PE word size");
    }
    need += p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_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;
    }

    /* Make sure the RVA/Size pairs at the end of the header are consistent with the sections to which they point. Reallocate()
     * has already been called recursively for the sections. */
    update_rvasize_pairs();

    /* Make sure header is consistent with sections. Reallocate() has already been called recursively for the sections.
     * Count the number of sections in the table and update the header's e_nsections member. */
    if (p_section_table) {
        ROSE_ASSERT(p_section_table->get_header()==this);
        SgAsmGenericSectionList *all = get_sections();
        p_e_nsections = 0;
        for (size_t i=0; i<all->get_sections().size(); i++) {
            SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]);
            if (pesec && pesec->get_section_entry()!=NULL)
                p_e_nsections++;
        }

        rose_addr_t header_size = ALIGN_UP(p_section_table->get_offset() + p_section_table->get_size(),
                                           p_e_file_align>0 ? p_e_file_align : 1);
#if 1
        /* The PE Specification regarding e_header_size (known as "SizeOfHeader" on page 14 of "Microsoft Portable Executable
         * and Common Object File Format Specification: Revision 8.1 February 15, 2008" is not always followed. We recompute
         * it here as being the minimum RVA from all the sections defined in the PE Section Table, but not smaller
         * than the value according to the specification. This alternate value is kept if it's already in the parse tree,
         * otherwise we use the correct value. (RPM 2008-10-21) */
        rose_addr_t min_offset = 0;
        for (size_t i=0, nfound=0; i<all->get_sections().size(); i++) {
            SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]);
            if (pesec && pesec->get_section_entry()!=NULL) {
                if (0==nfound++) {
                    min_offset = pesec->get_offset();
                } else {
                    min_offset = std::min(min_offset, pesec->get_offset() );
                }
            }
        }

        rose_addr_t header_size2 = std::max(header_size, min_offset);
        if (p_e_header_size==header_size2)
            header_size = header_size2;

        /* If the original header size was zero then don't change that--leave it at zero. Some tiny executables have a zero
         * value here and as a result, since this is near the end of the NT Optional Header, they can truncate the file and
         * the loader will fill the optional header with zeros when reading. (RPM 2008-11-11) */
        if (p_e_header_size==0)
            header_size = 0;
#endif
        p_e_header_size = header_size;
    }

    /* The size of the optional header. If there's a section table then we use its offset to calculate the optional header
     * size in order to be compatible with the PE loader. Otherwise use the actual optional header size. */
    if (p_section_table) {
        ROSE_ASSERT(p_section_table->get_offset() >= get_offset() + sizeof(PEFileHeader_disk));
        p_e_nt_hdr_size = p_section_table->get_offset() - (get_offset() + sizeof(PEFileHeader_disk));
    } else if (4==get_word_size()) {
        p_e_nt_hdr_size = sizeof(PE32OptHeader_disk);
    } else if (8==get_word_size()) {
        p_e_nt_hdr_size = sizeof(PE64OptHeader_disk);
    } else {
        throw FormatError("invalid PE word size");
    }
            
    /* Update COFF symbol table related data members in the file header */
    if (get_coff_symtab()) {
        ROSE_ASSERT(get_coff_symtab()->get_header()==this);
        set_e_coff_symtab(get_coff_symtab()->get_offset());
        set_e_coff_nsyms(get_coff_symtab()->get_nslots());
    }

    /* Update some additional header fields */
    set_e_num_rvasize_pairs(get_rvasize_pairs()->get_pairs().size());
    set_e_opt_magic(4==get_word_size() ? 0x010b : 0x020b);
    set_e_lmajor((get_exec_format()->get_version() >> 16) & 0xffff);
    set_e_lminor(get_exec_format()->get_version() & 0xffff);

    /* Adjust the COFF Header's e_nt_hdr_size to accommodate the NT Optional Header in such a way that EXEs from tinype.com
     * don't change (i.e., don't increase e_nt_hdr_size if the bytes beyond it are zero anyway, and if they aren't then adjust
     * it as little as possible.  The RVA/Size pairs are considered to be part of the NT Optional Header. */
    size_t oh_size = p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk);
    size_t rvasize_offset; /*offset with respect to "oh" buffer allocated below*/
    if (4==get_word_size()) {
        oh_size += sizeof(PE32OptHeader_disk);
    } else if (8==get_word_size()) {
        oh_size += sizeof(PE64OptHeader_disk);
    } else {
        throw FormatError("unsupported PE word size");
    }
    unsigned char *oh = new unsigned char[oh_size];
    if (4==get_word_size()) {
        encode((PE32OptHeader_disk*)oh);
        rvasize_offset = sizeof(PE32OptHeader_disk);
    } else if (8==get_word_size()) {
        encode((PE64OptHeader_disk*)oh);
        rvasize_offset = sizeof(PE64OptHeader_disk);
    } else {
        delete[] oh;
        throw FormatError("unsupported PE word size");
    }
    while (oh_size>p_e_nt_hdr_size) {
        if (0!=oh[oh_size-1]) break;
        --oh_size;
    }
    set_e_nt_hdr_size(oh_size);
    return reallocated;
}
Exemplo n.º 8
0
/** Initialize the header with information parsed from the file and construct and parse everything that's reachable from the
 *  header. The PE File Header should have been constructed such that SgAsmPEFileHeader::ctor() was called. */
SgAsmPEFileHeader*
SgAsmPEFileHeader::parse()
{
    SgAsmGenericHeader::parse();
    
    /* Read header, zero padding if the file isn't large enough */
    PEFileHeader_disk fh;
    if (sizeof(fh)>get_size())
        extend(sizeof(fh)-get_size());
    if (sizeof(fh)!=read_content_local(0, &fh, sizeof fh, false))
        fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE header at byte 0x%08"PRIx64"\n", get_offset());

    /* Check magic number before getting too far */
    if (fh.e_magic[0]!='P' || fh.e_magic[1]!='E' || fh.e_magic[2]!='\0' || fh.e_magic[3]!='\0')
        throw FormatError("Bad PE magic number");

    /* Decode COFF file header */
    p_e_cpu_type           = le_to_host(fh.e_cpu_type);
    p_e_nsections          = le_to_host(fh.e_nsections);
    p_e_time               = le_to_host(fh.e_time);
    p_e_coff_symtab        = le_to_host(fh.e_coff_symtab);
    p_e_coff_nsyms         = le_to_host(fh.e_coff_nsyms);
    p_e_nt_hdr_size        = le_to_host(fh.e_nt_hdr_size);
    p_e_flags              = le_to_host(fh.e_flags);

    /* Read the "Optional Header" (optional in the sense that not all files have one, but required for an executable), the
     * size of which is stored in the e_nt_hdr_size of the main PE file header. According to 
     * http://www.phreedom.org/solar/code/tinype the Windows loader honors the e_nt_hdr_size even when set to smaller than the
     * smallest possible documented size of the optional header. Also it's possible for the optional header to extend beyond
     * the end of the file, in which case that part should be read as zero. */
    PE32OptHeader_disk oh32;
    rose_addr_t need32 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh32));
    if (need32>get_size())
        extend(need32-get_size());
    if (sizeof(oh32)!=read_content_local(sizeof fh, &oh32, sizeof oh32, false))
        fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n", 
                get_offset() + sizeof(fh));
    p_e_opt_magic = le_to_host(oh32.e_opt_magic);
    
    /* File format changes from ctor() */
    p_exec_format->set_purpose(p_e_flags & HF_PROGRAM ? PURPOSE_EXECUTABLE : PURPOSE_LIBRARY);
    p_exec_format->set_word_size(0x010b==p_e_opt_magic? 4 : 8);

    /* Decode the optional header. */
    rose_addr_t entry_rva;
    if (4==p_exec_format->get_word_size()) {
        p_e_lmajor             = le_to_host(oh32.e_lmajor);
        p_e_lminor             = le_to_host(oh32.e_lminor);
        p_e_code_size          = le_to_host(oh32.e_code_size);
        p_e_data_size          = le_to_host(oh32.e_data_size);
        p_e_bss_size           = le_to_host(oh32.e_bss_size);
        entry_rva              = le_to_host(oh32.e_entrypoint_rva);
        p_e_code_rva           = le_to_host(oh32.e_code_rva);
        p_e_data_rva           = le_to_host(oh32.e_data_rva);
        p_base_va              = le_to_host(oh32.e_image_base);
        p_e_section_align      = le_to_host(oh32.e_section_align);
        p_e_file_align         = le_to_host(oh32.e_file_align);
        p_e_os_major           = le_to_host(oh32.e_os_major);
        p_e_os_minor           = le_to_host(oh32.e_os_minor);
        p_e_user_major         = le_to_host(oh32.e_user_major);
        p_e_user_minor         = le_to_host(oh32.e_user_minor);
        p_e_subsys_major       = le_to_host(oh32.e_subsys_major);
        p_e_subsys_minor       = le_to_host(oh32.e_subsys_minor);
        p_e_reserved9          = le_to_host(oh32.e_reserved9);
        p_e_image_size         = le_to_host(oh32.e_image_size);
        p_e_header_size        = le_to_host(oh32.e_header_size);
        p_e_file_checksum      = le_to_host(oh32.e_file_checksum);
        p_e_subsystem          = le_to_host(oh32.e_subsystem);
        p_e_dll_flags          = le_to_host(oh32.e_dll_flags);
        p_e_stack_reserve_size = le_to_host(oh32.e_stack_reserve_size);
        p_e_stack_commit_size  = le_to_host(oh32.e_stack_commit_size);
        p_e_heap_reserve_size  = le_to_host(oh32.e_heap_reserve_size);
        p_e_heap_commit_size   = le_to_host(oh32.e_heap_commit_size);
        p_e_loader_flags       = le_to_host(oh32.e_loader_flags);
        p_e_num_rvasize_pairs  = le_to_host(oh32.e_num_rvasize_pairs);
    } else if (8==p_exec_format->get_word_size()) {
        /* We guessed wrong. This is a 64-bit header, not 32-bit. */
        PE64OptHeader_disk oh64;
        rose_addr_t need64 = sizeof(PEFileHeader_disk) + std::min(p_e_nt_hdr_size, (rose_addr_t)(sizeof oh64));
        if (need64>get_size())
            extend(need64-get_size());
        if (sizeof(oh64)!=read_content_local(sizeof fh, &oh64, sizeof oh64))
            fprintf(stderr, "SgAsmPEFileHeader::parse: warning: short read of PE Optional Header at byte 0x%08"PRIx64"\n", 
                    get_offset() + sizeof(fh));
        p_e_lmajor             = le_to_host(oh64.e_lmajor);
        p_e_lminor             = le_to_host(oh64.e_lminor);
        p_e_code_size          = le_to_host(oh64.e_code_size);
        p_e_data_size          = le_to_host(oh64.e_data_size);
        p_e_bss_size           = le_to_host(oh64.e_bss_size);
        entry_rva              = le_to_host(oh64.e_entrypoint_rva);
        p_e_code_rva           = le_to_host(oh64.e_code_rva);
     // p_e_data_rva           = le_to_host(oh.e_data_rva);             /* not in PE32+ */
        p_base_va              = le_to_host(oh64.e_image_base);
        p_e_section_align      = le_to_host(oh64.e_section_align);
        p_e_file_align         = le_to_host(oh64.e_file_align);
        p_e_os_major           = le_to_host(oh64.e_os_major);
        p_e_os_minor           = le_to_host(oh64.e_os_minor);
        p_e_user_major         = le_to_host(oh64.e_user_major);
        p_e_user_minor         = le_to_host(oh64.e_user_minor);
        p_e_subsys_major       = le_to_host(oh64.e_subsys_major);
        p_e_subsys_minor       = le_to_host(oh64.e_subsys_minor);
        p_e_reserved9          = le_to_host(oh64.e_reserved9);
        p_e_image_size         = le_to_host(oh64.e_image_size);
        p_e_header_size        = le_to_host(oh64.e_header_size);
        p_e_file_checksum      = le_to_host(oh64.e_file_checksum);
        p_e_subsystem          = le_to_host(oh64.e_subsystem);
        p_e_dll_flags          = le_to_host(oh64.e_dll_flags);
        p_e_stack_reserve_size = le_to_host(oh64.e_stack_reserve_size);
        p_e_stack_commit_size  = le_to_host(oh64.e_stack_commit_size);
        p_e_heap_reserve_size  = le_to_host(oh64.e_heap_reserve_size);
        p_e_heap_commit_size   = le_to_host(oh64.e_heap_commit_size);
        p_e_loader_flags       = le_to_host(oh64.e_loader_flags);
        p_e_num_rvasize_pairs  = le_to_host(oh64.e_num_rvasize_pairs);
    } else {
        throw FormatError("unrecognized Windows PE optional header magic number");
    }

    /* Magic number */
    p_magic.clear();
    for (size_t i = 0; i < sizeof(fh.e_magic); ++i)
        p_magic.push_back(fh.e_magic[i]);

    /* File format */
    ROSE_ASSERT(p_e_lmajor <= 0xffff && p_e_lminor <= 0xffff);
    p_exec_format->set_version((p_e_lmajor << 16) | p_e_lminor);
    p_exec_format->set_is_current_version(true); /*FIXME*/

    /* Target architecture */
    switch (p_e_cpu_type) {
      case 0x0000:
        set_isa(ISA_UNSPECIFIED);
        break;
      case 0x014c:
        set_isa(ISA_IA32_386);
        break;
      case 0x014d:
        set_isa(ISA_IA32_486);
        break;
      case 0x014e:
        set_isa(ISA_IA32_Pentium);
        break;
      case 0x0162:
        set_isa(ISA_MIPS_MarkI); /* R2000, R3000 */
        break;
      case 0x0163:
        set_isa(ISA_MIPS_MarkII); /* R6000 */
        break;
      case 0x0166:
        set_isa(ISA_MIPS_MarkIII); /* R4000 */
        break;
      case 0x01a2: /*Hitachi SH3*/
      case 0x01a3: /*Hitachi SH3 with FPU*/
      case 0x01a6: /*Hitachi SH4*/
      case 0x01a8: /*Hitachi SH5*/
        set_isa(ISA_Hitachi_SH);
        break;
      case 0x01c0:
        set_isa(ISA_ARM_Family);
        break;
      case 0x01d3:
        set_isa(ISA_Matsushita_AM33);
        break;
      case 0x01f0: /*w/o FPU*/
      case 0x01f1: /*with FPU*/
        set_isa(ISA_PowerPC);
        break;
      case 0x0200:
        set_isa(ISA_IA64_Family);
        break;
      case 0x0266:
        set_isa(ISA_MIPS_16);
        break;
      case 0x0366:
        set_isa(ISA_MIPS_FPU);
        break;
      case 0x0466:
        set_isa(ISA_MIPS_16FPU);
        break;
      case 0x0ebc:
        set_isa(ISA_EFI_ByteCode);
        break;
      case 0x8664:
        set_isa(ISA_X8664_Family);
        break;
      case 0x9041:
        set_isa(ISA_Mitsubishi_M32R);
        break;
      default:
        fprintf(stderr, "SgAsmPEFileHeader::parse: warning: unrecognized e_cputype = 0x%x (%u)\n", p_e_cpu_type, p_e_cpu_type);
        set_isa(ISA_OTHER);
        break;
    }

    /* The NT loader normally maps this file header at the header's base virtual address. */
    set_mapped_preferred_rva(0);
    set_mapped_actual_va(0); /* will be assigned by BinaryLoader */
    set_mapped_size(p_e_header_size);
    set_mapped_alignment(0);
    set_mapped_rperm(true);
    set_mapped_wperm(false);
    set_mapped_xperm(false);

    /* Entry point. We will eventually bind the entry point to a particular section (in SgAsmPEFileHeader::parse) so that if
     * sections are rearranged, extended, etc. the entry point will be updated automatically. */
    add_entry_rva(entry_rva);

    /* The PE File Header has a fixed-size component followed by some number of RVA/Size pairs. The add_rvasize_pairs() will
     * extend  the header and parse the RVA/Size pairs. */
    if (get_e_num_rvasize_pairs() > 1000) {
        fprintf(stderr, "warning: PE File Header contains an unreasonable number of Rva/Size pairs. Limiting to 1000.\n");
        set_e_num_rvasize_pairs(1000);
    }
    add_rvasize_pairs();

    /* Construct the section table and its sections (non-synthesized sections). The specification says that the section table
     * comes after the optional (NT) header, which in turn comes after the fixed part of the PE header. The size of the
     * optional header is indicated in the fixed header. */
    rose_addr_t secttab_offset = get_offset() + sizeof(PEFileHeader_disk) + get_e_nt_hdr_size();
    rose_addr_t secttab_size = get_e_nsections() * sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk);
    SgAsmPESectionTable *secttab = new SgAsmPESectionTable(this);
    secttab->set_offset(secttab_offset);
    secttab->set_size(secttab_size);
    secttab->parse();
    set_section_table(secttab);

    /* Parse the COFF symbol table */
    if (get_e_coff_symtab() && get_e_coff_nsyms()) {
        SgAsmCoffSymbolTable *symtab = new SgAsmCoffSymbolTable(this);
        symtab->set_offset(get_e_coff_symtab());
        symtab->parse();
        set_coff_symtab(symtab);
    }

    /* Associate RVAs with particular sections so that if a section's mapping is changed the RVA gets adjusted automatically. */
    ROSE_ASSERT(get_entry_rvas().size()==1);
    get_entry_rvas()[0].bind(this);
    set_e_code_rva(get_e_code_rva().bind(this));
    set_e_data_rva(get_e_data_rva().bind(this));

    /* Turn header-specified tables (RVA/Size pairs) into generic sections */
    create_table_sections();
    return this;
}
Exemplo n.º 9
0
/** Update prior to unparsing */
bool
SgAsmElfFileHeader::reallocate()
{
    /* Reallocate superclass. This also calls reallocate() for all the sections associated with this ELF File Header. */
    bool reallocated = SgAsmGenericHeader::reallocate();

    /* Resize header based on current word size */
    rose_addr_t need;
    if (4==get_word_size()) {
        need = sizeof(Elf32FileHeader_disk);
    } else if (8==get_word_size()) {
        need = sizeof(Elf64FileHeader_disk);
    } else {
        throw FormatError("unsupported ELF word size");
    }
    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 ELF-specific file class data member from generic data. */
    switch(get_word_size()) {
      case 4:
        p_e_ident_file_class = 1;
        break;
      case 8:
        p_e_ident_file_class = 2;
        break;
      default:
        ROSE_ASSERT(!"invalid word size");
        break;
    }

    /* Byte order. According to the spec, valid values are 1 (little-endian) and 2 (big-endian). However, we've seen cases
     * where a value of zero is used to indicate "native" order (loader assumes words are in the order of the machine on which
     * the loader is running, and the ROSE ELF parser determines the order by looking at other fields in the header). Any
     * original value other than 1 or 2 will be written to the new output; otherwise we choose 1 or 2 based on the currently
     * defined byte order. */
    if (p_e_ident_data_encoding==1 || p_e_ident_data_encoding==2) {
        p_e_ident_data_encoding = ByteOrder::ORDER_LSB==get_sex() ? 1 : 2;
    }

    /* Update ELF-specific file type from generic data. */
    switch (p_exec_format->get_purpose()) {
      case PURPOSE_UNSPECIFIED:
      case PURPOSE_PROC_SPECIFIC:
      case PURPOSE_OS_SPECIFIC:
      case PURPOSE_OTHER:
        /* keep as is */
        break;
      case PURPOSE_LIBRARY:
        if (p_e_type==1 || p_e_type==3) {
            /* keep as is */
        } else {
            p_e_type = 1;
        }
        break;
      case PURPOSE_EXECUTABLE:
        p_e_type = 2;
        break;
      case PURPOSE_CORE_DUMP:
        p_e_type = 4;
    }

    /* Update ELF machine type. */
    p_e_machine = isa_to_machine(get_isa());

    /* The ELF header stores its own size */
    p_e_ehsize = get_size();

    return reallocated;
}
Exemplo n.º 10
0
SgAsmElfSection *
SgAsmElfSection::init_from_section_table(SgAsmElfSectionTableEntry *shdr, SgAsmElfStringSection *strsec, int id)
{
    ROSE_ASSERT(shdr);
    ROSE_ASSERT(strsec);
    ROSE_ASSERT(id>=0);

    /* Purpose */
    switch (shdr->get_sh_type()) {
      case SgAsmElfSectionTableEntry::SHT_PROGBITS:
        set_purpose(SP_PROGRAM);
        break;
      case SgAsmElfSectionTableEntry::SHT_STRTAB:
        set_purpose(SP_HEADER);
        break;
      case SgAsmElfSectionTableEntry::SHT_DYNSYM:
      case SgAsmElfSectionTableEntry::SHT_SYMTAB:
        set_purpose(SP_SYMTAB);
        break;
      default:
        set_purpose(SP_OTHER);
        break;
    }

    /* File mapping */
    set_offset(shdr->get_sh_offset());
    if (SgAsmElfSectionTableEntry::SHT_NULL==shdr->get_sh_type() ||
        SgAsmElfSectionTableEntry::SHT_NOBITS==shdr->get_sh_type()) {
        set_size(0);
    } else {
        set_size(shdr->get_sh_size());
    }
    set_file_alignment(shdr->get_sh_addralign());
    grab_content();

    /* Memory mapping */
    if (shdr->get_sh_addr() > 0) {
        set_mapped_preferred_rva(shdr->get_sh_addr());
        set_mapped_actual_va(0); /*will be assigned by Loader*/
        set_mapped_size(shdr->get_sh_size());
        set_mapped_rperm(true);
        set_mapped_wperm((shdr->get_sh_flags() & 0x01) == 0x01);
        set_mapped_xperm((shdr->get_sh_flags() & 0x04) == 0x04);
        set_mapped_alignment(shdr->get_sh_addralign());
    } else {
        set_mapped_preferred_rva(0);
        set_mapped_actual_va(0); /*will be assigned by Loader*/
        set_mapped_size(0);
        set_mapped_rperm(false);
        set_mapped_wperm(false);
        set_mapped_xperm(false);
        set_mapped_alignment(shdr->get_sh_addralign());
    }

    /* Name. This has to be near the end because possibly strsec==this, in which case we have to call set_size() to extend the
     * section to be large enough before we can try to look up the name. */
    set_id(id);
    set_name(new SgAsmStoredString(strsec->get_strtab(), shdr->get_sh_name()));

    /* Add section table entry to section */
    set_section_entry(shdr);
    shdr->set_parent(this);

    return this;
}