diff options
author | Eugene Tarassov | 2017-08-03 20:51:52 +0000 |
---|---|---|
committer | Eugene Tarassov | 2017-08-03 20:51:52 +0000 |
commit | 0775cd4e668e999b8885705de543ef2cc92fae06 (patch) | |
tree | 5d0e7bf96256e0afd86887cc7a363d0474b02c95 /agent/tcf | |
parent | db59380a4e891144b6e6c2f9cccf177537523aa3 (diff) | |
download | org.eclipse.tcf.agent-0775cd4e668e999b8885705de543ef2cc92fae06.tar.gz org.eclipse.tcf.agent-0775cd4e668e999b8885705de543ef2cc92fae06.tar.xz org.eclipse.tcf.agent-0775cd4e668e999b8885705de543ef2cc92fae06.zip |
TCF Agent: fixed handling of large registers (> 8 bytes) saved in a stack frame
Diffstat (limited to 'agent/tcf')
-rw-r--r-- | agent/tcf/framework/cpudefs.c | 28 | ||||
-rw-r--r-- | agent/tcf/services/dwarfframe.c | 2 | ||||
-rw-r--r-- | agent/tcf/services/stacktrace.c | 27 |
3 files changed, 43 insertions, 14 deletions
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c index 6e4afd8f..4dd55191 100644 --- a/agent/tcf/framework/cpudefs.c +++ b/agent/tcf/framework/cpudefs.c @@ -322,14 +322,30 @@ LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame size_t j; size_t size = cmd->args.mem.size; uint64_t n = 0; - uint8_t buf[8]; - assert(size <= sizeof(buf)); - 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->args.mem.big_endian ? j : size - j - 1]; + if (size <= sizeof(n)) { + 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->args.mem.big_endian ? j : size - j - 1]; + } + stk[stk_pos - 1] = n; + } + else if (state->pieces_cnt == 0 && i + 1 == cmd_cnt && stk_pos == 1) { + LocationPiece * piece = NULL; + if (state->pieces_cnt >= state->pieces_max) { + state->pieces_max += 4; + state->pieces = (LocationPiece *)tmp_realloc(state->pieces, state->pieces_max * sizeof(LocationPiece)); + } + piece = state->pieces + state->pieces_cnt++; + memset(piece, 0, sizeof(LocationPiece)); + piece->addr = (ContextAddress)stk[stk_pos - 1]; + piece->size = size; + stk_pos--; + } + else { + exception(ERR_INV_DATA_SIZE); } - stk[stk_pos - 1] = n; } break; case SFT_CMD_WR_MEM: diff --git a/agent/tcf/services/dwarfframe.c b/agent/tcf/services/dwarfframe.c index 8b80820a..34c76f6b 100644 --- a/agent/tcf/services/dwarfframe.c +++ b/agent/tcf/services/dwarfframe.c @@ -834,7 +834,6 @@ static void generate_register_commands(RegisterRules * reg, RegisterDefinition * 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; @@ -855,7 +854,6 @@ static void generate_register_commands(RegisterRules * reg, RegisterDefinition * 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; diff --git a/agent/tcf/services/stacktrace.c b/agent/tcf/services/stacktrace.c index c8353678..5bb71b8b 100644 --- a/agent/tcf/services/stacktrace.c +++ b/agent/tcf/services/stacktrace.c @@ -165,11 +165,12 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) { } down->ctx = ctx; for (i = 0; i < info->reg_cnt; i++) { - int ok = 0; - uint64_t v = 0; + RegisterDefinition * reg_def = info->regs[i]->reg; + uint8_t * buf = NULL; + size_t size = 0; Trap trap_reg; #if ENABLE_StackRegisterLocations - if (write_reg_location(down, info->regs[i]->reg, info->regs[i]->cmds, info->regs[i]->cmds_cnt) == 0) { + if (write_reg_location(down, reg_def, info->regs[i]->cmds, info->regs[i]->cmds_cnt) == 0) { down->has_reg_data = 1; continue; } @@ -178,12 +179,26 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) { /* If a saved register value cannot be evaluated - ignore it */ state = evaluate_location_expression(ctx, frame, info->regs[i]->cmds, info->regs[i]->cmds_cnt, NULL, 0); if (state->stk_pos == 1) { - v = state->stk[0]; - ok = 1; + unsigned j; + uint64_t v = state->stk[0]; + buf = (uint8_t *)tmp_alloc_zero(reg_def->size); + for (j = 0; j < reg_def->size; j++) { + buf[reg_def->big_endian ? reg_def->size - j - 1 : j] = (uint8_t)v; + v = v >> 8; + } + size = reg_def->size; + } + else if (state->stk_pos == 0 && state->pieces_cnt > 0) { + read_location_pieces(state->ctx, state->stack_frame, + state->pieces, state->pieces_cnt, state->reg_id_scope.big_endian, (void **)&buf, &size); } clear_trap(&trap_reg); } - if (ok && write_reg_value(down, info->regs[i]->reg, v) < 0) exception(errno); + if (buf != NULL && size > 0) { + if (size > reg_def->size) size = reg_def->size; + if (write_reg_bytes(down, reg_def, 0, size, buf) < 0) exception(errno); + down->has_reg_data = 1; + } } clear_trap(&trap); frame->is_walked = 1; |