Esempio n. 1
0
static U8_T read_frame_data_pointer(U1_T encoding, ELF_Section ** sec, U8_T func_addr) {
    U8_T v = 0;
    U8_T pos;
    unsigned idx;
    ELF_File * file;

    if (encoding == EH_PE_omit) return 0;
    pos = dio_GetPos();
    /* Decode the base or adjust the offset */
    switch ((encoding >> 4) & 0x7) {
    case 0:
    case EH_PB_funcrel:
        v = func_addr;
        break;
    case EH_PB_pcrel:
        if (sec != NULL) {
            v = pos + rules.section->addr;
        }
        break;
    case EH_PB_datarel:
        if (sec != NULL) {
            v = rules.section->addr;
        }
        break;
    case EH_PB_textrel:
        if (sec != NULL && rules.text_section != NULL) {
            v = rules.text_section->addr;
        }
        break;
    case EH_PB_aligned:
        if ((pos % rules.address_size) != 0) dio_SetPos(pos + (rules.address_size - (pos % rules.address_size)));
        break;
    default:
        str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers");
        break;
    }
    /* Decode the value */
    switch (encoding & 0xf) {
    case EH_PE_absptr:
        v += dio_ReadAddress(sec);
        break;
    case EH_PE_uleb128:
        v += dio_ReadU8LEB128();
        break;
    case EH_PE_udata2:
        v += dio_ReadAddressX(sec, 2);
        break;
    case EH_PE_udata4:
        v += dio_ReadAddressX(sec, 4);
        break;
    case EH_PE_udata8:
        v += dio_ReadAddressX(sec, 8);
        break;
    case EH_PE_sleb128:
        v += dio_ReadS8LEB128();
        break;
    case EH_PE_sdata2:
        v += (I2_T)dio_ReadAddressX(sec, 2);
        break;
    case EH_PE_sdata4:
        v += (I4_T)dio_ReadAddressX(sec, 4);
        break;
    case EH_PE_sdata8:
        v += (I8_T)dio_ReadAddressX(sec, 8);
        break;
    default:
        str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers");
        break;
    }
    if (encoding & EH_PE_indirect) {
        size_t size = rules.address_size;
        U8_T res = 0;
        file = rules.section->file;
        for (idx = 1; idx < file->section_cnt; idx++) {
            ELF_Section * sec = file->sections + idx;
            if ((sec->flags & SHF_ALLOC) == 0) continue;
            if (sec->addr <= v && sec->addr + sec->size >= v + size) {
                U1_T * p;
                size_t i;
                if (sec->data == NULL && elf_load(sec) < 0) exception(errno);
                p = (U1_T *)sec->data + (uintptr_t)(v - sec->addr);
                for (i = 0; i < size; i++) {
                    res = (res << 8) | p[file->big_endian ? i : size - i - 1];
                }
                break;
            }
        }
        v = res;
    }
    return v;
}
Esempio n. 2
0
static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
    dio_EnterSection(NULL, rules.section, cmds_offs);
    while (dio_GetPos() < cmds_offs + cmds_size) {
        U1_T op = dio_ReadU1();

        switch (op) {
        case OP_addr:
            {
                ELF_Section * section = NULL;
                U8_T lt_addr = dio_ReadAddress(&section);
                ContextAddress rt_addr = elf_map_to_run_time_address(
                    rules.ctx, rules.section->file, section, (ContextAddress)lt_addr);
                if (errno) str_exception(errno, "Cannot get object run-time address");
                add_command(SFT_CMD_NUMBER)->args.num = rt_addr;
            }
            break;
        case OP_deref:
            {
                LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM);
                cmd->args.mem.size = rules.address_size;
                cmd->args.mem.big_endian = rules.reg_id_scope.big_endian;
            }
            break;
        case OP_deref_size:
            {
                LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM);
                cmd->args.mem.size = dio_ReadU1();
                cmd->args.mem.big_endian = rules.reg_id_scope.big_endian;
            }
            break;
        case OP_const1u:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU1();
            break;
        case OP_const1s:
            add_command(SFT_CMD_NUMBER)->args.num = (I1_T)dio_ReadU1();
            break;
        case OP_const2u:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU2();
            break;
        case OP_const2s:
            add_command(SFT_CMD_NUMBER)->args.num = (I2_T)dio_ReadU2();
            break;
        case OP_const4u:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU4();
            break;
        case OP_const4s:
            add_command(SFT_CMD_NUMBER)->args.num = (I4_T)dio_ReadU4();
            break;
        case OP_const8u:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8();
            break;
        case OP_const8s:
            add_command(SFT_CMD_NUMBER)->args.num = (I8_T)dio_ReadU8();
            break;
        case OP_constu:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128();
            break;
        case OP_consts:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadS8LEB128();
            break;
        case OP_and:
            add_command(SFT_CMD_AND);
            break;
        case OP_minus:
            add_command(SFT_CMD_SUB);
            break;
        case OP_or:
            add_command(SFT_CMD_OR);
            break;
        case OP_plus:
            add_command(SFT_CMD_ADD);
            break;
        case OP_plus_uconst:
            add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128();
            add_command(SFT_CMD_ADD);
            break;
        case OP_ge:
            add_command(SFT_CMD_GE);
            break;
        case OP_gt:
            add_command(SFT_CMD_GT);
            break;
        case OP_le:
            add_command(SFT_CMD_LE);
            break;
        case OP_lt:
            add_command(SFT_CMD_LT);
            break;
        case OP_shl:
            add_command(SFT_CMD_SHL);
            break;
        case OP_lit0:
        case OP_lit1:
        case OP_lit2:
        case OP_lit3:
        case OP_lit4:
        case OP_lit5:
        case OP_lit6:
        case OP_lit7:
        case OP_lit8:
        case OP_lit9:
        case OP_lit10:
        case OP_lit11:
        case OP_lit12:
        case OP_lit13:
        case OP_lit14:
        case OP_lit15:
        case OP_lit16:
        case OP_lit17:
        case OP_lit18:
        case OP_lit19:
        case OP_lit20:
        case OP_lit21:
        case OP_lit22:
        case OP_lit23:
        case OP_lit24:
        case OP_lit25:
        case OP_lit26:
        case OP_lit27:
        case OP_lit28:
        case OP_lit29:
        case OP_lit30:
        case OP_lit31:
            add_command(SFT_CMD_NUMBER)->args.num = op - OP_lit0;
            break;
        case OP_reg0:
        case OP_reg1:
        case OP_reg2:
        case OP_reg3:
        case OP_reg4:
        case OP_reg5:
        case OP_reg6:
        case OP_reg7:
        case OP_reg8:
        case OP_reg9:
        case OP_reg10:
        case OP_reg11:
        case OP_reg12:
        case OP_reg13:
        case OP_reg14:
        case OP_reg15:
        case OP_reg16:
        case OP_reg17:
        case OP_reg18:
        case OP_reg19:
        case OP_reg20:
        case OP_reg21:
        case OP_reg22:
        case OP_reg23:
        case OP_reg24:
        case OP_reg25:
        case OP_reg26:
        case OP_reg27:
        case OP_reg28:
        case OP_reg29:
        case OP_reg30:
        case OP_reg31:
            {
                RegisterDefinition * def = get_reg_by_id(rules.ctx, op - OP_reg0, &rules.reg_id_scope);
                if (def == NULL) str_exception(errno, "Cannot read DWARF frame info");
                add_command(SFT_CMD_RD_REG)->args.reg = def;
            }
            break;
        case OP_regx:
            {
                unsigned n = (unsigned)dio_ReadULEB128();
                RegisterDefinition * def = get_reg_by_id(rules.ctx, n, &rules.reg_id_scope);
                if (def == NULL) str_exception(errno, "Cannot read DWARF frame info");
                add_command(SFT_CMD_RD_REG)->args.reg = def;
            }
            break;
        case OP_breg0:
        case OP_breg1:
        case OP_breg2:
        case OP_breg3:
        case OP_breg4:
        case OP_breg5:
        case OP_breg6:
        case OP_breg7:
        case OP_breg8:
        case OP_breg9:
        case OP_breg10:
        case OP_breg11:
        case OP_breg12:
        case OP_breg13:
        case OP_breg14:
        case OP_breg15:
        case OP_breg16:
        case OP_breg17:
        case OP_breg18:
        case OP_breg19:
        case OP_breg20:
        case OP_breg21:
        case OP_breg22:
        case OP_breg23:
        case OP_breg24:
        case OP_breg25:
        case OP_breg26:
        case OP_breg27:
        case OP_breg28:
        case OP_breg29:
        case OP_breg30:
        case OP_breg31:
            {
                I8_T offs = dio_ReadS8LEB128();
                RegisterDefinition * def = get_reg_by_id(rules.ctx, op - OP_breg0, &rules.reg_id_scope);
                if (def == NULL) str_exception(errno, "Cannot read DWARF frame info");
                add_command(SFT_CMD_RD_REG)->args.reg = def;
                if (offs != 0) {
                    add_command(SFT_CMD_NUMBER)->args.num = offs;
                    add_command(SFT_CMD_ADD);
                }
            }
            break;
        case OP_bregx:
            {
                unsigned n = (unsigned)dio_ReadULEB128();
                I8_T offs = dio_ReadS8LEB128();
                RegisterDefinition * def = get_reg_by_id(rules.ctx, n, &rules.reg_id_scope);
                if (def == NULL) str_exception(errno, "Cannot read DWARF frame info");
                add_command(SFT_CMD_RD_REG)->args.reg = def;
                if (offs != 0) {
                    add_command(SFT_CMD_NUMBER)->args.num = offs;
                    add_command(SFT_CMD_ADD);
                }
            }
            break;
        case OP_nop:
            break;
        default:
            trace(LOG_ALWAYS, "Unsupported DWARF expression op 0x%02x", op);
            str_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op");
        }
    }
}
Esempio n. 3
0
static U8_T read_frame_data_pointer(U1_T encoding, ELF_Section ** sec) {
    U8_T v = 0;
    if (encoding != EH_PE_omit) {
        U8_T pos = dio_GetPos();
        switch (encoding & 0xf) {
        case EH_PE_absptr:
            v = dio_ReadAddress(sec);
            break;
        case EH_PE_uleb128:
            v = dio_ReadU8LEB128();
            break;
        case EH_PE_udata2:
            v = dio_ReadU2();
            break;
        case EH_PE_udata4:
            v = dio_ReadU4();
            break;
        case EH_PE_udata8:
            v = dio_ReadU8();
            break;
        case EH_PE_sleb128:
            v = dio_ReadS8LEB128();
            break;
        case EH_PE_sdata2:
            v = (I2_T)dio_ReadU2();
            break;
        case EH_PE_sdata4:
            v = (I4_T)dio_ReadU4();
            break;
        case EH_PE_sdata8:
            v = (I8_T)dio_ReadU8();
            break;
        default:
            str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers");
            break;
        }
        if (v != 0 && sec != NULL) {
            switch ((encoding >> 4) & 0x7) {
            case 0:
                break;
            case EH_PB_pcrel:
                *sec = rules.section;
                v += rules.section->addr + pos;
                break;
            case EH_PB_datarel:
                *sec = rules.section;
                v += rules.section->addr;
                break;
            case EH_PB_textrel:
            case EH_PB_funcrel:
            case EH_PB_aligned:
            default:
                str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers");
                break;
            }
            if (encoding & EH_PE_indirect) {
                unsigned idx;
                ELF_File * file = rules.section->file;
                size_t size = rules.address_size;
                U8_T res = 0;
                for (idx = 1; idx < file->section_cnt; idx++) {
                    ELF_Section * sec = file->sections + idx;
                    if ((sec->flags & SHF_ALLOC) == 0) continue;
                    if (sec->addr <= v && sec->addr + sec->size >= v + size) {
                        U1_T * p;
                        size_t i;
                        if (sec->data == NULL && elf_load(sec) < 0) exception(errno);
                        p = (U1_T *)sec->data + (uintptr_t)(v - sec->addr);
                        for (i = 0; i < size; i++) {
                            res = (res << 8) | p[file->big_endian ? i : size - i - 1];
                        }
                        break;
                    }
                }
                v = res;
            }
        }
    }