예제 #1
0
static int get_dynamic_tag(Context * ctx, ELF_File * file, int tag, ContextAddress * addr) {
    unsigned i, j;

    for (i = 1; i < file->section_cnt; i++) {
        ELF_Section * sec = file->sections + i;
        if (sec->size == 0) continue;
        if (sec->name == NULL) continue;
        if (strcmp(sec->name, ".dynamic") == 0) {
            ContextAddress sec_addr = elf_map_to_run_time_address(ctx, file, sec, (ContextAddress)sec->addr);
            if (errno) return -1;
            if (elf_load(sec) < 0) return -1;
            if (file->elf64) {
                unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Dyn));
                for (j = 0; j < cnt; j++) {
                    Elf64_Dyn dyn = *((Elf64_Dyn *)sec->data + j);
                    if (file->byte_swap) SWAP(dyn.d_tag);
                    if (dyn.d_tag == DT_NULL) break;
                    if (dyn.d_tag == tag) {
                        if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
                        if (file->byte_swap) {
                            SWAP(dyn.d_tag);
                            SWAP(dyn.d_un.d_ptr);
                        }
                        if (dyn.d_tag != tag) continue;
                        if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
                        return 0;
                    }
                }
            }
            else {
                unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Dyn));
                for (j = 0; j < cnt; j++) {
                    Elf32_Dyn dyn = *((Elf32_Dyn *)sec->data + j);
                    if (file->byte_swap) SWAP(dyn.d_tag);
                    if (dyn.d_tag == DT_NULL) break;
                    if (dyn.d_tag == tag) {
                        if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1;
                        if (file->byte_swap) {
                            SWAP(dyn.d_tag);
                            SWAP(dyn.d_un.d_ptr);
                        }
                        if (dyn.d_tag != tag) continue;
                        if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr;
                        return 0;
                    }
                }
            }
        }
    }
    errno = ENOENT;
    return -1;
}
예제 #2
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];
    }
}
예제 #3
0
static int arm_read_mem(uint32_t addr, uint32_t * res, unsigned size) {
    unsigned i;
    uint8_t buf[4];
    *res = 0;
    assert(size <= 4);
    if (context_read_mem(arm_ctx, addr, buf, size) < 0) return -1;
    for (i = 0; i < size; i++) {
        /* TODO: big-endian support */
        *res |= (uint32_t)buf[i] << (i * 8);
    }
    return 0;
}
예제 #4
0
파일: cpudefs.c 프로젝트: eswartz/emul
uint64_t evaluate_stack_trace_commands(Context * ctx, StackFrame * frame, StackTracingCommandSequence * cmds) {
    static uint64_t * stk = NULL;
    static int stk_size = 0;

    int i;
    int stk_pos = 0;

    for (i = 0; i < cmds->cmds_cnt; i++) {
        StackTracingCommand * cmd = cmds->cmds + i;
        if (stk_pos >= stk_size) {
            stk_size += 4;
            stk = (uint64_t *)loc_realloc(stk, sizeof(uint64_t) * stk_size);
        }
        switch (cmd->cmd) {
        case SFT_CMD_NUMBER:
            stk[stk_pos++] = cmd->num;
            break;
        case SFT_CMD_REGISTER:
            if (read_reg_value(frame, cmd->reg, stk + stk_pos) < 0) exception(errno);
            stk_pos++;
            break;
        case SFT_CMD_FP:
            stk[stk_pos++] = frame->fp;
            break;
        case SFT_CMD_DEREF:
            if (stk_pos < 1) stack_trace_error();
            {
                size_t j;
                size_t size = cmd->size;
                uint64_t n = 0;
                uint8_t buf[8];

                if (context_read_mem(ctx, (ContextAddress)stk[stk_pos - 1], buf, size) < 0) exception(errno);
                for (j = 0; j < size; j++) {
                    n = (n << 8) | buf[cmd->big_endian ? j : size - j - 1];
                }
                stk[stk_pos - 1] = n;
            }
            break;
        case SFT_CMD_ADD:
            if (stk_pos < 2) stack_trace_error();
            stk[stk_pos - 2] = stk[stk_pos - 2] + stk[stk_pos - 1];
            stk_pos--;
            break;
        case SFT_CMD_SUB:
            if (stk_pos < 2) stack_trace_error();
            stk[stk_pos - 2] = stk[stk_pos - 2] - stk[stk_pos - 1];
            stk_pos--;
            break;
        case SFT_CMD_AND:
            if (stk_pos < 2) stack_trace_error();
            stk[stk_pos - 2] = stk[stk_pos - 2] & stk[stk_pos - 1];
            stk_pos--;
            break;
        case SFT_CMD_OR:
            if (stk_pos < 2) stack_trace_error();
            stk[stk_pos - 2] = stk[stk_pos - 2] | stk[stk_pos - 1];
            stk_pos--;
            break;
        default:
            stack_trace_error();
            break;
        }
    }
    if (stk_pos == 0) stack_trace_error();
    return stk[stk_pos - 1];
}
예제 #5
0
int read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, int Attr, PropertyValue * Value) {
    Trap trap;

    memset(Value, 0, sizeof(PropertyValue));
    Value->mContext = Ctx;
    Value->mFrame = Frame;
    Value->mObject = Obj;
    Value->mAttr = Attr;
    Value->mBigEndian = Obj->mCompUnit->mFile->big_endian;

    if (Attr == AT_location && Obj->mLowPC != 0) {
        Value->mValue = Obj->mLowPC;
        return 0;
    }

    sCompUnit = Obj->mCompUnit;
    sCache = (DWARFCache *)sCompUnit->mFile->dwarf_dt_cache;
    sDebugSection = sCompUnit->mSection;
    dio_EnterDebugSection(&sCompUnit->mDesc, sDebugSection, Obj->mID - sDebugSection->addr);
    if (set_trap(&trap)) {
        gop_gAttr = Attr;
        gop_gForm = 0;
        dio_ReadEntry(get_object_property_callback);
        clear_trap(&trap);
    }
    dio_ExitSection();
    sCompUnit = NULL;
    sCache = NULL;
    sDebugSection = NULL;
    if (trap.error) return -1;

    switch (Value->mForm = gop_gForm) {
    case FORM_REF       :
    case FORM_REF_ADDR  :
    case FORM_REF1      :
    case FORM_REF2      :
    case FORM_REF4      :
    case FORM_REF8      :
    case FORM_REF_UDATA :
        {
            ObjectInfo * RefObj = find_object(sCache, gop_gFormRef);
            PropertyValue ValueAddr;

            if (read_and_evaluate_dwarf_object_property(Ctx, Frame, 0, RefObj, AT_location, &ValueAddr) < 0) return -1;
            if (ValueAddr.mAccessFunc != NULL) {
                ValueAddr.mAccessFunc(&ValueAddr, 0, &Value->mValue);
            }
            else {
                static U1_T Buf[8];
                PropertyValue ValueSize;
                ContextAddress Addr;
                size_t Size;

                Addr = (ContextAddress)get_numeric_property_value(&ValueAddr);
                if (read_and_evaluate_dwarf_object_property(Ctx, Frame, Addr, RefObj, AT_byte_size, &ValueSize) < 0) return -1;
                Size = (size_t)get_numeric_property_value(&ValueSize);
                if (Size < 1 || Size > sizeof(Buf)) {
                    errno = ERR_INV_DATA_TYPE;
                    return -1;
                }
                if (context_read_mem(Ctx, Addr, Buf, Size) < 0) return -1;
                check_breakpoints_on_memory_read(Ctx, Addr, Buf, Size);
                Value->mAddr = Buf;
                Value->mSize = Size;
            }
        }
        break;
    case FORM_DATA1     :
    case FORM_DATA2     :
    case FORM_DATA4     :
    case FORM_DATA8     :
    case FORM_FLAG      :
    case FORM_BLOCK1    :
    case FORM_BLOCK2    :
    case FORM_BLOCK4    :
    case FORM_BLOCK     :
        Value->mAddr = gop_gFormDataAddr;
        Value->mSize = gop_gFormDataSize;
        break;
    case FORM_SDATA     :
    case FORM_UDATA     :
        Value->mValue = gop_gFormData;
        break;
    default:
        errno = ENOENT;
        return -1;
    }
    return 0;
}
예제 #6
0
static void safe_memory_get(void * parm) {
    MemoryCommandArgs * args = (MemoryCommandArgs *)parm;
    Channel * c = args->c;
    Context * ctx = args->ctx;

    if (!is_channel_closed(c)) {
        Trap trap;
        if (set_trap(&trap)) {
            OutputStream * out = &args->c->out;
            char * token = args->token;
            ContextAddress addr0 = args->addr;
            ContextAddress addr = args->addr;
            unsigned long size = args->size;
            unsigned long pos = 0;
            char buf[BUF_SIZE];
            int err = 0;
            MemoryErrorInfo err_info;
            JsonWriteBinaryState state;

            memset(&err_info, 0, sizeof(err_info));
            if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED;

            write_stringz(out, "R");
            write_stringz(out, token);

            json_write_binary_start(&state, out, size);
            while (pos < size) {
                int rd = size - pos;
                if (rd > BUF_SIZE) rd = BUF_SIZE;
                /* TODO: word size, mode */
                memset(buf, 0, rd);
                if (err == 0) {
                    if (context_read_mem(ctx, addr, buf, rd) < 0) {
                        err = errno;
#if ENABLE_ExtendedMemoryErrorReports
                        context_get_mem_error_info(&err_info);
#endif
                    }
                    else {
                        addr += rd;
                    }
                }
                json_write_binary_data(&state, buf, rd);
                pos += rd;
            }
            json_write_binary_end(&state);
            write_stream(out, 0);

            write_errno(out, err);
            if (err == 0) {
                write_stringz(out, "null");
            }
            else {
                write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_READ, &err_info);
            }
            write_stream(out, MARKER_EOM);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Exception in Memory.get: %s", errno_to_str(trap.error));
            channel_close(c);
        }
    }
    channel_unlock(c);
    context_unlock(ctx);
    loc_free(args);
}
예제 #7
0
static void disassemble_cache_client(void * x) {
    DisassembleCmdArgs * args = (DisassembleCmdArgs *)x;

    int error = 0;
    Context * ctx = NULL;
    uint8_t * mem_buf = NULL;
    ContextAddress buf_addr = 0;
    ContextAddress buf_size = 0;
    size_t mem_size = 0;
    ByteArrayOutputStream buf;
    OutputStream * buf_out = create_byte_array_output_stream(&buf);
    Channel * c = cache_channel();
    char * data = NULL;
    size_t size = 0;
    ContextISA isa;

    memset(&isa, 0, sizeof(isa));

    ctx = id2ctx(args->id);
    if (ctx == NULL) error = ERR_INV_CONTEXT;
    else if (ctx->exited) error = ERR_ALREADY_EXITED;

    if (!error) check_all_stopped(ctx);

    if (!error) {
        ContextAddress sym_addr = 0;
        ContextAddress sym_size = 0;
        int sym_addr_ok = 0;
        int sym_size_ok = 0;
#if SERVICE_Symbols
        {
            Symbol * sym = NULL;
            if (find_symbol_by_addr(ctx, STACK_NO_FRAME, args->addr, &sym) == 0) {
                if (get_symbol_address(sym, &sym_addr) == 0) sym_addr_ok = 1;
                if (get_symbol_size(sym, &sym_size) == 0) sym_size_ok = 1;
            }
            if (sym_addr_ok && sym_addr <= args->addr) {
                if (args->addr - sym_addr >= 0x1000) {
                    sym_addr_ok = 0;
                    sym_size_ok = 0;
                }
                else if (sym_size_ok && sym_addr + sym_size > args->addr + args->size) {
                    sym_size = args->addr + args->size - sym_addr;
                }
            }
        }
#endif
#if SERVICE_LineNumbers
        if (!sym_addr_ok || !sym_size_ok) {
            CodeArea * area = NULL;
            address_to_line(ctx, args->addr, args->addr + 1, address_to_line_cb, &area);
            if (area != NULL) {
                sym_addr = area->start_address;
                sym_size = area->end_address - area->start_address;
                sym_addr_ok = 1;
                sym_size_ok = 1;
            }
        }
#endif
        if (sym_addr_ok && sym_size_ok && sym_addr <= args->addr && sym_addr + sym_size > args->addr) {
            buf_addr = sym_addr;
            buf_size = sym_size;
            mem_size = (size_t)sym_size;
        }
        else if (sym_addr_ok && sym_addr < args->addr) {
            if (get_isa(ctx, sym_addr, &isa) < 0) {
                error = errno;
            }
            else {
                buf_addr = sym_addr;
                buf_size = args->addr + args->size - sym_addr;
                if (isa.max_instruction_size > 0) {
                    mem_size = (size_t)(buf_size + isa.max_instruction_size);
                }
                else {
                    mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
                }
            }
        }
        else {
            /* Use default address alignment */
            if (get_isa(ctx, args->addr, &isa) < 0) {
                error = errno;
            }
            else {
                if (isa.alignment > 0) {
                    buf_addr = args->addr & ~(ContextAddress)(isa.alignment - 1);
                }
                else {
                    buf_addr = args->addr & ~(ContextAddress)(DEFAULT_ALIGMENT - 1);
                }
                buf_size = args->addr + args->size - buf_addr;
                if (isa.max_instruction_size > 0) {
                    mem_size = (size_t)(buf_size + isa.max_instruction_size);
                }
                else {
                    mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
                }
            }
        }

        if (!error) {
            mem_buf = (uint8_t *)tmp_alloc(mem_size);
            if (context_read_mem(ctx, buf_addr, mem_buf, mem_size) < 0) error = errno;
            if (error) {
#if ENABLE_ExtendedMemoryErrorReports
                MemoryErrorInfo info;
                if (context_get_mem_error_info(&info) == 0 && info.size_valid > 0) {
                    mem_size = info.size_valid;
                    error = 0;
                }
#endif
            }
        }
    }

    if (!error && disassemble_block(
            ctx, buf_out, mem_buf, buf_addr, buf_size,
            mem_size, &isa, args) < 0) error = errno;

    if (get_error_code(error) == ERR_CACHE_MISS) {
        loc_free(buf.mem);
        buf.mem = NULL;
        buf.max = 0;
        buf.pos = 0;
    }

    cache_exit();

    get_byte_array_output_stream_data(&buf, &data, &size);

    if (!is_channel_closed(c)) {
        OutputStream * out = &c->out;
        write_stringz(out, "R");
        write_stringz(out, args->token);
        write_errno(out, error);
        if (size > 0) {
            write_block_stream(out, data, size);
        }
        else {
            write_string(out, "null");
        }
        write_stream(out, 0);
        write_stream(out, MARKER_EOM);
    }

    loc_free(data);
}