示例#1
0
/** Converts 32-bit disk representation to host representation */
void
SgAsmElfSectionTableEntry::ctor(ByteOrder sex, const Elf32SectionTableEntry_disk *disk) 
{
    p_sh_name      = disk_to_host(sex, disk->sh_name);
    p_sh_type      = (SectionType)disk_to_host(sex, disk->sh_type);
    p_sh_flags     = disk_to_host(sex, disk->sh_flags);
    p_sh_addr      = disk_to_host(sex, disk->sh_addr);
    p_sh_offset    = disk_to_host(sex, disk->sh_offset);
    p_sh_size      = disk_to_host(sex, disk->sh_size);
    p_sh_link      = disk_to_host(sex, disk->sh_link);
    p_sh_info      = disk_to_host(sex, disk->sh_info);
    p_sh_addralign = disk_to_host(sex, disk->sh_addralign);
    p_sh_entsize   = disk_to_host(sex, disk->sh_entsize);
}
示例#2
0
/** Converts 32-bit disk representation to host representation */
void
SgAsmElfSegmentTableEntry::ctor(ByteOrder sex, const struct Elf32SegmentTableEntry_disk *disk) 
{
    p_type      = (SegmentType)disk_to_host(sex, disk->p_type);
    p_offset    = disk_to_host(sex, disk->p_offset);
    p_vaddr     = disk_to_host(sex, disk->p_vaddr);
    p_paddr     = disk_to_host(sex, disk->p_paddr);
    p_filesz    = disk_to_host(sex, disk->p_filesz);
    p_memsz     = disk_to_host(sex, disk->p_memsz);
    p_flags     = (SegmentFlags)disk_to_host(sex, disk->p_flags);
    p_align     = disk_to_host(sex, disk->p_align);
}
示例#3
0
文件: ElfNote.C 项目: KurSh/rose
/** Initialize a note by parsing it from the specified location in the note section. Return value is the offset to the
 *  beginning of the next note. */
