示例#1
0
static void read_field(Context * ctx, const Symbol * sym, ContextAddress base, ContextAddress * value) {
    LocationInfo * loc_info = NULL;
    LocationExpressionState * state = NULL;
    uint64_t args[1];
    void * buf = NULL;
    size_t size = 0;
    size_t i;

    args[0] = base;
    if (get_location_info(sym, &loc_info) < 0) exception(errno);
    if (loc_info->args_cnt != 1) str_exception(ERR_OTHER, "Wrong object kind");
    state = evaluate_location_expression(ctx, NULL,
                                         loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, 1);
    if (state->pieces_cnt > 0) {
        read_location_pieces(state->ctx, state->stack_frame,
                             state->pieces, state->pieces_cnt, loc_info->big_endian, &buf, &size);
    }
    else {
        ContextAddress sym_size = 0;
        if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid location expression");
        if (get_symbol_size(sym, &sym_size) < 0) exception(errno);
        size = (size_t)sym_size;
        buf = tmp_alloc(size);
        if (context_read_mem(state->ctx, (ContextAddress)state->stk[0], buf, size) < 0) exception(errno);
    }
    *value = 0;
    for (i = 0; i < size && i < sizeof(ContextAddress); i++) {
        *value = *value << 8;
        *value |= ((uint8_t *)buf)[loc_info->big_endian ? i : size - i - 1];
    }
}
示例#2
0
int ini_server(const char * url, Protocol * p, TCFBroadcastGroup * b) {
    ChannelServer * serv = NULL;
    PeerServer * ps = NULL;
    Trap trap;

    if (!set_trap(&trap)) {
        bcg = NULL;
        proto = NULL;
        if (ps != NULL) peer_server_free(ps);
        errno = trap.error;
        return -1;
    }

    bcg = b;
    proto = p;
    ps = channel_peer_from_url(url);
    if (ps == NULL) str_exception(ERR_OTHER, "Invalid server URL");
    peer_server_addprop(ps, loc_strdup("Name"), loc_strdup(PROXY_NAME));
    peer_server_addprop(ps, loc_strdup("Proxy"), loc_strdup(""));
    SERVER_ADDPROP_HOOK;
    serv = channel_server(ps);
    if (serv == NULL) exception(errno);
    serv->new_conn = channel_new_connection;

    clear_trap(&trap);
    add_channel_redirection_listener(channel_redirection_listener);
    return 0;
}
DWARFCache * get_dwarf_cache(ELF_File * File) {
    DWARFCache * Cache = (DWARFCache *)File->dwarf_dt_cache;
    if (Cache == NULL) {
        Trap trap;
        if (!sCloseListenerOK) {
            elf_add_close_listener(free_dwarf_cache);
            sCloseListenerOK = 1;
        }
        sCache = Cache = (DWARFCache *)(File->dwarf_dt_cache = loc_alloc_zero(sizeof(DWARFCache)));
        sCache->magic = SYM_CACHE_MAGIC;
        sCache->mFile = File;
        sCache->mObjectHash = loc_alloc_zero(sizeof(ObjectInfo *) * OBJ_HASH_SIZE);
        if (set_trap(&trap)) {
            dio_LoadAbbrevTable(File);
            load_symbol_tables();
            load_debug_sections();
            clear_trap(&trap);
        }
        else {
            sCache->mErrorCode = trap.error;
            strncpy(sCache->mErrorMsg, trap.msg, sizeof(sCache->mErrorMsg) - 1);
        }
        sCache = NULL;
    }
    if (Cache->mErrorCode) str_exception(Cache->mErrorCode, Cache->mErrorMsg);
    return Cache;
}
static void load_debug_sections(void) {
    Trap trap;
    unsigned idx;
    ELF_File * File = sCache->mFile;

    memset(&trap, 0, sizeof(trap));
    sSymbolTableLen = sCache->mSymbolTableLen;
    sObjectList = NULL;
    sObjectListTail = NULL;
    sCompUnitsMax = 0;

    for (idx = 1; idx < File->section_cnt; idx++) {
        ELF_Section * sec = File->sections + idx;
        if (sec->size == 0) continue;
        if (sec->name == NULL) continue;
        if (strcmp(sec->name, ".debug") == 0 || strcmp(sec->name, ".debug_info") == 0) {
            sDebugSection = sec;
            sParentObject = NULL;
            sPrevSibling = NULL;
            dio_EnterDebugSection(NULL, sec, 0);
            if (set_trap(&trap)) {
                while (dio_GetPos() < sec->size) {
                    dio_ReadUnit(&sUnitDesc, entry_callback);
                    sCompUnit->mDesc = sUnitDesc;
                }
                clear_trap(&trap);
            }
            dio_ExitSection();
            sParentObject = NULL;
            sPrevSibling = NULL;
            sCompUnit = NULL;
            sDebugSection = NULL;
            if (trap.error) break;
        }
        else if (strcmp(sec->name, ".debug_ranges") == 0) {
            sCache->mDebugRanges = sec;
        }
        else if (strcmp(sec->name, ".debug_aranges") == 0) {
            sCache->mDebugARanges = sec;
        }
        else if (strcmp(sec->name, ".debug_line") == 0) {
            sCache->mDebugLine = sec;
        }
        else if (strcmp(sec->name, ".debug_loc") == 0) {
            sCache->mDebugLoc = sec;
        }
    }

    if (sObjectList == NULL) {
        loc_free(sCache->mObjectHash);
        sCache->mObjectHash = NULL;
    }
    sCache->mObjectList = sObjectList;
    sSymbolTableLen = 0;
    sObjectList = NULL;
    sObjectListTail = NULL;
    sCompUnitsMax = 0;
    if (trap.error) str_exception(trap.error, trap.msg);
}
示例#5
0
static ContextAddress find_module(Context * ctx, ELF_File * exe_file, ELF_File * module,
                                  ContextAddress r_map, ContextAddress r_brk) {
#if ENABLE_Symbols
    Symbol * sym = NULL;
    int i = 0, n = 0;
    Symbol ** children = NULL;
    ContextAddress link = r_map;
    Symbol * sym_l_addr = NULL;
    Symbol * sym_l_next = NULL;
    Symbol * sym_l_tls_modid = NULL;
    if (find_symbol_by_name(ctx, STACK_NO_FRAME, r_brk, "link_map", &sym) < 0)
        str_exception(errno, "Cannot find loader symbol: link_map");
    if (get_symbol_children(sym, &children, &n) < 0) exception(errno);
    for (i = 0; i < n; i++) {
        char * name = NULL;
        if (get_symbol_name(children[i], &name) < 0) exception(errno);
        if (name == NULL) continue;
        if (strcmp(name, "l_map_start") == 0) sym_l_addr = children[i];
        else if (strcmp(name, "l_next") == 0) sym_l_next = children[i];
        else if (strcmp(name, "l_tls_modid") == 0) sym_l_tls_modid = children[i];
    }
    if (sym_l_addr == NULL || sym_l_next == NULL || sym_l_tls_modid == NULL)
        str_exception(ERR_OTHER, "Invalid 'link_map' fields");
    while (link != 0) {
        ContextAddress l_tls_modid = 0;
        read_field(ctx, sym_l_tls_modid, link, &l_tls_modid);
        if (l_tls_modid != 0) {
            ContextAddress l_addr = 0;
            ELF_File * link_file = NULL;
            read_field(ctx, sym_l_addr, link, &l_addr);
            elf_map_to_link_time_address(ctx, l_addr, 0, &link_file, NULL);
            if (link_file != NULL) {
                if (link_file == module) return l_tls_modid;
                if (get_dwarf_file(link_file) == module) return l_tls_modid;
            }
        }
        read_field(ctx, sym_l_next, link, &link);
    }
#endif
    return 0;
}
示例#6
0
ContextAddress get_tls_address(Context * ctx, ELF_File * file) {
    ContextAddress mod_tls_addr = 0;
    RegisterIdScope reg_id_scope;

    memset(&reg_id_scope, 0, sizeof(reg_id_scope));
    reg_id_scope.machine = file->machine;
    reg_id_scope.os_abi = file->os_abi;
    reg_id_scope.elf64 = file->elf64;
    reg_id_scope.big_endian = file->big_endian;
    reg_id_scope.id_type = REGNUM_DWARF;

    switch (file->machine) {
    case EM_X86_64:
    {
        uint8_t buf[8];
        ContextAddress tcb_addr = 0;
        ContextAddress vdt_addr = 0;
        ContextAddress mod_id = 0;
        RegisterDefinition * reg_def = get_reg_by_id(ctx, 58, &reg_id_scope);
        if (reg_def == NULL) exception(errno);
        if (context_read_reg(ctx, reg_def, 0, reg_def->size, buf) < 0)
            str_exception(errno, "Cannot read TCB base register");
        tcb_addr = to_address(buf, reg_def->size, reg_def->big_endian);
        if (elf_read_memory_word(ctx, file, tcb_addr + 8, &vdt_addr) < 0)
            str_exception(errno, "Cannot read TCB");
        mod_id = get_module_id(ctx, file);
        if (elf_read_memory_word(ctx, file, vdt_addr + mod_id * 16, &mod_tls_addr) < 0)
            str_exception(errno, "Cannot read VDT");
        if (mod_tls_addr == 0 || mod_tls_addr == ~(ContextAddress)0)
            str_exception(errno, "Thread local storage is not allocated yet");
    }
    break;
    default:
        str_fmt_exception(ERR_INV_CONTEXT,
                          "Thread local storage access is not supported yet for machine type %d",
                          file->machine);
    }
    return mod_tls_addr;
}
示例#7
0
static ContextAddress get_module_id(Context * ctx, ELF_File * module) {
    ELF_File * exe_file = NULL;
    ContextAddress addr = elf_get_debug_structure_address(ctx, &exe_file);
    size_t word_size = exe_file && exe_file->elf64 ? 8 : 4;
    Trap trap;

    if (addr == 0 || exe_file == NULL) str_exception(ERR_OTHER, "Cannot find loader debug data");
    if (set_trap(&trap)) {
        ContextAddress r_map = 0;
        ContextAddress r_brk = 0;
        ContextAddress mod_id = 0;
        if (elf_read_memory_word(ctx, exe_file, addr + word_size * 1, &r_map) < 0) exception(errno);
        if (elf_read_memory_word(ctx, exe_file, addr + word_size * 2, &r_brk) < 0) exception(errno);
        if (r_map != 0 && r_brk != 0) mod_id = find_module(ctx, exe_file, module, r_map, r_brk);
        clear_trap(&trap);
        if (mod_id) return mod_id;
    }
    else {
        str_exception(trap.error, "Cannot access target ELF loader data");
    }
    str_exception(ERR_OTHER, "Cannot get TLS module ID");
    return 0;
}
示例#8
0
static LONG NTAPI VectoredExceptionHandler(PEXCEPTION_POINTERS x) {
    if (is_dispatch_thread()) {
        DWORD exception_code = x->ExceptionRecord->ExceptionCode;
        if (exception_code == EXCEPTION_IN_PAGE_ERROR) {
            int error = ERR_OTHER;
            if (x->ExceptionRecord->NumberParameters >= 3) {
                ULONG status = (ULONG)x->ExceptionRecord->ExceptionInformation[2];
                if (status != 0) error = set_nt_status_errno(status);
            }
            str_exception(error, "In page error");
        }
    }
    return EXCEPTION_CONTINUE_SEARCH;
}
示例#9
0
static void command_get_cache_client(void * x) {
    GetArgs * args = (GetArgs *)x;
    Channel * c  = cache_channel();
    Trap trap;

    bbf_pos = 0;
    if (set_trap(&trap)) {
        int frame = 0;
        Context * ctx = NULL;
        RegisterDefinition * reg_def = NULL;

        if (id2register(args->id, &ctx, &frame, &reg_def) < 0) exception(errno);
        if (ctx->exited) exception(ERR_ALREADY_EXITED);
        if ((ctx->reg_access & REG_ACCESS_RD_STOP) != 0) {
            check_all_stopped(ctx);
        }
        if ((ctx->reg_access & REG_ACCESS_RD_RUNNING) == 0) {
            if (!ctx->stopped && context_has_state(ctx))
                str_exception(ERR_IS_RUNNING, "Cannot read register if not stopped");
        }
        if (reg_def->size > bbf_len) {
            bbf_len += 0x100 + reg_def->size;
            bbf = (uint8_t *)loc_realloc(bbf, bbf_len);
        }

        bbf_pos = reg_def->size;
        memset(bbf, 0, reg_def->size);
        if (frame < 0 || is_top_frame(ctx, frame)) {
            if (context_read_reg(ctx, reg_def, 0, reg_def->size, bbf) < 0) exception(errno);
        }
        else {
            StackFrame * info = NULL;
            if (get_frame_info(ctx, frame, &info) < 0) exception(errno);
            if (read_reg_bytes(info, reg_def, 0, reg_def->size, bbf) < 0) exception(errno);
        }

        clear_trap(&trap);
    }

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, trap.error);
    json_write_binary(&c->out, bbf, bbf_pos);
    write_stream(&c->out, 0);
    write_stream(&c->out, MARKER_EOM);
}
示例#10
0
static void generate_commands(void) {
    int i;
    RegisterRules * reg;
    RegisterDefinition * reg_def;

    reg = get_reg(&frame_regs, rules.return_address_register);
    if (reg->rule != 0) {
        reg_def = get_reg_by_id(rules.ctx, rules.return_address_register, &rules.reg_id_scope);
        generate_register_commands(reg, get_PC_definition(rules.ctx), reg_def);
    }
    for (i = 0; i < frame_regs.regs_cnt; i++) {
        reg = get_reg(&frame_regs, i);
        if (reg->rule == 0) continue;
        reg_def = get_reg_by_id(rules.ctx, i, &rules.reg_id_scope);
        generate_register_commands(reg, reg_def, reg_def);
    }

    trace_cmds_cnt = 0;
    switch (frame_regs.cfa_rule) {
    case RULE_OFFSET:
        reg_def = get_reg_by_id(rules.ctx, frame_regs.cfa_register, &rules.reg_id_scope);
        if (reg_def != NULL) {
            /* TriCore : PCXI needs to be decyphered so it will point ot the CSA
             * which is an area of the memory where registers were saved.
             */
            if ((rules.reg_id_scope.machine == EM_TRICORE) && (reg_def->dwarf_id == 41))
                add_command(SFT_CMD_RD_REG_PCXI_TRICORE)->args.reg = reg_def;
            else
                add_command(SFT_CMD_RD_REG)->args.reg = reg_def;
            if (frame_regs.cfa_offset != 0) {
                add_command(SFT_CMD_NUMBER)->args.num = frame_regs.cfa_offset;
                add_command(SFT_CMD_ADD);
            }
        }
        break;
    case RULE_EXPRESSION:
        add_dwarf_expression_commands(frame_regs.cfa_expression, frame_regs.cfa_offset);
        break;
    default:
        str_exception(ERR_INV_DWARF, "Invalid .debug_frame");
        break;
    }
    add_command_sequence(&dwarf_stack_trace_fp, NULL);
}
示例#11
0
static void command_set_cache_client(void * x) {
    SetArgs * args = (SetArgs *)x;
    Channel * c  = cache_channel();
    int notify = 0;
    Trap trap;

    if (set_trap(&trap)) {
        int frame = 0;
        Context * ctx = NULL;
        RegisterDefinition * reg_def = NULL;

        if (id2register(args->id, &ctx, &frame, &reg_def) < 0) exception(errno);
        if (frame >= 0 && !is_top_frame(ctx, frame)) exception(ERR_INV_CONTEXT);
        if (ctx->exited) exception(ERR_ALREADY_EXITED);
        if ((ctx->reg_access & REG_ACCESS_WR_STOP) != 0) {
            check_all_stopped(ctx);
        }
        if ((ctx->reg_access & REG_ACCESS_WR_RUNNING) == 0) {
            if (!ctx->stopped && context_has_state(ctx))
                str_exception(ERR_IS_RUNNING, "Cannot write register if not stopped");
        }
        if ((size_t)args->data_len > reg_def->size) exception(ERR_INV_DATA_SIZE);
        if (args->data_len > 0) {
            if (context_write_reg(ctx, reg_def, 0, args->data_len, args->data) < 0) exception(errno);
            notify = 1;
        }
        clear_trap(&trap);
    }

    cache_exit();

    if (notify) send_event_register_changed(args->id);

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, trap.error);
    write_stream(&c->out, MARKER_EOM);

    loc_free(args->data);
}
示例#12
0
文件: dwarfframe.c 项目: eswartz/emul
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;
            }
        }
    }
