static int arm_read_reg(unsigned n, uint32_t * res) { unsigned i; uint8_t buf[4]; *res = 0; assert(regs_index[n].size == 4); assert(!regs_index[n].big_endian); if (context_read_reg(arm_ctx, regs_index + n, 0, 4, buf) < 0) return -1; for (i = 0; i < 4; i++) *res |= (uint32_t)buf[i] << (i * 8); return 0; }
static int read_reg(Context *ctx, RegisterDefinition * def, size_t size, ContextAddress * addr) { size_t i; uint8_t buf[8]; uint64_t n = 0; *addr = 0; assert(!def->big_endian); assert(size <= def->size); assert(size <= sizeof(buf)); if (context_read_reg(ctx, def, 0, size, buf) < 0) return -1; for (i = 0; i < size; i++) n |= (uint64_t)buf[i] << (i * 8); *addr = (ContextAddress)n; return 0; }
ContextAddress get_regs_PC(Context * ctx) { size_t i; uint8_t buf[8]; ContextAddress pc = 0; RegisterDefinition * def = get_PC_definition(ctx); if (def == NULL) return 0; assert(def->size <= sizeof(buf)); if (context_read_reg(ctx, def, 0, def->size, buf) < 0) return 0; for (i = 0; i < def->size; i++) { pc = pc << 8; pc |= buf[def->big_endian ? i : def->size - i - 1]; } return pc; }
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, ®_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); }
static void command_getm_cache_client(void * x) { GetmArgs * args = (GetmArgs *)x; Channel * c = cache_channel(); Trap trap; bbf_pos = 0; if (bbf == NULL) bbf = (uint8_t *)loc_alloc(bbf_len = 0x100); if (set_trap(&trap)) { unsigned locs_pos = 0; check_location_list(args->locs, args->locs_cnt, 0); while (locs_pos < args->locs_cnt) { Location * l = args->locs + locs_pos++; if (bbf_pos + l->size > bbf_len) { bbf_len += 0x100 + l->size; bbf = (uint8_t *)loc_realloc(bbf, bbf_len); } memset(bbf + bbf_pos, 0, l->size); if (l->frame_info == NULL) { if (context_read_reg(l->ctx, l->reg_def, l->offs, l->size, bbf + bbf_pos) < 0) exception(errno); } else { if (read_reg_bytes(l->frame_info, l->reg_def, l->offs, l->size, bbf + bbf_pos) < 0) exception(errno); } bbf_pos += l->size; } 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); loc_free(args->locs); }
ContextAddress get_tls_address(Context * ctx, ELF_File * file) { ContextAddress mod_tls_addr = 0; RegisterIdScope reg_id_scope; memset(®_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, ®_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; }