static void command_find_in_scope_cache_client(void * x) { CommandFindInScopeArgs * args = (CommandFindInScopeArgs *)x; Channel * c = cache_channel(); Context * ctx = NULL; int frame = STACK_NO_FRAME; Symbol * scope = NULL; Symbol * sym = NULL; int err = 0; if (id2frame(args->frame_id, &ctx, &frame) < 0) ctx = id2ctx(args->frame_id); if (ctx == NULL) err = set_errno(ERR_INV_CONTEXT, args->frame_id); else if (ctx->exited) err = ERR_ALREADY_EXITED; if (err == 0 && args->scope_id[0] && id2symbol(args->scope_id, &scope) < 0) err = errno; if (err == 0 && args->name == NULL) err = set_errno(EINVAL, "Symbol name must not be null"); if (err == 0 && find_symbol_in_scope(ctx, frame, args->ip, scope, args->name, &sym) < 0) err = errno; list_cnt = 0; if (err == 0) { list_add(sym); while (find_next_symbol(&sym) == 0) list_add(sym); if (get_error_code(errno) != ERR_SYM_NOT_FOUND) err = errno; } cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); write_symbol_list(&c->out); write_stream(&c->out, MARKER_EOM); loc_free(args->name); }
int id2frame(const char * id, Context ** ctx, int * frame) { int f = 0; Context * c = NULL; if (*id++ != 'F') { errno = ERR_INV_CONTEXT; return -1; } if (*id++ != 'P') { errno = ERR_INV_CONTEXT; return -1; } while (*id != '.') { if (*id < '0' || *id > '9') { errno = ERR_INV_CONTEXT; return -1; } f = f * 10 + (*id++ - '0'); } id++; c = id2ctx(id); if (c == NULL) { errno = ERR_INV_CONTEXT; return -1; } *ctx = c; *frame = f; return 0; }
static void command_get_context(char * token, Channel * c) { int err = 0; char id[256]; Context * ctx = NULL; json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); ctx = id2ctx(id); if (ctx == NULL || ctx->mem_access == 0) err = ERR_INV_CONTEXT; else if (ctx->exited) err = ERR_ALREADY_EXITED; write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); if (err == 0) { write_context(&c->out, ctx); } else { write_string(&c->out, "null"); } write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
static void command_suspend(char * token, Channel * c) { char id[256]; Context * ctx; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); ctx = id2ctx(id); if (ctx == NULL) { err = ERR_INV_CONTEXT; } else if (ctx->exited) { err = ERR_ALREADY_EXITED; } else if (ctx->intercepted) { err = ERR_ALREADY_STOPPED; } else if (ctx->stopped) { send_event_context_suspended(&c->bcg->out, ctx); } else { ctx->pending_intercept = 1; if (context_stop(ctx) < 0) err = errno; } send_simple_result(c, token, err); }
static void command_get_state(char * token, Channel * c) { char id[256]; Context * ctx; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); ctx = id2ctx(id); write_stringz(&c->out, "R"); write_stringz(&c->out, token); if (ctx == NULL) err = ERR_INV_CONTEXT; else if (ctx->exited) err = ERR_ALREADY_EXITED; write_errno(&c->out, err); json_write_boolean(&c->out, ctx != NULL && ctx->intercepted); write_stream(&c->out, 0); if (err) { write_stringz(&c->out, "0"); write_stringz(&c->out, "null"); write_stringz(&c->out, "null"); } else { write_context_state(&c->out, ctx); } write_stream(&c->out, MARKER_EOM); }
static void command_get_context(char * token, Channel * c) { int err = 0; char id[256]; Context * ctx = NULL; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); ctx = id2ctx(id); if (ctx == NULL) err = ERR_INV_CONTEXT; else if (ctx->exited) err = ERR_ALREADY_EXITED; if (err) { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stringz(&c->out, "null"); write_stream(&c->out, MARKER_EOM); } else { /* Need to stop everything to access context properties. * In particular, proc FS access can fail when process is running. */ GetContextArgs * s = loc_alloc_zero(sizeof(GetContextArgs)); s->c = c; stream_lock(c); strcpy(s->token, token); s->ctx = ctx; context_lock(ctx); id2pid(id, &s->parent); post_safe_event(ctx->mem, event_get_context, s); } }
static void command_reset_cache_client(void * x) { CommandResetArgs * args = (CommandResetArgs *)x; Channel * c = cache_channel(); Context * ctx = id2ctx(args->id); OutputStream * out = &c->out; int err = 0; if (ctx == NULL) err = ERR_INV_CONTEXT; else if (ctx->exited) err = ERR_ALREADY_EXITED; if (!err) { Context * grp = get_reset_context(ctx); ResetInfo * rst = find_reset(grp, args->type); if (rst == NULL) err = set_errno(ERR_OTHER, "Unsupported reset type"); else if (rst->reset(ctx, &args->params) < 0) err = errno; } cache_exit(); while (args->params.list != NULL) { ResetParameter * p = args->params.list; args->params.list = p->next; loc_free(p->name); loc_free(p->value); loc_free(p); } write_stringz(out, "R"); write_stringz(out, args->token); write_errno(out, err); write_stream(out, MARKER_EOM); }
static void command_find_by_addr_cache_client(void * x) { CommandFindByAddrArgs * args = (CommandFindByAddrArgs *)x; Channel * c = cache_channel(); Context * ctx = NULL; int frame = STACK_NO_FRAME; Symbol * sym = NULL; int err = 0; if (id2frame(args->id, &ctx, &frame) < 0) ctx = id2ctx(args->id); if (ctx == NULL) err = set_errno(ERR_INV_CONTEXT, args->id); else if (ctx->exited) err = ERR_ALREADY_EXITED; if (err == 0 && find_symbol_by_addr(ctx, frame, args->addr, &sym) < 0) err = errno; list_cnt = 0; if (err == 0) { list_add(sym); while (find_next_symbol(&sym) == 0) list_add(sym); if (get_error_code(errno) != ERR_SYM_NOT_FOUND) err = errno; } cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); write_symbol_list(&c->out); write_stream(&c->out, MARKER_EOM); }
static void command_disassemble(char * token, Channel * c) { int error = 0; Context * ctx = NULL; DisassembleCmdArgs * args = (DisassembleCmdArgs *)loc_alloc_zero(sizeof(DisassembleCmdArgs)); json_read_string(&c->inp, args->id, sizeof(args->id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); args->addr = (ContextAddress)json_read_uint64(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); args->size = (ContextAddress)json_read_uint64(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); json_read_struct(&c->inp, read_disassembly_params, args); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); ctx = id2ctx(args->id); if (ctx == NULL) error = ERR_INV_CONTEXT; else if (ctx->exited) error = ERR_ALREADY_EXITED; else if (context_get_group(ctx, CONTEXT_GROUP_PROCESS)->mem_access == 0) error = ERR_INV_CONTEXT; if (error != 0) { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, error); write_stringz(&c->out, "null"); write_stream(&c->out, MARKER_EOM); loc_free(args); } else { channel_lock(args->c = c); strlcpy(args->token, token, sizeof(args->token)); post_safe_event(ctx, safe_event_disassemble, args); } }
int id2symbol(const char * id, Symbol ** res) { Symbol * sym = NULL; Context * ctx = NULL; ULONG64 module = 0; ULONG index = 0; unsigned frame = 0; const Symbol * base = NULL; const TypeInfo * info = NULL; size_t length = 0; const char * p; if (id != NULL && id[0] == '@' && id[1] == 'P') { p = id + 2; length = (size_t)read_hex(&p); if (*p == '.') p++; if (id2symbol(p, (Symbol **)&base)) return -1; ctx = base->ctx; } else if (id != NULL && id[0] == '@' && id[1] == 'S') { unsigned idx = 0; p = id + 2; module = (ULONG64)read_hex(&p); if (*p == '.') p++; index = (ULONG)read_hex(&p); if (*p == '.') p++; frame = (unsigned)read_hex(&p); if (*p == '.') p++; idx = (unsigned)read_hex(&p); if (idx) info = basic_type_info + (idx - 1); if (*p == '.') p++; ctx = id2ctx(p); } else { errno = ERR_INV_CONTEXT; return -1; } if (ctx == NULL) { errno = ERR_INV_CONTEXT; return -1; } sym = alloc_symbol(); sym->ctx = ctx; sym->module = module; sym->index = index; sym->frame = frame; sym->base = base; sym->info = info; sym->length = length; if (sym->base || sym->info) { sym->sym_class = SYM_CLASS_TYPE; } else { DWORD dword = 0; if (get_type_info(sym, TI_GET_SYMTAG, &dword) < 0) return -1; tag2symclass(sym, dword); } *res = sym; return 0; }
static void command_resume(char * token, Channel * c) { char id[256]; long mode; long count; Context * ctx; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); mode = json_read_long(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); count = json_read_long(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (peek_stream(&c->inp) != MARKER_EOM) { json_read_struct(&c->inp, resume_params_callback, &err); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); } if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (err == 0) { ctx = id2ctx(id); assert(safe_event_list == NULL); if (ctx == NULL) { err = ERR_INV_CONTEXT; } else if (ctx->exited) { err = ERR_ALREADY_EXITED; } else if (!ctx->intercepted) { err = ERR_ALREADY_RUNNING; } else if (ctx->regs_error) { err = ctx->regs_error; } else if (count != 1) { err = EINVAL; } else if (mode == RM_RESUME || mode == RM_STEP_INTO) { send_event_context_resumed(&c->bcg->out, ctx); if (mode == RM_STEP_INTO) { if (context_single_step(ctx) < 0) { err = errno; } else { ctx->pending_intercept = 1; } } else if (context_continue(ctx) < 0) { err = errno; } } else { err = EINVAL; } } send_simple_result(c, token, err); }
static void command_terminate(char * token, Channel * c) { char id[256]; int err = 0; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (terminate_debug_context(c->bcg, id2ctx(id)) != 0) err = errno; send_simple_result(c, token, err); }
static void command_get_children(char * token, Channel * c) { char id[256]; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); write_stream(&c->out, '['); if (id[0] == 0) { LINK * qp; int cnt = 0; for (qp = context_root.next; qp != &context_root; qp = qp->next) { Context * ctx = ctxl2ctxp(qp); if (ctx->exited) continue; if (ctx->parent != NULL) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, container_id(ctx)); cnt++; } } else if (id[0] == 'P') { LINK * qp; int cnt = 0; pid_t ppd = 0; Context * parent = id2ctx(id); id2pid(id, &ppd); if (parent != NULL && parent->parent == NULL && ppd == 0) { if (!parent->exited && context_has_state(parent)) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, thread_id(parent)); cnt++; } for (qp = parent->children.next; qp != &parent->children; qp = qp->next) { Context * ctx = cldl2ctxp(qp); assert(!ctx->exited); assert(ctx->parent == parent); if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out,thread_id(ctx)); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
static void command_get_children_cache_client(void * x) { GetChildrenArgs * args = (GetChildrenArgs *)x; Channel * c = cache_channel(); Context * ctx = NULL; int frame = STACK_NO_FRAME; StackFrame * frame_info = NULL; RegisterDefinition * defs = NULL; RegisterDefinition * parent = NULL; Trap trap; if (set_trap(&trap)) { if (id2register(args->id, &ctx, &frame, &parent) == 0) { if (frame != STACK_TOP_FRAME && get_frame_info(ctx, frame, &frame_info) < 0) exception(errno); } else if (id2frame(args->id, &ctx, &frame) == 0) { if (get_frame_info(ctx, frame, &frame_info) < 0) exception(errno); } else { ctx = id2ctx(args->id); frame = STACK_TOP_FRAME; } if (ctx != NULL) defs = get_reg_definitions(ctx); clear_trap(&trap); } cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, trap.error); write_stream(&c->out, '['); if (defs != NULL) { int cnt = 0; RegisterDefinition * reg_def; for (reg_def = defs; reg_def->name != NULL; reg_def++) { if (reg_def->parent != parent) continue; if (frame < 0 || frame_info->is_top_frame || reg_def->size == 0 || read_reg_value(frame_info, reg_def, NULL) == 0) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, register2id(ctx, frame, reg_def)); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
static void command_get_address_info_cache_client(void * x) { int err = 0; Channel * c = cache_channel(); CommandAddressInfo * args = (CommandAddressInfo *)x; Context * ctx = NULL; const char * isa = NULL; ContextAddress range_addr = 0; ContextAddress range_size = 0; ContextAddress plt = 0; ctx = id2ctx(args->id); if (ctx == NULL) err = ERR_INV_CONTEXT; if (!err && get_context_isa(ctx, args->addr, &isa, &range_addr, &range_size) < 0) err = errno; if (!err) plt = is_plt_section(ctx, args->addr); cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); if (!err) { write_stream(&c->out, '{'); json_write_string(&c->out, "Addr"); write_stream(&c->out, ':'); json_write_uint64(&c->out, range_addr); write_stream(&c->out, ','); json_write_string(&c->out, "Size"); write_stream(&c->out, ':'); json_write_uint64(&c->out, range_size); if (isa != NULL) { write_stream(&c->out, ','); json_write_string(&c->out, "ISA"); write_stream(&c->out, ':'); json_write_string(&c->out, isa); } if (plt != 0) { write_stream(&c->out, ','); json_write_string(&c->out, "PLT"); write_stream(&c->out, ':'); json_write_uint64(&c->out, plt); } write_stream(&c->out, '}'); write_stream(&c->out, 0); } else { write_stringz(&c->out, "null"); } write_stream(&c->out, MARKER_EOM); }
static MemoryCommandArgs * read_command_args(char * token, Channel * c, int cmd) { int err = 0; char id[256]; MemoryCommandArgs buf; memset(&buf, 0, sizeof(buf)); json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); buf.addr = (ContextAddress)json_read_uint64(&c->inp); json_test_char(&c->inp, MARKER_EOA); buf.word_size = (int)json_read_long(&c->inp); json_test_char(&c->inp, MARKER_EOA); buf.size = (int)json_read_long(&c->inp); json_test_char(&c->inp, MARKER_EOA); buf.mode = (int)json_read_long(&c->inp); json_test_char(&c->inp, MARKER_EOA); if (cmd == CMD_GET) json_test_char(&c->inp, MARKER_EOM); buf.ctx = id2ctx(id); if (buf.ctx == NULL) err = ERR_INV_CONTEXT; else if (buf.ctx->exited) err = ERR_ALREADY_EXITED; else if (buf.ctx->mem_access == 0) err = ERR_INV_CONTEXT; if (err != 0) { if (cmd != CMD_GET) { int ch; do ch = read_stream(&c->inp); while (ch != MARKER_EOM && ch != MARKER_EOS); } write_stringz(&c->out, "R"); write_stringz(&c->out, token); if (cmd == CMD_GET) write_stringz(&c->out, "null"); write_errno(&c->out, err); write_stringz(&c->out, "null"); write_stream(&c->out, MARKER_EOM); return NULL; } else { MemoryCommandArgs * args = (MemoryCommandArgs *)loc_alloc(sizeof(MemoryCommandArgs)); *args = buf; args->c = c; strlcpy(args->token, token, sizeof(args->token)); channel_lock(c); context_lock(buf.ctx); return args; } }
static void command_get_children(char * token, Channel * c) { char id[256]; json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); write_stream(&c->out, '['); if (id[0] == 0) { LINK * qp; int cnt = 0; for (qp = context_root.next; qp != &context_root; qp = qp->next) { Context * ctx = ctxl2ctxp(qp); if (ctx->parent != NULL) continue; if (ctx->exited) continue; if (ctx->mem_access == 0 && list_is_empty(&ctx->children)) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, ctx->id); cnt++; } } else { Context * parent = id2ctx(id); if (parent != NULL) { LINK * l; int cnt = 0; for (l = parent->children.next; l != &parent->children; l = l->next) { Context * ctx = cldl2ctxp(l); assert(ctx->parent == parent); if (ctx->exited) continue; if (ctx->mem_access == 0 && list_is_empty(&ctx->children)) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, ctx->id); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) { int r = 0; *ctx = NULL; *frame = STACK_TOP_FRAME; *reg_def = NULL; if (*id++ != 'R') { errno = ERR_INV_CONTEXT; return -1; } while (*id != '.' && *id != '@') { if (*id >= '0' && *id <= '9') { r = r * 10 + (*id++ - '0'); } else { errno = ERR_INV_CONTEXT; return -1; } } if (*id == '@') { int n = 0; id++; while (*id != '.') { if (*id >= '0' && *id <= '9') { n = n * 10 + (*id++ - '0'); } else { errno = ERR_INV_CONTEXT; return -1; } } *frame = n; } id++; *ctx = id2ctx(id); if (*ctx == NULL) { errno = ERR_INV_CONTEXT; return -1; } if ((*ctx)->exited) { errno = ERR_ALREADY_EXITED; return -1; } *reg_def = get_reg_definitions(*ctx) + r; return 0; }
static void command_get_capabilities(char * token, Channel * c) { char id[256]; Context * ctx; OutputStream * out = &c->out; int err = 0; json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); ctx = id2ctx(id); if (ctx == NULL) err = ERR_INV_CONTEXT; else if (ctx->exited) err = ERR_ALREADY_EXITED; write_stringz(out, "R"); write_stringz(out, token); write_errno(out, err); write_stream(out, '['); if (!err) { unsigned i; ContextExtensionRS * ext = EXT(get_reset_context(ctx)); for (i = 0; i < ext->resets_cnt; i++) { ResetInfo * ri = ext->resets + i; if (i > 0) write_stream(&c->out, ','); write_stream(out, '{'); json_write_string(out, "Type"); write_stream(out, ':'); json_write_string(out, ri->type); write_stream(out, ','); json_write_string(out, "Description"); write_stream(out, ':'); json_write_string(out, ri->desc); write_stream(out, '}'); } } write_stream(out, ']'); write_stream(out, 0); write_stream(out, MARKER_EOM); }
static void command_list_cache_client(void * x) { CommandListArgs * args = (CommandListArgs *)x; Channel * c = cache_channel(); Context * ctx = NULL; int frame = STACK_NO_FRAME; int err = 0; list_cnt = 0; if (id2frame(args->id, &ctx, &frame) < 0) ctx = id2ctx(args->id); if (ctx == NULL) err = set_errno(ERR_INV_CONTEXT, args->id); else if (ctx->exited) err = ERR_ALREADY_EXITED; if (err == 0 && enumerate_symbols(ctx, frame, list_callback, NULL) < 0) err = errno; cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); if (err == 0) { unsigned i = 0; write_stream(&c->out, '['); for (i = 0; i < list_cnt; i++) { if (i > 0) write_stream(&c->out, ','); json_write_string(&c->out, symbol2id(list_buf[i])); } write_stream(&c->out, ']'); write_stream(&c->out, 0); } else { write_stringz(&c->out, "null"); } write_stream(&c->out, MARKER_EOM); }
static void command_get_capabilities_cache_client(void * x) { int error = 0; Context * ctx = NULL; ContextExtensionDS * ext = NULL; GetCapabilitiesCmdArgs * args = (GetCapabilitiesCmdArgs *)x; Channel * c = cache_channel(); ctx = id2ctx(args->id); if (ctx == NULL) error = ERR_INV_CONTEXT; else if (ctx->exited) error = ERR_ALREADY_EXITED; else ext = EXT(context_get_group(ctx, CONTEXT_GROUP_CPU)); cache_exit(); if (!is_channel_closed(c)) { OutputStream * out = &c->out; write_stringz(out, "R"); write_stringz(out, args->token); write_errno(out, error); write_stream(out, '['); if (ext != NULL) { unsigned i; for (i = 0; i < ext->disassemblers_cnt; i++) { if (i > 0) write_stream(out, ','); write_stream(out, '{'); json_write_string(out, "ISA"); write_stream(out, ':'); json_write_string(out, ext->disassemblers[i].isa); write_stream(out, '}'); } } write_stream(out, ']'); write_stream(out, 0); write_stream(out, MARKER_EOM); } }
static void command_get_capabilities(char * token, Channel * c) { int error = 0; char id[256]; Context * ctx = NULL; ContextExtensionDS * ext = NULL; unsigned i, j; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); ctx = id2ctx(id); if (ctx == NULL) error = ERR_INV_CONTEXT; else if (ctx->exited) error = ERR_ALREADY_EXITED; ctx = context_get_group(ctx, CONTEXT_GROUP_CPU); ext = EXT(ctx); write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, error); write_stream(&c->out, '['); for (i = 0, j = 0; i < ext->disassemblers_cnt; i++) { if (j > 0) write_stream(&c->out, ','); write_stream(&c->out, '{'); json_write_string(&c->out, "ISA"); write_stream(&c->out, ':'); json_write_string(&c->out, ext->disassemblers[i].isa); write_stream(&c->out, '}'); j++; } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
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; }
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); }
static void command_get_sym_file_info_cache_client(void * x) { int err = 0; MemoryMap * client_map = NULL; MemoryMap * target_map = NULL; MemoryRegion * region = NULL; Channel * c = cache_channel(); CommandSymFileInfo * args = (CommandSymFileInfo *)x; const char * sym_file = NULL; Context * ctx = NULL; int sym_error = 0; ctx = id2ctx(args->id); if (ctx == NULL) err = ERR_INV_CONTEXT; if (!err && memory_map_get(ctx, &client_map, &target_map) < 0) err = errno; if (!err) { unsigned i; for (i = 0; i < client_map->region_cnt; i++) { MemoryRegion * r = client_map->regions + i; if (r->addr <= args->addr && r->addr + r->size > args->addr) region = r; } if (region == NULL) { for (i = 0; i < target_map->region_cnt; i++) { MemoryRegion * r = target_map->regions + i; if (r->addr <= args->addr && r->addr + r->size > args->addr) region = r; } } #if ENABLE_ELF /* TODO: need a generic way to support ELF program headers in getSymFileInfo command */ if (region == NULL) { static MemoryMap map; extern int elf_get_map(Context * ctx, ContextAddress addr0, ContextAddress addr1, MemoryMap * map); if (elf_get_map(ctx, args->addr, args->addr, &map) == 0) { for (i = 0; i < map.region_cnt; i++) { MemoryRegion * r = map.regions + i; if (r->addr <= args->addr && r->addr + r->size > args->addr) region = r; } } } #endif sym_file = get_symbol_file_name(ctx, region); sym_error = errno; } cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); if (region != NULL) { write_stream(&c->out, '{'); json_write_string(&c->out, "Addr"); write_stream(&c->out, ':'); json_write_uint64(&c->out, region->addr); write_stream(&c->out, ','); json_write_string(&c->out, "Size"); write_stream(&c->out, ':'); json_write_uint64(&c->out, region->size); if (sym_file != NULL) { write_stream(&c->out, ','); json_write_string(&c->out, "FileName"); write_stream(&c->out, ':'); json_write_string(&c->out, sym_file); } if (sym_error != 0) { write_stream(&c->out, ','); json_write_string(&c->out, "FileError"); write_stream(&c->out, ':'); write_error_object(&c->out, sym_error); } write_stream(&c->out, '}'); write_stream(&c->out, 0); } else { write_stringz(&c->out, "null"); } write_stream(&c->out, MARKER_EOM); }
static void command_find_frame_props_cache_client(void * x) { CommandFindFrameInfo * args = (CommandFindFrameInfo *)x; Channel * c = cache_channel(); Context * ctx = NULL; StackTracingInfo * info = NULL; int err = 0; ctx = id2ctx(args->id); if (ctx == NULL) err = ERR_INV_CONTEXT; else if (get_stack_tracing_info(ctx, args->addr, &info) < 0) err = errno; cache_exit(); write_stringz(&c->out, "R"); write_stringz(&c->out, args->token); write_errno(&c->out, err); if (args->props) { unsigned cnt = 0; write_stream(&c->out, '{'); if (info != NULL && info->size) { json_write_string(&c->out, "CodeAddr"); write_stream(&c->out, ':'); json_write_uint64(&c->out, info->addr); write_stream(&c->out, ','); json_write_string(&c->out, "CodeSize"); write_stream(&c->out, ':'); json_write_uint64(&c->out, info->size); cnt++; } if (info != NULL && info->fp != NULL) { if (cnt++ > 0) write_stream(&c->out, ','); json_write_string(&c->out, "FP"); write_stream(&c->out, ':'); write_commands(&c->out, ctx, info->fp->cmds, info->fp->cmds_cnt); } if (info != NULL && info->regs != NULL) { int i; if (cnt++ > 0) write_stream(&c->out, ','); json_write_string(&c->out, "Regs"); write_stream(&c->out, ':'); write_stream(&c->out, '{'); for (i = 0; i < info->reg_cnt; i++) { if (i > 0) write_stream(&c->out, ','); json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg)); write_stream(&c->out, ':'); write_commands(&c->out, ctx, info->regs[i]->cmds, info->regs[i]->cmds_cnt); } write_stream(&c->out, '}'); } if (info != NULL && info->subs != NULL) { int i; if (cnt++ > 0) write_stream(&c->out, ','); json_write_string(&c->out, "Inlined"); write_stream(&c->out, ':'); write_stream(&c->out, '['); for (i = 0; i < info->sub_cnt; i++) { if (i > 0) write_stream(&c->out, ','); write_inlined_subroutine_info(&c->out, info->subs[i]); } write_stream(&c->out, ']'); } write_stream(&c->out, '}'); write_stream(&c->out, 0); } else { /* Deprecated, use findFrameProps */ json_write_uint64(&c->out, info ? info->addr : 0); write_stream(&c->out, 0); json_write_uint64(&c->out, info ? info->size : 0); write_stream(&c->out, 0); if (info == NULL || info->fp == NULL) write_string(&c->out, "null"); else write_commands(&c->out, ctx, info->fp->cmds, info->fp->cmds_cnt); write_stream(&c->out, 0); if (info != NULL && info->regs != NULL) { int i; write_stream(&c->out, '{'); for (i = 0; i < info->reg_cnt; i++) { if (i > 0) write_stream(&c->out, ','); json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg)); write_stream(&c->out, ':'); write_commands(&c->out, ctx, info->regs[i]->cmds, info->regs[i]->cmds_cnt); } write_stream(&c->out, '}'); } else { write_string(&c->out, "null"); } write_stream(&c->out, 0); } write_stream(&c->out, MARKER_EOM); }