示例#13
0
static void generate_register_commands(RegisterRules * reg, RegisterDefinition * dst_reg_def, RegisterDefinition * src_reg_def) {
    if (dst_reg_def == NULL) return;
    trace_cmds_cnt = 0;
    switch (reg->rule) {
    case RULE_VAL_OFFSET:
    case RULE_OFFSET:
        add_command(SFT_CMD_FP);
        if (reg->offset != 0) {
            add_command(SFT_CMD_NUMBER)->args.num = reg->offset;
            add_command(SFT_CMD_ADD);
        }
        if (reg->rule == RULE_OFFSET) {
            LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM);
            cmd->args.mem.size = dst_reg_def->size;
            if (cmd->args.mem.size > rules.address_size) cmd->args.mem.size = rules.address_size;
            cmd->args.mem.big_endian = rules.reg_id_scope.big_endian;
        }
        break;
    case RULE_SAME_VALUE:
        if (src_reg_def == NULL) return;
        add_command(SFT_CMD_RD_REG)->args.reg = src_reg_def;
        break;
    case RULE_REGISTER:
        {
            RegisterDefinition * src_sef = get_reg_by_id(rules.ctx, reg->offset, &rules.reg_id_scope);
            if (src_sef != NULL) add_command(SFT_CMD_RD_REG)->args.reg = src_sef;
        }
        break;
    case RULE_EXPRESSION:
    case RULE_VAL_EXPRESSION:
        add_command(SFT_CMD_FP);
        add_dwarf_expression_commands(reg->expression, reg->offset);
        if (reg->rule == RULE_EXPRESSION) {
            LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM);
            cmd->args.mem.size = dst_reg_def->size;
            if (cmd->args.mem.size > rules.address_size) cmd->args.mem.size = rules.address_size;
            cmd->args.mem.big_endian = rules.reg_id_scope.big_endian;
        }
        break;
    default:
        str_exception(ERR_INV_DWARF, "Invalid .debug_frame");
        break;
    }
    if (rules.reg_id_scope.machine == EM_MICROBLAZE &&
            dst_reg_def != NULL && dst_reg_def->dwarf_id == 32 &&
            rules.return_address_register == 15) {
        add_command(SFT_CMD_NUMBER)->args.num = 8;
        add_command(SFT_CMD_ADD);
    }
    if (rules.reg_id_scope.machine == EM_ARM &&
            dst_reg_def != NULL && dst_reg_def->dwarf_id == 15) {
        add_command(SFT_CMD_NUMBER)->args.num = 0xfffffffe;
        add_command(SFT_CMD_AND);
    }
    if (dwarf_stack_trace_regs_cnt >= trace_regs_max) {
        int i;
        trace_regs_max += 16;
        dwarf_stack_trace_regs = (StackFrameRegisterLocation **)loc_realloc(dwarf_stack_trace_regs, trace_regs_max * sizeof(StackFrameRegisterLocation *));
        for (i = dwarf_stack_trace_regs_cnt; i < trace_regs_max; i++) dwarf_stack_trace_regs[i] = NULL;
    }
    if (trace_cmds_cnt == 0) return;
    add_command_sequence(dwarf_stack_trace_regs + dwarf_stack_trace_regs_cnt++, dst_reg_def);
}
示例#14
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");
        }
    }
}
示例#15
0
static void exec_stack_frame_instruction(U8_T func_addr) {
    RegisterRules * reg;
    U1_T op = dio_ReadU1();
    U4_T n;

    switch (op) {
    case CFA_nop:
        break;
    case CFA_set_loc:
        rules.location = read_frame_data_pointer(rules.addr_encoding, &rules.loc_section, func_addr);
        break;
    case CFA_advance_loc1:
        rules.location += dio_ReadU1() * rules.code_alignment;
        break;
    case CFA_advance_loc2:
        rules.location += dio_ReadU2() * rules.code_alignment;
        break;
    case CFA_advance_loc4:
        rules.location += dio_ReadU4() * rules.code_alignment;
        break;
    case CFA_offset_extended:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_OFFSET;
        reg->offset = dio_ReadULEB128() * rules.data_alignment;
        break;
    case CFA_restore_extended:
        n = dio_ReadULEB128();
        reg = get_reg(&frame_regs, n);
        *reg = *get_reg(&cie_regs, n);
        break;
    case CFA_undefined:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        memset(reg, 0, sizeof(*reg));
        break;
    case CFA_same_value:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_SAME_VALUE;
        break;
    case CFA_register:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_REGISTER;
        reg->offset = dio_ReadULEB128();
        break;
    case CFA_remember_state:
        copy_register_rules(get_regs_stack_item(regs_stack_pos++), &frame_regs);
        break;
    case CFA_restore_state:
        if (regs_stack_pos <= 0) {
            str_exception(ERR_INV_DWARF, "Invalid DW_CFA_restore_state instruction");
        }
        copy_register_rules(&frame_regs, get_regs_stack_item(--regs_stack_pos));
        break;
    case CFA_def_cfa:
        frame_regs.cfa_rule = RULE_OFFSET;
        frame_regs.cfa_register = dio_ReadULEB128();
        frame_regs.cfa_offset = dio_ReadULEB128();
        break;
    case CFA_def_cfa_register:
        frame_regs.cfa_rule = RULE_OFFSET;
        frame_regs.cfa_register = dio_ReadULEB128();
        break;
    case CFA_def_cfa_offset:
        frame_regs.cfa_rule = RULE_OFFSET;
        frame_regs.cfa_offset = dio_ReadULEB128();
        break;
    case CFA_def_cfa_expression:
        frame_regs.cfa_rule = RULE_EXPRESSION;
        frame_regs.cfa_offset = dio_ReadULEB128();
        frame_regs.cfa_expression = dio_GetPos();
        dio_Skip(frame_regs.cfa_offset);
        break;
    case CFA_expression:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_EXPRESSION;
        reg->offset = dio_ReadULEB128();
        reg->expression = dio_GetPos();
        dio_Skip(reg->offset);
        break;
    case CFA_offset_extended_sf:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_OFFSET;
        reg->offset = dio_ReadSLEB128() * rules.data_alignment;
        break;
    case CFA_def_cfa_sf:
        frame_regs.cfa_rule = RULE_OFFSET;
        frame_regs.cfa_register = dio_ReadULEB128();
        frame_regs.cfa_offset = dio_ReadSLEB128() * rules.data_alignment;
        break;
    case CFA_def_cfa_offset_sf:
        frame_regs.cfa_rule = RULE_OFFSET;
        frame_regs.cfa_offset = dio_ReadSLEB128() * rules.data_alignment;
        break;
    case CFA_val_offset:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_VAL_OFFSET;
        reg->offset = dio_ReadULEB128() * rules.data_alignment;
        break;
    case CFA_val_offset_sf:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_VAL_OFFSET;
        reg->offset = dio_ReadSLEB128() * rules.data_alignment;
        break;
    case CFA_val_expression:
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_VAL_EXPRESSION;
        reg->offset = dio_ReadULEB128();
        reg->expression = dio_GetPos();
        dio_Skip(reg->offset);
        break;
    case CFA_CFA_GNU_window_save:
        /* SPARC-specific code */
        for (n = 8; n < 16; n++) {
            reg = get_reg(&frame_regs, n);
            reg->rule = RULE_REGISTER;
            reg->offset = n + 16;
        }
        for (n = 16; n < 32; n++) {
            reg = get_reg(&frame_regs, n);
            reg->rule = RULE_OFFSET;
            reg->offset = (n - 16) * (rules.reg_id_scope.machine == EM_SPARCV9 ? 8 : 4);
        }
        break;
    case CFA_GNU_args_size:
        /* This instruction specifies the total size of the arguments
         * which have been pushed onto the stack. Not used by the debugger. */
        dio_ReadULEB128();
        break;
    case CFA_GNU_negative_offset_ext:
        /* This instruction is identical to DW_CFA_offset_extended_sf
         * except that the operand is subtracted to produce the offset. */
        reg = get_reg(&frame_regs, dio_ReadULEB128());
        reg->rule = RULE_OFFSET;
        reg->offset = -dio_ReadSLEB128() * rules.data_alignment;
        break;
    default:
        switch (op >> 6) {
        case 0:
            str_exception(ERR_INV_DWARF, "Unsupported instruction in Call Frame Information");
            break;
        case 1: /* DW_CFA_advance_loc */
            rules.location += (op & 0x3f) * rules.code_alignment;
            break;
        case 2: /* DW_CFA_offset */
            reg = get_reg(&frame_regs, op & 0x3f);
            reg->rule = RULE_OFFSET;
            reg->offset = dio_ReadULEB128() * rules.data_alignment;
            break;
        case 3: /* DW_CFA_restore */
            n = op & 0x3f;
            reg = get_reg(&frame_regs, n);
            *reg = *get_reg(&cie_regs, n);
            break;
        }
    }
}
示例#16
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;
}
示例#17
0
static void relocate(void * r) {
    ElfRelocateFunc * func;
    if (!relocs->file->elf64) {
        if (relocs->type == SHT_REL) {
            Elf32_Rel bf = *(Elf32_Rel *)r;
            if (relocs->file->byte_swap) {
                SWAP(bf.r_offset);
                SWAP(bf.r_info);
            }
            sym_index = ELF32_R_SYM(bf.r_info);
            reloc_type = ELF32_R_TYPE(bf.r_info);
            reloc_addend = 0;
        }
        else {
            Elf32_Rela bf = *(Elf32_Rela *)r;
            if (relocs->file->byte_swap) {
                SWAP(bf.r_offset);
                SWAP(bf.r_info);
                SWAP(bf.r_addend);
            }
            sym_index = ELF32_R_SYM(bf.r_info);
            reloc_type = ELF32_R_TYPE(bf.r_info);
            reloc_addend = bf.r_addend;
        }
        if (sym_index != STN_UNDEF) {
            Elf32_Sym bf = ((Elf32_Sym *)symbols->data)[sym_index];
            if (symbols->file->byte_swap) {
                SWAP(bf.st_name);
                SWAP(bf.st_value);
                SWAP(bf.st_size);
                SWAP(bf.st_info);
                SWAP(bf.st_other);
                SWAP(bf.st_shndx);
            }
            switch (bf.st_shndx) {
            case SHN_ABS:
                sym_value = bf.st_value;
                break;
            case SHN_COMMON:
                str_exception(ERR_INV_FORMAT, "Common relocation record unsupported");
                break;
            case SHN_UNDEF:
                str_exception(ERR_INV_FORMAT, "Invalid relocation record");
                break;
            default:
                if (bf.st_shndx >= symbols->file->section_cnt) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
                if (symbols->file->type != ET_EXEC) {
                    sym_value = (symbols->file->sections + bf.st_shndx)->addr + bf.st_value;
                }
                else {
                    sym_value = bf.st_value;
                }
                *destination_section = symbols->file->sections + bf.st_shndx;
                break;
            }
        }
    }
    else {
        if (relocs->type == SHT_REL) {
            Elf64_Rel bf = *(Elf64_Rel *)r;
            if (relocs->file->byte_swap) {
                SWAP(bf.r_offset);
                SWAP(bf.r_info);
            }
            sym_index = ELF64_R_SYM(bf.r_info);
            reloc_type = ELF64_R_TYPE(bf.r_info);
            reloc_addend = 0;
        }
        else {
            Elf64_Rela bf = *(Elf64_Rela *)r;
            if (relocs->file->byte_swap) {
                SWAP(bf.r_offset);
                SWAP(bf.r_info);
                SWAP(bf.r_addend);
            }
            sym_index = ELF64_R_SYM(bf.r_info);
            reloc_type = ELF64_R_TYPE(bf.r_info);
            reloc_addend = bf.r_addend;
        }
        if (sym_index != STN_UNDEF) {
            Elf64_Sym bf = ((Elf64_Sym *)symbols->data)[sym_index];
            if (symbols->file->byte_swap) {
                SWAP(bf.st_name);
                SWAP(bf.st_value);
                SWAP(bf.st_size);
                SWAP(bf.st_info);
                SWAP(bf.st_other);
                SWAP(bf.st_shndx);
            }
            switch (bf.st_shndx) {
            case SHN_ABS:
                sym_value = bf.st_value;
                break;
            case SHN_COMMON:
                str_exception(ERR_INV_FORMAT, "Common relocation record unsupported");
                break;
            case SHN_UNDEF:
                str_exception(ERR_INV_FORMAT, "Invalid relocation record");
                break;
            default:
                if (bf.st_shndx >= symbols->file->section_cnt) str_exception(ERR_INV_FORMAT, "Invalid relocation record");
                if (symbols->file->type != ET_EXEC) {
                    sym_value = (symbols->file->sections + bf.st_shndx)->addr + bf.st_value;
                }
                else {
                    sym_value = bf.st_value;
                }
                *destination_section = symbols->file->sections + bf.st_shndx;
                break;
            }
        }
    }

    /* For executable file we don't need to apply the relocation,
     * all we need is destination_section */
    if (section->file->type != ET_REL) return;

    func = elf_relocate_funcs;
    while (func->machine != section->file->machine) {
        if (func->func == NULL) str_exception(ERR_INV_FORMAT, "Unsupported ELF machine code");
        func++;
    }
    func->func();
}
示例#18
0
int elf_enumerate_symbols (Context * ctx, const char * file_name, EnumerateSymbols ** enum_syms, EnumerateBatchSymbolsCallBack * call_back, void * args) {
    Trap trap;
    ELF_File * file;
    unsigned sec_idx;
    int has_more = 0;

    if (!set_trap(&trap)) {
        loc_free (*enum_syms);
        *enum_syms = NULL;
        return -1;
    }

    if (ctx == NULL && file_name == NULL) {
        assert (*enum_syms != NULL);

        file = elf_open ((*enum_syms)->file_name);
        if (file == NULL) exception (errno);

        /*
         * Check that the file is identical to the initial file and the context
         * still exists.
         */

        if (file->ino != (*enum_syms)->ino || file->dev != (*enum_syms)->dev || file->mtime != (*enum_syms)->mtime) {
            str_exception(ERR_OTHER, "The elf symbol file has changed");
        }
        else {
            ctx = id2ctx((*enum_syms)->ctxId);
            if (ctx == NULL) exception (ERR_INV_CONTEXT);
            else if (ctx->exited) exception (ERR_ALREADY_EXITED);
        }
        sec_idx = (*enum_syms)->sec_idx;
    }
    else {
        unsigned symtab_idx = 0;
        unsigned dynsym_idx = 0;
        unsigned ix;

        assert (file_name != NULL && enum_syms != NULL && *enum_syms == NULL);

        file = elf_open (file_name);
        if (file == NULL) exception (errno);

        if (file->sections == NULL) str_exception(ERR_OTHER, "The file does not have sections");

        /* Look for the symbol table sections */

        for (ix = 0; ix < file->section_cnt && (symtab_idx == 0 || dynsym_idx == 0); ix++) {
            ELF_Section * sec = file->sections + ix;
            if (sec->type == SHT_SYMTAB) symtab_idx = ix;
            else if (sec->type == SHT_DYNSYM) dynsym_idx = ix;
        }

        if (symtab_idx == 0 && dynsym_idx == 0) str_exception(ERR_OTHER, "The file does not have a symbol table");

       /* Set priority to the symbol table */

        if (symtab_idx != 0) sec_idx = symtab_idx;
        else sec_idx = dynsym_idx;

        *enum_syms = (EnumerateSymbols *)loc_alloc_zero (sizeof (EnumerateSymbols));
        strlcpy ((*enum_syms)->file_name, file_name, sizeof ((*enum_syms)->file_name));
        if (strlen (file_name) != strlen ((*enum_syms)->file_name)) str_exception (ERR_OTHER, "File pathname too long");

        strlcpy ((*enum_syms)->ctxId, ctx->id, sizeof ((*enum_syms)->ctxId));
        (*enum_syms)->dev = file->dev;
        (*enum_syms)->ino = file->ino;
        (*enum_syms)->mtime = file->mtime;
        (*enum_syms)->sec_idx = sec_idx;
    }

    has_more = enumerate_symbol_table(ctx, file->sections + sec_idx, *enum_syms, call_back, args);

    clear_trap(&trap);

    if (has_more == 0) {
        loc_free (*enum_syms);
        *enum_syms = NULL;
    }

    return has_more;
}
void load_line_numbers(DWARFCache * Cache, CompUnit * Unit) {
    Trap trap;
    if (Unit->mFiles != NULL && Unit->mDirs != NULL) return;
    if (elf_load(Cache->mDebugLine)) exception(errno);
    dio_EnterDataSection(&Unit->mDesc, Cache->mDebugLine->data, Unit->mLineInfoOffs, Cache->mDebugLine->size);
    if (set_trap(&trap)) {
        U8_T header_pos = 0;
        U1_T opcode_base = 0;
        U1_T opcode_size[256];
        U8_T header_size = 0;
        U1_T min_instruction_length = 0;
        U1_T is_stmt_default = 0;
        I1_T line_base = 0;
        U1_T line_range = 0;
        U8_T unit_size = 0;
        int dwarf64 = 0;
        LineNumbersState state;

        /* Read header */
        unit_size = dio_ReadU4();
        if (unit_size == 0xffffffffu) {
            unit_size = dio_ReadU8();
            unit_size += 12;
            dwarf64 = 1;
        }
        else {
            unit_size += 4;
        }
        dio_ReadU2(); /* line info version */
        header_size = dwarf64 ? dio_ReadU8() : (U8_T)dio_ReadU4();
        header_pos = dio_GetPos();
        min_instruction_length = dio_ReadU1();
        is_stmt_default = dio_ReadU1() != 0;
        line_base = (I1_T)dio_ReadU1();
        line_range = dio_ReadU1();
        opcode_base = dio_ReadU1();
        memset(opcode_size, 0, sizeof(opcode_size));
        dio_Read(opcode_size + 1, opcode_base - 1);

        /* Read directory names */
        for (;;) {
            char * Name = dio_ReadString();
            if (Name == NULL) break;
            add_dir(Unit, Name);
        }

        /* Read source sFileLocks info */
        for (;;) {
            U4_T dir = 0;
            FileInfo File;
            memset(&File, 0, sizeof(File));
            File.mName = dio_ReadString();
            if (File.mName == NULL) break;
            dir = dio_ReadULEB128();
            if (dir > 0 && dir <= Unit->mDirsCnt) File.mDir = Unit->mDirs[dir - 1];
            File.mModTime = dio_ReadULEB128();
            File.mSize = dio_ReadULEB128();
            add_file(Unit, &File);
        }

        /* Run the program */
        if (header_pos + header_size != dio_GetPos())
            str_exception(ERR_INV_DWARF, "Invalid line info header");
        memset(&state, 0, sizeof(state));
        state.mFile = 1;
        state.mLine = 1;
        if (is_stmt_default) state.mFlags |= LINE_IsStmt;
        while (dio_GetPos() < Unit->mLineInfoOffs + unit_size) {
            U1_T opcode = dio_ReadU1();
            if (opcode >= opcode_base) {
                state.mLine += (unsigned)((int)((opcode - opcode_base) % line_range) + line_base);
                state.mAddress += (opcode - opcode_base) / line_range * min_instruction_length;
                add_state(Unit, &state);
                state.mFlags &= ~(LINE_BasicBlock | LINE_PrologueEnd | LINE_EpilogueBegin);
            }
            else if (opcode == 0) {
                U4_T op_size = dio_ReadULEB128();
                U8_T op_pos = dio_GetPos();
                switch (dio_ReadU1()) {
                case DW_LNE_define_file: {
                    U4_T dir = 0;
                    FileInfo File;
                    memset(&File, 0, sizeof(File));
                    File.mName = dio_ReadString();
                    dir = dio_ReadULEB128();
                    if (dir > 0 && dir <= Unit->mDirsCnt) File.mDir = Unit->mDirs[dir - 1];
                    File.mModTime = dio_ReadULEB128();
                    File.mSize = dio_ReadULEB128();
                    add_file(Unit, &File);
                    break;
                }
                case DW_LNE_end_sequence:
                    state.mFlags |= LINE_EndSequence;
                    add_state(Unit, &state);
                    memset(&state, 0, sizeof(state));
                    state.mFile = 1;
                    state.mLine = 1;
                    if (is_stmt_default) state.mFlags |= LINE_IsStmt;
                    else state.mFlags &= ~LINE_IsStmt;
                    break;
                case DW_LNE_set_address:
                    state.mAddress = (ContextAddress)dio_ReadAddress();
                    break;
                default:
                    dio_Skip(op_size - 1);
                    break;
                }
                if (dio_GetPos() != op_pos + op_size)
                    str_exception(ERR_INV_DWARF, "Invalid line info op size");
            }
            else {
                switch (opcode) {
                case DW_LNS_copy:
                    add_state(Unit, &state);
                    state.mFlags &= ~(LINE_BasicBlock | LINE_PrologueEnd | LINE_EpilogueBegin);
                    break;
                case DW_LNS_advance_pc:
                    state.mAddress += (ContextAddress)(dio_ReadU8LEB128() * min_instruction_length);
                    break;
                case DW_LNS_advance_line:
                    state.mLine += dio_ReadSLEB128();
                    break;
                case DW_LNS_set_file:
                    state.mFile = dio_ReadULEB128();
                    break;
                case DW_LNS_set_column:
                    state.mColumn = dio_ReadULEB128();
                    break;
                case DW_LNS_negate_stmt:
                    state.mFlags ^= LINE_IsStmt;
                    break;
                case DW_LNS_set_basic_block:
                    state.mFlags |= LINE_BasicBlock;
                    break;
                case DW_LNS_const_add_pc:
                    state.mAddress += (255 - opcode_base) / line_range * min_instruction_length;
                    break;
                case DW_LNS_fixed_advance_pc:
                    state.mAddress += dio_ReadU2();
                    break;
                case DW_LNS_set_prologue_end:
                    state.mFlags |= LINE_PrologueEnd;
                    break;
                case DW_LNS_set_epilogue_begin:
                    state.mFlags |= LINE_EpilogueBegin;
                    break;
                case DW_LNS_set_isa:
                    state.mISA = (U1_T)dio_ReadULEB128();
                    break;
                default:
                    str_exception(ERR_INV_DWARF, "Invalid line info op code");
                    break;
                }
            }
        }
        dio_ExitSection();
        clear_trap(&trap);
    }
    else {
        dio_ExitSection();
        free_unit_cache(Unit);
        str_exception(trap.error, trap.msg);
    }
}
示例#20
0
static void read_frame_cie(U8_T fde_pos, U8_T pos) {
    int cie_dwarf64 = 0;
    U8_T saved_pos = dio_GetPos();
    U8_T cie_length = 0;
    U8_T cie_end = 0;

    rules.cie_pos = pos;
    if (pos >= rules.section->size) {
        str_fmt_exception(ERR_INV_DWARF,
            "Invalid CIE pointer 0x%" PRIX64
            " in FDE at 0x%" PRIX64, pos, fde_pos);
    }
    dio_SetPos(pos);
    cie_length = dio_ReadU4();
    if (cie_length == ~(U4_T)0) {
        cie_length = dio_ReadU8();
        cie_dwarf64 = 1;
    }
    cie_end = dio_GetPos() + cie_length;
    dio_Skip(cie_dwarf64 ? 8 : 4);
    rules.version = dio_ReadU1();
    if (rules.version != 1 && rules.version != 3 && rules.version != 4) {
        str_fmt_exception(ERR_INV_DWARF,
            "Unsupported version of Call Frame Information: %d", rules.version);
    }
    rules.cie_aug = dio_ReadString();
    if (rules.cie_aug != NULL && strcmp(rules.cie_aug, "eh") == 0) {
        rules.cie_eh_data = dio_ReadAddress(&rules.cie_eh_data_section);
    }
    if (rules.version >= 4) {
        rules.address_size = dio_ReadU1();
        rules.segment_size = dio_ReadU1();
    }
    else {
        rules.address_size = rules.section->file->elf64 ? 8 : 4;
        rules.segment_size = 0;
    }
    if (rules.segment_size != 0) {
        str_exception(ERR_INV_DWARF,
            "Unsupported Call Frame Information: segment size != 0");
    }
    rules.code_alignment = dio_ReadULEB128();
    rules.data_alignment = dio_ReadSLEB128();
    rules.return_address_register = dio_ReadULEB128();

    rules.lsda_encoding = 0;
    rules.prh_encoding = 0;
    rules.addr_encoding = 0;
    if (rules.cie_aug != NULL && rules.cie_aug[0] == 'z') {
        U4_T aug_length = dio_ReadULEB128();
        U8_T aug_pos = dio_GetPos();
        char * p = rules.cie_aug + 1;
        while (*p) {
            switch (*p++) {
            case 'L':
                rules.lsda_encoding = dio_ReadU1();
                break;
            case 'P':
                {
                    Trap trap;
                    U8_T addr_pos;
                    rules.prh_encoding = dio_ReadU1();
                    addr_pos = dio_GetPos();
                    if (set_trap(&trap)) {
                        read_frame_data_pointer(rules.prh_encoding, NULL, 0);
                        clear_trap(&trap);
                    }
                    else {
                        dio_SetPos(addr_pos + rules.address_size);
                    }
                }
                break;
            case 'R':
                rules.addr_encoding = dio_ReadU1();
                break;
            }
        }
        dio_SetPos(aug_pos + aug_length);
    }
    clear_frame_registers(&cie_regs);
    clear_frame_registers(&frame_regs);
    regs_stack_pos = 0;
    while (dio_GetPos() < cie_end) {
        exec_stack_frame_instruction(0);
    }
    copy_register_rules(&cie_regs, &frame_regs);
    dio_SetPos(saved_pos);
}
示例#21
0
文件: cpudefs.c 项目: eswartz/emul
static void stack_trace_error(void) {
    str_exception(ERR_OTHER, "Invalid stack trace program");
}
示例#22
0
void drl_relocate(ELF_Section * s, U8_T offset, void * buf, size_t size, ELF_Section ** dst) {
    unsigned i;
    ELF_Section * d = NULL;

    if (dst == NULL) dst = &d;
    else *dst = NULL;
    if (!s->relocate) return;

    section = s;
    destination_section = dst;
    reloc_offset = offset;
    data_buf = buf;
    data_size = size;
    for (i = 1; i < s->file->section_cnt; i++) {
        ELF_Section * r = s->file->sections + i;
        if (r->size == 0) continue;
        if (r->type != SHT_REL && r->type != SHT_RELA) continue;
        if (r->info == s->index) {
            uint8_t * p;
            uint8_t * q;
            unsigned ix;
            relocs = r;
            symbols = s->file->sections + r->link;
            if (elf_load(relocs) < 0) exception(errno);
            if (elf_load(symbols) < 0) exception(errno);
            if (r->entsize == 0 || r->size % r->entsize != 0) str_exception(ERR_INV_FORMAT, "Invalid sh_entsize");

            if (r->reloc_num_zones == 0) {
                U8_T prev_offs = 0;
                unsigned max_bondaries = 2; /* default is two bondaries ... */
                r->reloc_num_zones = 1; /* ... for one zone */
                r->reloc_zones_bondaries = (unsigned *)loc_alloc_zero(sizeof (unsigned) * max_bondaries);
                r->reloc_zones_bondaries[0] = 0;  /* first zone starting index */
                for (ix = 0; ix < r->size / r->entsize; ix++) {
                    U8_T offs;
                    uint8_t * x = (uint8_t *)r->data + ix * r->entsize;
                    if (r->file->elf64) {
                        offs = *(U8_T *)x;
                        if (r->file->byte_swap) SWAP(offs);
                    }
                    else {
                        U4_T offs4 = *(U4_T *)x;
                        if (r->file->byte_swap) SWAP(offs4);
                        offs = offs4;
                    }
                    if (offs < prev_offs) {
                        /*
                         * Relocation offsets are not ordered. Store the start
                         * index of the new zone.
                         */
                        if ((r->reloc_num_zones + 1) == max_bondaries) {
                            max_bondaries += 5;
                            r->reloc_zones_bondaries =
                                (unsigned *)loc_realloc(r->reloc_zones_bondaries,
                                sizeof (unsigned) * max_bondaries);
                        }
                        r->reloc_zones_bondaries[r->reloc_num_zones++] = ix;
                    }
                    prev_offs = offs;
                }
                /* Store the last zone boundary index */
                r->reloc_zones_bondaries[r->reloc_num_zones] = ix;
                if (r->reloc_num_zones > 1) {
                    trace(LOG_ELF, "ELF relocations are not ordered; the performances "\
                                   "may be degraded.");
                }
                /*
                 * As we parsed the relocation section, it would be possible to
                 * localize the searched offset at the same time, to optimize the
                 * first lookup. But I don't know if it worth it, compare to some
                 * code duplication with the rest of the routine below.
                 */
            }

            /* Perform a dichotomic look up for each ordered area */

            for (ix = 0; ix < r->reloc_num_zones; ix++) {
                p = (uint8_t *)r->data + r->reloc_zones_bondaries[ix] * r->entsize;
                q = (uint8_t *)r->data + r->reloc_zones_bondaries[ix + 1] * r->entsize;
                while (p < q) {
                    unsigned n = (q - p) / r->entsize / 2;
                    uint8_t * x = p + n * r->entsize;
                    assert(x < q);
                    if (r->file->elf64) {
                        U8_T offs = *(U8_T *)x;
                        if (r->file->byte_swap) SWAP(offs);
                        if (s->file->type != ET_REL) offs -= s->addr;
                        if (offset > offs) {
                            p = x + r->entsize;
                            continue;
                        }
                        if (offset < offs) {
                            q = x;
                            continue;
                        }
                    }
                    else {
                        U4_T offs = *(U4_T *)x;
                        if (r->file->byte_swap) SWAP(offs);
                        if (s->file->type != ET_REL) offs -= (U4_T)s->addr;
                        if (offset > offs) {
                            p = x + r->entsize;
                            continue;
                        }
                        if (offset < offs) {
                            q = x;
                            continue;
                        }
                    }
                    relocate(x);
                    return;
                }
            }
        }
    }
}