rose_addr_t
SgAsmElfNoteEntry::parse(rose_addr_t at)
{
    /* Find the section holding this note */
    SgAsmElfNoteSection *notes = SageInterface::getEnclosingNode<SgAsmElfNoteSection>(this);
    ROSE_ASSERT(notes!=NULL);
    ROSE_ASSERT(at < notes->get_size());
    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(notes->get_header());
    ROSE_ASSERT(fhdr!=NULL);
    
    /* Length of note entry name, including NUL termination */
    uint32_t u32;
    notes->read_content_local(at, &u32, 4);
    size_t name_size = disk_to_host(fhdr->get_sex(), u32);
    at += 4;

    /* Length of note entry description (i.e., the payload) */
    notes->read_content_local(at, &u32, 4);
    size_t payload_size = disk_to_host(fhdr->get_sex(), u32);
    at += 4;

    /* Type of note */
    notes->read_content_local(at, &u32, 4);
    unsigned type = disk_to_host(fhdr->get_sex(), u32);
    at += 4;

    /* NUL-terminated name */
    std::string note_name = notes->read_content_local_str(at);
    ROSE_ASSERT(note_name.size()+1 == name_size);
    at += name_size;
    at = (at+3) & ~0x3; /* payload is aligned on a four-byte offset */

    /* Set properties */
    get_name()->set_string(note_name);
    set_type(type);
    p_payload = notes->read_content_local_ucl(at, payload_size);

    return at + payload_size;
}
示例#4
0
/** Initialize symbol by parsing a symbol table entry. An ELF String Section must be supplied in order to get the symbol name. */
void
SgAsmElfSymbol::parse(ByteOrder sex, const Elf64SymbolEntry_disk *disk)
{
    p_st_info  = disk_to_host(sex, disk->st_info);
    p_st_res1  = disk_to_host(sex, disk->st_res1);
    p_st_shndx = disk_to_host(sex, disk->st_shndx);
    p_st_size  = disk_to_host(sex, disk->st_size);

    p_value    = disk_to_host(sex, disk->st_value);
    p_size     = p_st_size;

    rose_addr_t name_offset  = disk_to_host(sex, disk->st_name);
    get_name()->set_string(name_offset);

    parse_common();
}
示例#5
0
/** Initialize by parsing a file. */
SgAsmElfEHFrameSection *
SgAsmElfEHFrameSection::parse()
{
    SgAsmElfSection::parse();
    SgAsmElfFileHeader *fhdr = get_elf_header();
    ROSE_ASSERT(fhdr!=NULL);

    rose_addr_t record_offset=0;
    std::map<rose_addr_t, SgAsmElfEHFrameEntryCI*> cies;

    while (record_offset<get_size()) {
        rose_addr_t at = record_offset;
        unsigned char u8_disk;
        uint32_t u32_disk;
        uint64_t u64_disk;

        /* Length or extended length */
        rose_addr_t length_field_size = 4; /*number of bytes not counted in length*/
        read_content_local(at, &u32_disk, 4); at += 4;
        rose_addr_t record_size = disk_to_host(fhdr->get_sex(), u32_disk);
        if (record_size==0xffffffff) {
            read_content_local(at, &u64_disk, 8); at += 8;
            record_size = disk_to_host(fhdr->get_sex(), u64_disk);
            length_field_size += 8; /*FIXME: it's not entirely clear whether ExtendedLength includes this field*/
        }
        if (0==record_size)
            break;

        /* Backward offset to CIE record, or zero if this is a CIE record. */
        read_content_local(at, &u32_disk, 4); at += 4;
        rose_addr_t cie_back_offset = disk_to_host(fhdr->get_sex(), u32_disk);
        if (0==cie_back_offset) {
            /* This is a CIE record */
            SgAsmElfEHFrameEntryCI *cie = new SgAsmElfEHFrameEntryCI(this);
            cies[record_offset] = cie;

            /* Version */
            uint8_t cie_version;
            read_content_local(at++, &cie_version, 1);
            cie->set_version(cie_version);

            /* Augmentation String */
            std::string astr = read_content_local_str(at);
            at += astr.size() + 1;
            cie->set_augmentation_string(astr);

            /* Alignment factors */
            cie->set_code_alignment_factor(read_content_local_uleb128(&at));
            cie->set_data_alignment_factor(read_content_local_sleb128(&at));

            /* Augmentation data length. This is apparently the length of the data described by the Augmentation String plus
             * the Initial Instructions plus any padding. [RPM 2009-01-15] */
            cie->set_augmentation_data_length(read_content_local_uleb128(&at));

            /* Augmentation data. The format of the augmentation data in the CIE record is determined by reading the
             * characters of the augmentation string. */ 
            if (!astr.empty() && astr[0]=='z') {
                for (size_t i=1; i<astr.size(); i++) {
                    if ('L'==astr[i]) {
                        read_content_local(at++, &u8_disk, 1);
                        cie->set_lsda_encoding(u8_disk);
                    } else if ('P'==astr[i]) {
                        /* The first byte is an encoding method which describes the following bytes, which are the address of
                         * a Personality Routine Handler. There appears to be very little documentation about these fields. */
                        read_content_local(at++, &u8_disk, 1);
                        cie->set_prh_encoding(u8_disk);
                        switch (cie->get_prh_encoding()) {
                            case 0x05:          /* See Ubuntu 32bit /usr/bin/aptitude */
                            case 0x06:          /* See second CIE record for Gentoo-Amd64 /usr/bin/addftinfo */
                            case 0x07:          /* See first CIE record for Gentoo-Amd64 /usr/bin/addftinfo */
                                read_content_local(at++, &u8_disk, 1); /* not sure what this is; arg for __gxx_personality_v0? */
                                cie->set_prh_arg(u8_disk);
                                read_content_local(at, &u32_disk, 4); at+=4; /* address of <__gxx_personality_v0@plt> */
                                cie->set_prh_addr(ByteOrder::le_to_host(u32_disk));
                                break;
                            case 0x09:          /* *.o file generated by gcc-4.0.x */
                                /* FIXME: Cannot find any info about this entry. Fix SgAsmElfEHFrameSection::parse() if we
                                 *        ever figure this out. [RPM 2009-09-29] */
                                /*fallthrough*/
                            default: {
                                if (++nwarnings<=WARNING_LIMIT) {
                                    fprintf(stderr, "%s:%u: warning: ELF CIE 0x%08"PRIx64" has unknown PRH encoding 0x%02x\n", 
                                            __FILE__, __LINE__, get_offset()+record_offset, cie->get_prh_encoding());
                                    if (WARNING_LIMIT==nwarnings)
                                        fprintf(stderr, "    (additional frame warnings will be suppressed)\n");
                                }
                                break;
                            }
                        }
                    } else if ('R'==astr[i]) {
                        read_content_local(at++, &u8_disk, 1);
                        cie->set_addr_encoding(u8_disk);
                    } else if ('S'==astr[i]) {
                        /* See http://lkml.indiana.edu/hypermail/linux/kernel/0602.3/1144.html and GCC PR #26208*/
                        cie->set_sig_frame(true);
                    } else {
                        /* Some stuff we don't handle yet. Warn about it and don't read anything. */
                        if (++nwarnings<=WARNING_LIMIT) {
                            fprintf(stderr, "%s:%u: warning: ELF CIE 0x%08"PRIx64" has invalid augmentation string \"%s\"\n", 
                                    __FILE__, __LINE__, get_offset()+record_offset, escapeString(astr).c_str());
                            if (WARNING_LIMIT==nwarnings)
                                fprintf(stderr, "    (additional frame warnings will be suppressed)\n");
                        }
                    }
                }
            }

            /* Initial instructions. These are apparently included in the augmentation_data_length. The final instructions can
             * be zero padding (no-op instructions) to bring the record up to a multiple of the word size. */
            rose_addr_t init_insn_size = (length_field_size + record_size) - (at - record_offset);
            cie->get_instructions() = read_content_local_ucl(at, init_insn_size);
            ROSE_ASSERT(cie->get_instructions().size()==init_insn_size);

        } else {
            /* This is a FDE record */
            rose_addr_t cie_offset = record_offset + length_field_size - cie_back_offset;
            assert(cies.find(cie_offset)!=cies.end());
            SgAsmElfEHFrameEntryCI *cie = cies[cie_offset];
            SgAsmElfEHFrameEntryFD *fde = new SgAsmElfEHFrameEntryFD(cie);

            /* PC Begin (begin_rva) and size */
            switch (cie->get_addr_encoding()) {
              case -1:          /* No address encoding specified */
              case 0x01:
              case 0x03:
              case 0x1b:        /* Address doesn't look valid (e.g., 0xfffd74e8) but still four bytes [RPM 2008-01-16]*/
              {
                  read_content_local(at, &u32_disk, 4); at+=4;
                  fde->set_begin_rva(ByteOrder::le_to_host(u32_disk));
                  read_content_local(at, &u32_disk, 4); at+=4;
                  fde->set_size(ByteOrder::le_to_host(u32_disk));
                  break;
              }
              default:
                fprintf(stderr, "%s:%u: ELF CIE 0x%08"PRIx64", FDE 0x%08"PRIx64": unknown address encoding: 0x%02x\n", 
                        __FILE__, __LINE__, get_offset()+cie_offset, get_offset()+record_offset, cie->get_addr_encoding());
                abort();
            }

            /* Augmentation Data */
            std::string astring = cie->get_augmentation_string();
            if (astring.size()>0 && astring[0]=='z') {
                rose_addr_t aug_length = read_content_local_uleb128(&at);
                fde->get_augmentation_data() = read_content_local_ucl(at, aug_length);
                at += aug_length;
                ROSE_ASSERT(fde->get_augmentation_data().size()==aug_length);
            }

            /* Call frame instructions */
            rose_addr_t cf_insn_size = (length_field_size + record_size) - (at - record_offset);
            fde->get_instructions() = read_content_local_ucl(at, cf_insn_size);
            ROSE_ASSERT(fde->get_instructions().size()==cf_insn_size);
        }

        record_offset += length_field_size + record_size;
    }
    return this;
}