Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorEugene Tarassov2019-11-21 17:23:57 +0000
committerEugene Tarassov2019-11-21 17:23:57 +0000
commit78b751acc5ebdf1d65b2416a8c08b684f1419c84 (patch)
treeeaf22969a23a5faae33fe87d129f06c783effdfc /agent
parentd427a075fa66cbf8d8f70072cd1ab5a1a319e3d8 (diff)
downloadorg.eclipse.tcf.agent-78b751acc5ebdf1d65b2416a8c08b684f1419c84.tar.gz
org.eclipse.tcf.agent-78b751acc5ebdf1d65b2416a8c08b684f1419c84.tar.xz
org.eclipse.tcf.agent-78b751acc5ebdf1d65b2416a8c08b684f1419c84.zip
TCF Agent: Expressions service: added built-in function $relocate
The function maps link-time address in a file to run-time address in memory. Can be used to plant breakpoints on link-time addresses.
Diffstat (limited to 'agent')
-rw-r--r--agent/tcf/services/expressions.c99
-rw-r--r--agent/tcf/services/symbols_elf.c95
2 files changed, 167 insertions, 27 deletions
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index 81de0026..67968556 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -1171,6 +1171,79 @@ static unsigned flag_count(SYM_FLAGS flags) {
}
#endif /* ENABLE_Symbols */
+static void expression(int mode, Value * v);
+static uint64_t to_uns(int mode, Value * v);
+static void load_value(Value * v);
+
+static int builtin_identifier(int mode, char * name, Value * v) {
+ Context * ctx = expression_context;
+ for (;;) {
+ RegisterDefinition * def = get_reg_definitions(ctx);
+ if (def != NULL) {
+ while (def->name != NULL) {
+ if (strcmp(name + 1, def->name) == 0) {
+ int frame = STACK_NO_FRAME;
+ if (ctx == expression_context) frame = expression_frame;
+ reg2value(mode, ctx, frame, def, v);
+ return SYM_CLASS_REFERENCE;
+ }
+ def++;
+ }
+ }
+ ctx = ctx->parent;
+ if (ctx == NULL) break;
+ }
+ if (strcmp(name, "$thread") == 0) {
+ set_string_value(v, expression_context->id);
+ v->constant = 1;
+ return SYM_CLASS_VALUE;
+ }
+ if (strcmp(name, "$relocate") == 0 && text_sy == '(') {
+ unsigned cnt;
+ uint64_t addr = 0;
+ const char * file_name = "";
+ const char * sect_name = "";
+ Symbol * sym = NULL;
+ next_sy();
+ for (cnt = 0;; cnt++) {
+ switch (cnt) {
+ case 0:
+ expression(mode, v);
+ addr = to_uns(mode, v);
+ break;
+ case 1:
+ expression(mode, v);
+ load_value(v);
+ file_name = tmp_strndup((char *)v->value, v->size);
+ break;
+ case 2:
+ expression(mode, v);
+ load_value(v);
+ sect_name = tmp_strndup((char *)v->value, v->size);
+ break;
+ default:
+ error(ERR_INV_EXPRESSION, "Too many arguments");
+ }
+ if (text_sy != ',') break;
+ next_sy();
+ }
+ if (text_sy != ')') error(ERR_INV_EXPRESSION, "Missing ')'");
+ next_sy();
+ ini_value(v);
+ if (mode != MODE_NORMAL) {
+ set_ctx_word_value(v, addr);
+ v->type_class = TYPE_CLASS_POINTER;
+ return SYM_CLASS_VALUE;
+ }
+ if (find_symbol_by_name(expression_context, STACK_NO_FRAME, 0,
+ tmp_printf("$relocate:%s:%s:%" PRIX64, file_name, sect_name, addr), &sym) < 0) {
+ error(errno, "Cannot read symbol data");
+ }
+ return sym2value(mode, sym, v);
+ }
+ return -1;
+}
+
static int identifier(int mode, Value * scope, char * name, SYM_FLAGS flags, Value * v) {
ini_value(v);
if (scope == NULL) {
@@ -1182,28 +1255,8 @@ static int identifier(int mode, Value * scope, char * name, SYM_FLAGS flags, Val
exception(ERR_INV_CONTEXT);
}
if (name[0] == '$') {
- Context * ctx = expression_context;
- for (;;) {
- RegisterDefinition * def = get_reg_definitions(ctx);
- if (def != NULL) {
- while (def->name != NULL) {
- if (strcmp(name + 1, def->name) == 0) {
- int frame = STACK_NO_FRAME;
- if (ctx == expression_context) frame = expression_frame;
- reg2value(mode, ctx, frame, def, v);
- return SYM_CLASS_REFERENCE;
- }
- def++;
- }
- }
- ctx = ctx->parent;
- if (ctx == NULL) break;
- }
- }
- if (strcmp(name, "$thread") == 0) {
- set_string_value(v, expression_context->id);
- v->constant = 1;
- return SYM_CLASS_VALUE;
+ int id_class = builtin_identifier(mode, name, v);
+ if (id_class >= 0) return id_class;
}
}
#if ENABLE_Symbols
@@ -2029,8 +2082,6 @@ static void set_complex_type(Value * v) {
#endif
}
-static void expression(int mode, Value * v);
-
static void primary_expression(int mode, Value * v) {
if (text_sy == '(') {
next_sy();
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index 4f241c4d..5c42db43 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -87,6 +87,7 @@ struct Symbol {
#define is_array_type_pseudo_symbol(s) (s->sym_class == SYM_CLASS_TYPE && s->obj == NULL && s->base != NULL)
#define is_std_type_pseudo_symbol(s) (s->sym_class == SYM_CLASS_TYPE && s->obj == NULL && s->base == NULL)
#define is_constant_pseudo_symbol(s) (s->sym_class == SYM_CLASS_VALUE && s->obj == NULL && s->base != NULL)
+#define is_pointer_pseudo_symbol(s) (s->sym_class == SYM_CLASS_VALUE && s->obj == NULL && s->base == NULL && s->has_address)
static Context * sym_ctx;
static int sym_frame;
@@ -1548,6 +1549,66 @@ static void find_by_name_in_sym_table(ELF_File * file, const char * name, int gl
}
}
+static void find_relocate(ELF_File * file, const char * name) {
+ /* Psedo-symbol, which helps debugger to map link-time address to run-time address */
+ size_t l = strlen(file->name);
+ size_t i = 0;
+ int ok = 0;
+ if (strncmp(file->name, name, l) == 0 && name[l] == ':') {
+ i = l + 1;
+ ok = 1;
+ }
+ if (!ok) {
+ size_t p = l;
+ while (p > 0 && file->name[p - 1] != '/' && file->name[p - 1] != '\\') p--;
+ if (strncmp(file->name + p, name, l - p) == 0 && name[l - p] == ':') {
+ i = l - p + 1;
+ ok = 1;
+ }
+ }
+ if (ok) {
+ size_t j = i;
+ char * section_name = NULL;
+ while (name[j] != 0 && name[j] != ':') j++;
+ if (j > i) section_name = tmp_strndup(name + i, j - i);
+ if (name[j++] == ':') {
+ ELF_Section * section = NULL;
+ ContextAddress addr = 0;
+ for (;;) {
+ char ch = name[j++];
+ if (ch >= '0' && ch <= '9') addr = (addr << 4) | (ch - '0');
+ else if (ch >= 'A' && ch <= 'F') addr = (addr << 4) | (ch - 'A' + 10);
+ else if (ch >= 'a' && ch <= 'f') addr = (addr << 4) | (ch - 'a' + 10);
+ else break;
+ }
+ if (section_name != NULL) {
+ unsigned n;
+ for (n = 1; n < file->section_cnt; n++) {
+ ELF_Section * s = file->sections + n;
+ if (s->name == NULL) continue;
+ if (strcmp(s->name, section_name) == 0) {
+ section = s;
+ break;
+ }
+ }
+ if (section == NULL) return;
+ }
+ addr = elf_map_to_run_time_address(sym_ctx, file, section, addr);
+ if (errno == 0) {
+ Symbol * sym = alloc_symbol();
+ sym->ctx = context_get_group(sym_ctx, CONTEXT_GROUP_SYMBOLS);
+ sym->frame = STACK_NO_FRAME;
+ sym->sym_class = SYM_CLASS_VALUE;
+ sym->address = addr;
+ sym->size = file->elf64 ? 8 : 4;
+ sym->has_address = 1;
+ assert(is_pointer_pseudo_symbol(sym));
+ add_to_find_symbol_buf(sym);
+ }
+ }
+ }
+}
+
int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char * name, Symbol ** res) {
int error = 0;
ELF_File * curr_file = NULL;
@@ -1691,8 +1752,13 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char
Trap trap;
if (set_trap(&trap)) {
DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
- find_by_name_in_pub_names(cache, name);
- find_by_name_in_sym_table(file, name, 0);
+ if (strncmp(name, "$relocate:", 10) == 0) {
+ find_relocate(file, name + 10);
+ }
+ else {
+ find_by_name_in_pub_names(cache, name);
+ find_by_name_in_sym_table(file, name, 0);
+ }
clear_trap(&trap);
}
else {
@@ -3193,6 +3259,10 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) {
*type_class = sym->dimension;
return 0;
}
+ if (is_pointer_pseudo_symbol(sym)) {
+ *type_class = TYPE_CLASS_POINTER;
+ return 0;
+ }
if (unpack(sym) < 0) return -1;
*type_class = TYPE_CLASS_UNKNOWN;
get_object_type_class(sym->obj, type_class);
@@ -3315,6 +3385,10 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) {
*size = sym->cardinal;
return 0;
}
+ if (is_pointer_pseudo_symbol(sym)) {
+ *size = sym->size;
+ return 0;
+ }
if (unpack(sym) < 0) return -1;
*size = 0;
if (obj != NULL) {
@@ -3922,7 +3996,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
assert(sym->magic == SYMBOL_MAGIC);
- if (sym->has_address) {
+ if (sym->has_address && sym->sym_class != SYM_CLASS_VALUE) {
info->big_endian = big_endian_host();
add_location_command(info, SFT_CMD_NUMBER)->args.num = sym->address;
return 0;
@@ -3950,6 +4024,21 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
return err_wrong_obj();
}
+ if (is_pointer_pseudo_symbol(sym)) {
+ void const * value = NULL;
+ LocationExpressionCommand * cmd = add_location_command(info, SFT_CMD_PIECE);
+
+ info->big_endian = big_endian_host();
+ cmd->args.piece.bit_size = (unsigned)(sym->size * 8);
+ cmd->args.piece.value = tmp_alloc((size_t)sym->size);
+ value = &sym->address;
+ if (big_endian_host() && sym->size < sizeof(ContextAddress)) {
+ value = (uint8_t *)value + (sizeof(ContextAddress) - sym->size);
+ }
+ memcpy(cmd->args.piece.value, value, (size_t)sym->size);
+ return 0;
+ }
+
if (unpack(sym) < 0) return -1;
if (obj != NULL) {

Back to the top