Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2014-09-21 17:08:25 +0000
committerEugene Tarassov2014-09-21 17:08:25 +0000
commit156e61d6b035fdd603ec1064f30a49e35686d36b (patch)
tree1961be5a33c726406e94016301eaa5bb49a179f8
parent44411479e1a50cc54d9f74743c63e80f7389142f (diff)
downloadorg.eclipse.tcf.agent-156e61d6b035fdd603ec1064f30a49e35686d36b.tar.gz
org.eclipse.tcf.agent-156e61d6b035fdd603ec1064f30a49e35686d36b.tar.xz
org.eclipse.tcf.agent-156e61d6b035fdd603ec1064f30a49e35686d36b.zip
TCF Agent: fixed handling of DWARF implicit pointers
-rw-r--r--agent/tcf/framework/cpudefs.c8
-rw-r--r--agent/tcf/framework/cpudefs.h1
-rw-r--r--agent/tcf/services/dwarfecomp.c11
-rw-r--r--agent/tcf/services/expressions.c247
-rw-r--r--agent/tcf/services/symbols_elf.c7
-rw-r--r--agent/tcf/services/tcf_elf.c8
-rw-r--r--agent/tcf/services/vm.c14
-rw-r--r--tests/test-dwarf/tcf/backend/backend.c127
8 files changed, 311 insertions, 112 deletions
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index ecd21ebc..7106f3c4 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -475,6 +475,10 @@ void read_location_pieces(Context * ctx, StackFrame * frame,
unsigned piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
uint8_t * pbf = NULL;
uint8_t * rbf = NULL;
+ if (piece->implicit_pointer) {
+ set_errno(ERR_OTHER, "Symbol value unknown: implicit pointer");
+ exception(errno);
+ }
if (piece->reg) {
if (piece->reg->size < piece_size) {
rbf = pbf = (uint8_t *)tmp_alloc_zero(piece_size);
@@ -529,6 +533,10 @@ void write_location_pieces(Context * ctx, StackFrame * frame,
unsigned piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
uint8_t * pbf = NULL;
uint8_t * rbf = NULL;
+ if (piece->implicit_pointer) {
+ set_errno(ERR_OTHER, "Cannot set symbol value: implicit pointer");
+ exception(errno);
+ }
if (piece->reg) {
if (piece->reg->size < piece_size) {
rbf = pbf = (uint8_t *)tmp_alloc_zero(piece_size);
diff --git a/agent/tcf/framework/cpudefs.h b/agent/tcf/framework/cpudefs.h
index 16a4164c..f9515b2e 100644
--- a/agent/tcf/framework/cpudefs.h
+++ b/agent/tcf/framework/cpudefs.h
@@ -124,6 +124,7 @@ typedef struct LocationPiece {
size_t size;
unsigned bit_offs;
unsigned bit_size;
+ unsigned implicit_pointer; /* >0 if the value is result of implicit pointer dereference */
} LocationPiece;
typedef struct LocationExpressionState {
diff --git a/agent/tcf/services/dwarfecomp.c b/agent/tcf/services/dwarfecomp.c
index 6b6725bc..91572957 100644
--- a/agent/tcf/services/dwarfecomp.c
+++ b/agent/tcf/services/dwarfecomp.c
@@ -441,10 +441,6 @@ static void op_implicit_pointer(void) {
read_dwarf_object_property(expr_ctx, STACK_NO_FRAME, ref_obj, AT_location, &pv);
dwarf_get_expression_list(&pv, &info);
add_expression_list(info, 0, 0);
- if (offset != 0) {
- add(OP_TCF_offset);
- add_uleb128(offset);
- }
clear_trap(&trap);
}
else if (trap.error == ERR_SYM_NOT_FOUND) {
@@ -471,11 +467,6 @@ static void op_implicit_pointer(void) {
break;
}
if (pv.mAddr == NULL) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- if (offset != 0) {
- if (offset > pv.mSize) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- pv.mSize -= (size_t)offset;
- pv.mAddr = (U1_T *)pv.mAddr + offset;
- }
add(OP_implicit_value);
add_uleb128(pv.mSize);
for (i = 0; i < pv.mSize; i++) {
@@ -485,6 +476,8 @@ static void op_implicit_pointer(void) {
else {
exception(trap.error);
}
+ add(OP_TCF_offset);
+ add_uleb128(offset);
}
static void op_push_tls_address(void) {
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index b2cb31a2..f285bbcc 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -941,15 +941,10 @@ static int sym2value(int mode, Symbol * sym, Value * v) {
v->remote = 1;
}
else {
- size_t size = 0;
- void * value = NULL;
- read_location_pieces(expression_context, frame_info,
- state->pieces, state->pieces_cnt, loc_info->big_endian, &value, &size);
- if (state->pieces_cnt == 1 && state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
+ if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0 &&
+ state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
v->reg = state->pieces->reg;
}
- v->size = size;
- v->value = value;
v->loc = state;
}
v->big_endian = loc_info->big_endian;
@@ -1392,6 +1387,17 @@ static void load_value(Value * v) {
}
v->value = buf;
v->remote = 0;
+ v->loc = 0;
+ }
+ else if (v->value == NULL) {
+ size_t size = 0;
+ void * value = NULL;
+ LocationExpressionState * loc = v->loc;
+ read_location_pieces(expression_context, loc->stack_frame,
+ loc->pieces, loc->pieces_cnt, v->big_endian, &value, &size);
+ if (size > v->size) size = (size_t)v->size;
+ set_value(v, value, size, v->big_endian);
+ sign_extend(v, loc);
}
}
@@ -1780,14 +1786,23 @@ static void op_deref(int mode, Value * v) {
error(ERR_OTHER, "Array or pointer base type is unknown");
}
if (v->type_class == TYPE_CLASS_POINTER) {
- if (v->sym != NULL && v->size == 0 && get_symbol_size(v->sym, &v->size) < 0) {
- error(errno, "Cannot retrieve symbol size");
+ if (v->loc && v->loc->pieces_cnt == 1 && v->loc->pieces->implicit_pointer) {
+ v->loc->pieces->implicit_pointer--;
+ }
+ else {
+ if (v->sym != NULL && v->size == 0 && get_symbol_size(v->sym, &v->size) < 0) {
+ error(errno, "Cannot retrieve symbol size");
+ }
+ v->address = (ContextAddress)to_uns(mode, v);
+ v->remote = 1;
+ v->sym_list = NULL;
+ v->sym = NULL;
+ v->reg = NULL;
+ v->loc = NULL;
+ v->value = NULL;
+ v->constant = 0;
+ set_value_endianness(v, NULL, type);
}
- v->address = (ContextAddress)to_uns(mode, v);
- v->remote = 1;
- v->constant = 0;
- v->value = NULL;
- set_value_endianness(v, NULL, type);
}
v->type = type;
if (get_symbol_type_class(v->type, &v->type_class) < 0) {
@@ -1931,6 +1946,7 @@ static void op_field(int mode, Value * v) {
}
read_location_pieces(expression_context, frame_info,
loc->pieces, loc->pieces_cnt, big_endian, &value, &size);
+ if (size > v->size) size = (size_t)v->size;
set_value(v, value, size, big_endian);
sign_extend(v, loc);
}
@@ -1990,15 +2006,25 @@ static void op_index(int mode, Value * v) {
error(errno, "Cannot get array element type");
}
if (v->type_class == TYPE_CLASS_POINTER) {
- v->address = (ContextAddress)to_uns(mode, v);
- v->remote = 1;
- v->constant = 0;
- v->value = NULL;
- set_value_endianness(v, NULL, type);
+ if (v->loc && v->loc->pieces_cnt == 1 && v->loc->pieces->implicit_pointer) {
+ v->loc->pieces->implicit_pointer--;
+ }
+ else {
+ v->address = (ContextAddress)to_uns(mode, v);
+ v->remote = 1;
+ v->sym_list = NULL;
+ v->sym = NULL;
+ v->reg = NULL;
+ v->loc = NULL;
+ v->value = NULL;
+ v->constant = 0;
+ set_value_endianness(v, NULL, type);
+ }
}
if (get_symbol_size(type, &size) < 0) {
error(errno, "Cannot get array element size");
}
+
if (mode == MODE_NORMAL) {
int64_t index = 0;
int64_t lower_bound = 0;
@@ -2021,6 +2047,7 @@ static void op_index(int mode, Value * v) {
v->address += offs;
}
else {
+ load_value(v);
v->value = (char *)v->value + offs;
}
}
@@ -2694,18 +2721,23 @@ static void lazy_unary_expression(int mode, Value * v) {
break;
case TYPE_CLASS_ARRAY:
if (v->type_class == TYPE_CLASS_POINTER) {
- v->address = (ContextAddress)to_uns(mode, v);
- v->sym_list = NULL;
- v->sym = NULL;
- v->reg = NULL;
- v->loc = NULL;
+ if (v->loc && v->loc->pieces_cnt == 1 && v->loc->pieces->implicit_pointer) {
+ v->loc->pieces->implicit_pointer--;
+ }
+ else {
+ v->address = (ContextAddress)to_uns(mode, v);
+ v->remote = 1;
+ v->sym_list = NULL;
+ v->sym = NULL;
+ v->reg = NULL;
+ v->loc = NULL;
+ v->value = NULL;
+ v->size = type_size;
+ v->big_endian = expression_context->big_endian;
+ v->constant = 0;
+ }
v->type = type;
v->type_class = type_class;
- v->size = type_size;
- v->big_endian = expression_context->big_endian;
- v->remote = 1;
- v->constant = 0;
- v->value = NULL;
}
else {
error(ERR_INV_EXPRESSION, "Invalid type cast: illegal source type");
@@ -2770,7 +2802,6 @@ static void pm_expression(int mode, Value * v) {
v->loc = NULL;
v->remote = 1;
v->function = 0;
- v->sym_list = NULL;
v->value = NULL;
v->constant = 0;
if (get_symbol_base_type(x.type, &v->type) < 0) {
@@ -3829,6 +3860,7 @@ static void command_evaluate_cache_client(void * x) {
Value value;
int value_ok = 0;
void * buf = NULL;
+ int implicit_pointer = 0;
int err = 0;
memset(&value, 0, sizeof(value));
@@ -3846,6 +3878,23 @@ static void command_evaluate_cache_client(void * x) {
if (!err && context_read_mem(ctx, value.address, buf, (size_t)value.size) < 0)
err = set_errno(errno, "Cannot read target memory");
}
+ if (!err && value.loc) {
+ unsigned n;
+ for (n = 0; n < value.loc->pieces_cnt; n++) {
+ if (value.loc->pieces[n].implicit_pointer) {
+ implicit_pointer = 1;
+ break;
+ }
+ }
+ }
+ if (!err && !value.remote && value.value == NULL && !implicit_pointer) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ load_value(&value);
+ clear_trap(&trap);
+ }
+ err = trap.error;
+ }
cache_exit();
@@ -3897,79 +3946,89 @@ static void command_evaluate_cache_client(void * x) {
cnt++;
}
#endif
- if (value.reg != NULL) {
- int reg_frame = value.loc->ctx == ctx ? frame : STACK_NO_FRAME;
- if (cnt > 0) write_stream(&c->out, ',');
- json_write_string(&c->out, "Register");
- write_stream(&c->out, ':');
- json_write_string(&c->out, register2id(value.loc->ctx, reg_frame, value.reg));
- cnt++;
- }
- if (value.remote) {
+ if (implicit_pointer) {
if (cnt > 0) write_stream(&c->out, ',');
- json_write_string(&c->out, "Address");
+ json_write_string(&c->out, "ImplicitPointer");
write_stream(&c->out, ':');
- json_write_uint64(&c->out, value.address);
+ json_write_boolean(&c->out, 1);
cnt++;
}
-
- if (value.loc != NULL && value.loc->pieces_cnt > 0 && value.reg == NULL) {
- unsigned i;
- if (cnt > 0) write_stream(&c->out, ',');
- json_write_string(&c->out, "Pieces");
- write_stream(&c->out, ':');
- write_stream(&c->out, '[');
- for (i = 0; i < value.loc->pieces_cnt; i++) {
- LocationPiece * piece = value.loc->pieces + i;
- if (i > 0) write_stream(&c->out, ',');
- write_stream(&c->out, '{');
- if (piece->size) {
- json_write_string(&c->out, "Size");
- write_stream(&c->out, ':');
- json_write_ulong(&c->out, piece->size);
- }
- else {
- json_write_string(&c->out, "BitSize");
- write_stream(&c->out, ':');
- json_write_ulong(&c->out, piece->bit_size);
- }
- if (piece->bit_offs) {
+ else {
+ if (value.reg != NULL) {
+ int reg_frame = value.loc->ctx == ctx ? frame : STACK_NO_FRAME;
+ if (cnt > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Register");
+ write_stream(&c->out, ':');
+ json_write_string(&c->out, register2id(value.loc->ctx, reg_frame, value.reg));
+ cnt++;
+ }
+
+ if (value.remote) {
+ if (cnt > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Address");
+ write_stream(&c->out, ':');
+ json_write_uint64(&c->out, value.address);
+ cnt++;
+ }
+
+ if (value.loc != NULL && value.loc->pieces_cnt > 0 && value.reg == NULL) {
+ unsigned i;
+ if (cnt > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "Pieces");
+ write_stream(&c->out, ':');
+ write_stream(&c->out, '[');
+ for (i = 0; i < value.loc->pieces_cnt; i++) {
+ LocationPiece * piece = value.loc->pieces + i;
+ if (i > 0) write_stream(&c->out, ',');
+ write_stream(&c->out, '{');
+ if (piece->size) {
+ json_write_string(&c->out, "Size");
+ write_stream(&c->out, ':');
+ json_write_ulong(&c->out, piece->size);
+ }
+ else {
+ json_write_string(&c->out, "BitSize");
+ write_stream(&c->out, ':');
+ json_write_ulong(&c->out, piece->bit_size);
+ }
+ if (piece->bit_offs) {
+ write_stream(&c->out, ',');
+ json_write_string(&c->out, "BitOffs");
+ write_stream(&c->out, ':');
+ json_write_ulong(&c->out, piece->bit_offs);
+ }
write_stream(&c->out, ',');
- json_write_string(&c->out, "BitOffs");
- write_stream(&c->out, ':');
- json_write_ulong(&c->out, piece->bit_offs);
- }
- write_stream(&c->out, ',');
- if (piece->reg) {
- Context * reg_ctx = value.loc->ctx;
- int reg_frame = get_info_frame(value.loc->ctx, value.loc->stack_frame);
- json_write_string(&c->out, "Register");
- write_stream(&c->out, ':');
- json_write_string(&c->out, register2id(reg_ctx, reg_frame, piece->reg));
- }
- else if (piece->value) {
- json_write_string(&c->out, "Value");
- write_stream(&c->out, ':');
- json_write_binary(&c->out, piece->value, piece->size);
- }
- else {
- json_write_string(&c->out, "Address");
- write_stream(&c->out, ':');
- json_write_uint64(&c->out, piece->addr);
+ if (piece->reg) {
+ Context * reg_ctx = value.loc->ctx;
+ int reg_frame = get_info_frame(value.loc->ctx, value.loc->stack_frame);
+ json_write_string(&c->out, "Register");
+ write_stream(&c->out, ':');
+ json_write_string(&c->out, register2id(reg_ctx, reg_frame, piece->reg));
+ }
+ else if (piece->value) {
+ json_write_string(&c->out, "Value");
+ write_stream(&c->out, ':');
+ json_write_binary(&c->out, piece->value, piece->size);
+ }
+ else {
+ json_write_string(&c->out, "Address");
+ write_stream(&c->out, ':');
+ json_write_uint64(&c->out, piece->addr);
+ }
+ write_stream(&c->out, '}');
}
- write_stream(&c->out, '}');
+ write_stream(&c->out, ']');
+ cnt++;
}
- write_stream(&c->out, ']');
- cnt++;
- }
- if (value.big_endian) {
- if (cnt > 0) write_stream(&c->out, ',');
- json_write_string(&c->out, "BigEndian");
- write_stream(&c->out, ':');
- json_write_boolean(&c->out, 1);
- cnt++;
+ if (value.big_endian) {
+ if (cnt > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, "BigEndian");
+ write_stream(&c->out, ':');
+ json_write_boolean(&c->out, 1);
+ cnt++;
+ }
}
write_stream(&c->out, '}');
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index 736a20f3..c16f112c 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -1863,9 +1863,7 @@ int id2symbol(const char * id, Symbol ** res) {
ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
ELF_File * file = NULL;
ELF_Section * sec = NULL;
- ContextAddress res = 0;
- errno = 0;
- res = elf_map_to_link_time_address(ctx, addr, 0, &file, &sec);
+ ContextAddress res = elf_map_to_link_time_address(ctx, addr, 0, &file, &sec);
if (res == 0 || sec == NULL) return 0;
if (sec->name == NULL) return 0;
if (strcmp(sec->name, ".plt") != 0) return 0;
@@ -3433,7 +3431,8 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
add_location_command(info, SFT_CMD_NUMBER)->args.num = addr;
return 0;
}
- else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND &&
+ get_error_code(errno) != ERR_INV_ADDRESS) {
return -1;
}
if (!(obj->mFlags & DOIF_ranges) && (obj->mFlags & DOIF_low_pc)) {
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c
index f7a23c77..caf52602 100644
--- a/agent/tcf/services/tcf_elf.c
+++ b/agent/tcf/services/tcf_elf.c
@@ -1406,6 +1406,7 @@ UnitAddressRange * elf_find_unit(Context * ctx, ContextAddress addr_min, Context
}
}
}
+ errno = 0;
return range;
}
@@ -1492,6 +1493,7 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
if (f->pheader_cnt == 0 && f->type == ET_EXEC) {
*file = d;
if (sec != NULL) *sec = find_section_by_address(d, addr, to_dwarf);
+ errno = 0;
return addr;
}
for (j = 0; j < f->pheader_cnt; j++) {
@@ -1504,6 +1506,7 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
pheader_address = to_dwarf ? get_pheader_address(f, p) : p->address;
addr = (ContextAddress)(offs - p->offset + pheader_address);
if (sec != NULL) *sec = find_section_by_address(d, addr, to_dwarf);
+ errno = 0;
return addr;
}
}
@@ -1513,12 +1516,15 @@ ContextAddress elf_map_to_link_time_address(Context * ctx, ContextAddress addr,
ELF_Section * s = d->sections + j;
if (strcmp(s->name, r->sect_name) == 0) {
*file = d;
+ addr = (ContextAddress)(addr - r->addr + s->addr);
if (sec != NULL) *sec = s;
- return (ContextAddress)(addr - r->addr + s->addr);
+ errno = 0;
+ return addr;
}
}
}
}
+ errno = 0;
return 0;
}
diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c
index d1acade1..f03b2b51 100644
--- a/agent/tcf/services/vm.c
+++ b/agent/tcf/services/vm.c
@@ -35,6 +35,7 @@ static LocationExpressionState * state = NULL;
static RegisterDefinition * reg_def = NULL;
static void * value_addr = NULL;
static size_t value_size = 0;
+static unsigned implicit_pointer = 0;
static uint8_t * code = NULL;
static size_t code_pos = 0;
static size_t code_len = 0;
@@ -160,8 +161,10 @@ static LocationPiece * add_piece(void) {
state->stk_pos--;
piece->addr = (ContextAddress)state->stk[state->stk_pos];
}
- reg_def = NULL;
+ piece->implicit_pointer = implicit_pointer;
+ implicit_pointer = 0;
value_addr = NULL;
+ reg_def = NULL;
return piece;
}
@@ -170,11 +173,9 @@ static void set_state(LocationExpressionState * s) {
code = state->code;
code_pos = state->code_pos;
code_len = state->code_len;
- reg_def = NULL;
}
static void get_state(LocationExpressionState * s) {
- if (reg_def != NULL || value_addr != NULL) add_piece();
s->code_pos = code_pos;
state = NULL;
code = NULL;
@@ -684,6 +685,7 @@ static void evaluate_expression(void) {
piece->size = piece->bit_size / 8;
piece->bit_size = 0;
}
+ piece->implicit_pointer++;
}
bit_offs += org_piece->bit_size;
}
@@ -692,6 +694,7 @@ static void evaluate_expression(void) {
else {
check_e_stack(1);
state->stk[state->stk_pos - 1] += read_u8leb128();
+ implicit_pointer++;
}
break;
case OP_GNU_entry_value:
@@ -756,9 +759,14 @@ int evaluate_vm_expression(LocationExpressionState * vm_state) {
int error = 0;
Trap trap;
+ implicit_pointer = 0;
+ value_addr = NULL;
+ reg_def = NULL;
+
set_state(vm_state);
if (set_trap(&trap)) {
evaluate_expression();
+ if (reg_def != NULL || value_addr != NULL || implicit_pointer) add_piece();
clear_trap(&trap);
}
else {
diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c
index 95e3353b..cd6e7106 100644
--- a/tests/test-dwarf/tcf/backend/backend.c
+++ b/tests/test-dwarf/tcf/backend/backend.c
@@ -66,6 +66,8 @@ static ContextAddress frame_addr = 0x40000000u;
static const char * elf_file_name = NULL;
static ELF_File * elf_file = NULL;
static int mem_region_pos = 0;
+static int file_has_line_info = 0;
+static unsigned line_info_cnt = 0;
static ContextAddress pc = 0;
static unsigned pass_cnt = 0;
static int test_posted = 0;
@@ -585,6 +587,87 @@ static void test_this_pointer(Symbol * base_type) {
}
}
+static void test_implicit_pointer(Symbol * sym) {
+ Trap trap;
+ StackFrame * frame_info = NULL;
+ LocationInfo * loc_info = NULL;
+ const char * id = symbol2id(sym);
+ LocationExpressionState * state = NULL;
+ int type_class = 0;
+ Symbol * type = NULL;
+ int cpp_ref = 0; /* '1' if the symbol is C++ reference */
+ Value v;
+
+ if (get_symbol_type(sym, &type) < 0) {
+ error_sym("get_symbol_type", sym);
+ }
+ if (type != NULL) {
+ if (get_symbol_type_class(sym, &type_class) < 0) {
+ error_sym("get_symbol_type_class", sym);
+ }
+ cpp_ref = is_cpp_reference(type);
+ }
+
+ if (get_location_info(sym, &loc_info) < 0) {
+ error_sym("get_location_info", sym);
+ }
+ else if (get_frame_info(elf_ctx, STACK_TOP_FRAME, &frame_info) < 0) {
+ error("get_frame_info");
+ }
+ assert(loc_info->value_cmds.cnt > 0);
+ assert(loc_info->code_size == 0 || (loc_info->code_addr <= pc && loc_info->code_addr + loc_info->code_size > pc));
+ if (set_trap(&trap)) {
+ unsigned i;
+ unsigned implicit_pointer = 0;
+ state = evaluate_location_expression(elf_ctx, frame_info,
+ loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, NULL, 0);
+ if (state->pieces_cnt == 0) {
+ errno = set_errno(ERR_OTHER, "Expected pieces");
+ error("evaluate_location_expression");
+ }
+ for (i = 0; i < state->pieces_cnt; i++) {
+ implicit_pointer += state->pieces[i].implicit_pointer;
+ }
+ if (implicit_pointer == 0) {
+ errno = set_errno(ERR_OTHER, "Expected implicit pointer");
+ error("evaluate_location_expression");
+ }
+ clear_trap(&trap);
+ }
+ else {
+ error("evaluate_location_expression");
+ }
+
+ if (state->pieces_cnt == 1 && !cpp_ref) {
+ char * expr = (char *)tmp_alloc(strlen(id) + 16);
+ sprintf(expr, "${%s}", id);
+ if (evaluate_expression(elf_ctx, STACK_TOP_FRAME, pc, expr, 0, &v) < 0) {
+ error_sym("evaluate_expression", sym);
+ }
+ if (v.loc->pieces->implicit_pointer != state->pieces->implicit_pointer) {
+ errno = set_errno(ERR_OTHER, "Invalid implicit_pointer");
+ error("evaluate_expression");
+ }
+
+ sprintf(expr, "*${%s}", id);
+ if (evaluate_expression(elf_ctx, STACK_TOP_FRAME, pc, expr, 0, &v) < 0) {
+ error_sym("evaluate_expression", sym);
+ }
+ if (v.loc && v.loc->pieces_cnt > 0) {
+ if (v.loc->pieces->implicit_pointer != state->pieces->implicit_pointer - 1) {
+ errno = set_errno(ERR_OTHER, "Invalid implicit_pointer");
+ error("evaluate_expression");
+ }
+ }
+ else {
+ if (state->pieces->implicit_pointer != 1) {
+ errno = set_errno(ERR_OTHER, "Invalid implicit_pointer");
+ error("evaluate_expression");
+ }
+ }
+ }
+}
+
static void loc_var_func(void * args, Symbol * sym) {
int frame = 0;
Context * ctx = NULL;
@@ -709,6 +792,10 @@ static void loc_var_func(void * args, Symbol * sym) {
if (errcmp(err, "Unsupported type in OP_GNU_const_type") == 0) return;
if (errcmp(err, "Unsupported type in OP_GNU_convert") == 0) return;
if (errcmp(err, "Ivalid size of implicit value") == 0) return;
+ if (errcmp(err, "Symbol value unknown: implicit pointer") == 0) {
+ test_implicit_pointer(sym);
+ return;
+ }
if (symbol_class == SYM_CLASS_TYPE && errcmp(err, "Wrong object kind") == 0) return;
errno = err;
error_sym("get_symbol_value", sym);
@@ -1127,6 +1214,8 @@ static void next_pc(void) {
int test_cnt = 0;
int loaded = mem_region_pos < 0;
ContextAddress next_pc = pc + 1;
+ UnitAddressRange * unit_range = NULL;
+ ContextAddress rage_rt_addr = 0;
for (;;) {
if (mem_region_pos < 0) {
@@ -1277,6 +1366,25 @@ static void next_pc(void) {
}
}
+ unit_range = elf_find_unit(elf_ctx, pc, pc, &rage_rt_addr);
+ if (unit_range == NULL && errno) error("elf_find_unit");
+ if (unit_range != NULL) {
+ ELF_Section * sec = unit_range->mUnit->mFile->sections + unit_range->mSection;
+ ContextAddress addr = elf_map_to_run_time_address(elf_ctx, sec->file, sec, unit_range->mAddr);
+ if (addr > pc || addr + unit_range->mSize <= pc) {
+ set_errno(ERR_OTHER, "Invalid compile unit address");
+ error("elf_find_unit");
+ }
+ if (func_object != NULL && unit_range->mUnit != func_object->mCompUnit) {
+ set_errno(ERR_OTHER, "Invalid compile unit");
+ error("elf_find_unit");
+ }
+ }
+ else if (func_object != NULL) {
+ set_errno(ERR_OTHER, "Compile unit not found");
+ error("elf_find_unit");
+ }
+
if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, "@ non existing name @", &sym) < 0) {
if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
error("find_symbol_by_name");
@@ -1304,8 +1412,9 @@ static void next_pc(void) {
errno = set_errno(ERR_OTHER, "Invalid line area address");
error("line_to_address");
}
+ line_info_cnt++;
}
- else if (func_object != NULL) {
+ else if (func_object != NULL && func_object->mCompUnit->mLineInfoOffs != 0) {
//errno = set_errno(ERR_OTHER, "Line info not found");
//error("address_to_line");
}
@@ -1313,6 +1422,7 @@ static void next_pc(void) {
lt_file = NULL;
lt_sec = NULL;
lt_addr = elf_map_to_link_time_address(elf_ctx, pc, 0, &lt_file, &lt_sec);
+ if (errno) error("elf_map_to_link_time_address");
assert(lt_file != NULL);
assert(lt_file == elf_file);
assert(lt_sec == NULL || lt_sec->file == lt_file);
@@ -1328,6 +1438,7 @@ static void next_pc(void) {
lt_file = NULL;
lt_sec = NULL;
lt_addr = elf_map_to_link_time_address(elf_ctx, pc, 1, &lt_file, &lt_sec);
+ if (errno) error("elf_map_to_link_time_address");
assert(lt_file != NULL);
assert(lt_file == get_dwarf_file(elf_file));
assert(lt_sec == NULL || lt_sec->file == lt_file);
@@ -1514,6 +1625,16 @@ static void next_file(void) {
memory_map_event_module_loaded(elf_ctx);
mem_region_pos = -1;
+ line_info_cnt = 0;
+ file_has_line_info = 0;
+ for (j = 0; j < f->section_cnt; j++) {
+ ELF_Section * sec = f->sections + j;
+ if (sec->name == NULL) continue;
+ if (sec->size > 0 && (strcmp(sec->name, ".debug_line") == 0 || strcmp(sec->name, ".line") == 0)) {
+ file_has_line_info = 1;
+ }
+ }
+
reg_size = 0;
memset(reg_defs, 0, sizeof(reg_defs));
memset(reg_vals, 0, sizeof(reg_vals));
@@ -1547,6 +1668,10 @@ static void test(void * args) {
assert(test_posted);
test_posted = 0;
if (elf_file_name == NULL || mem_region_pos >= (int)mem_map.region_cnt) {
+ if (file_has_line_info && line_info_cnt == 0) {
+ set_errno(ERR_OTHER, "Line info not accessable");
+ error("address_to_line");
+ }
next_file();
}
else {

Back to the top