summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--loc2c-test.c42
-rw-r--r--loc2c.c32
-rw-r--r--loc2c.h5
-rw-r--r--tapsets.cxx42
4 files changed, 80 insertions, 41 deletions
diff --git a/loc2c-test.c b/loc2c-test.c
index 2967b9ed..4376b578 100644
--- a/loc2c-test.c
+++ b/loc2c-test.c
@@ -44,6 +44,34 @@ fail (void *arg __attribute__ ((unused)), const char *fmt, ...)
exit (2);
}
+static const Dwarf_Op *
+get_location (Dwarf_Addr dwbias, Dwarf_Addr pc, Dwarf_Attribute *loc_attr,
+ size_t *len)
+{
+ Dwarf_Op *expr;
+
+ switch (dwarf_getlocation_addr (loc_attr, pc - dwbias, &expr, len, 1))
+ {
+ case 1: /* Should always happen. */
+ if (*len == 0)
+ goto inaccessible;
+ break;
+
+ default: /* Shouldn't happen. */
+ case -1:
+ fail (NULL, _("dwarf_addrloclists (form %#x): %s"),
+ dwarf_whatform (loc_attr), dwarf_errmsg (-1));
+ return NULL;
+
+ case 0: /* Shouldn't happen. */
+ inaccessible:
+ fail (NULL, _("not accessible at this address"));
+ return NULL;
+ }
+
+ return expr;
+}
+
static void
handle_variable (Dwarf_Die *scopes, int nscopes, int out,
Dwarf_Addr cubias, Dwarf_Die *vardie, Dwarf_Addr pc,
@@ -86,9 +114,12 @@ handle_variable (Dwarf_Die *scopes, int nscopes, int out,
#define FIELD "addr"
#define emit(fmt, ...) printf (" addr = " fmt "\n", ## __VA_ARGS__)
+ size_t locexpr_len;
+ const Dwarf_Op *locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len);
+
struct location *head, *tail = NULL;
head = c_translate_location (&pool, &fail, NULL, NULL,
- 1, cubias, &attr_mem, pc,
+ 1, cubias, pc, locexpr, locexpr_len,
&tail, fb_attr);
if (dwarf_attr_integrate (vardie, DW_AT_type, &attr_mem) == NULL)
@@ -181,9 +212,12 @@ handle_variable (Dwarf_Die *scopes, int nscopes, int out,
*fields, dwarf_errmsg (-1));
}
else
- c_translate_location (&pool, NULL, NULL, NULL,
- 1, cubias, &attr_mem, pc,
- &tail, NULL);
+ {
+ locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len);
+ c_translate_location (&pool, NULL, NULL, NULL,
+ 1, cubias, pc, locexpr, locexpr_len,
+ &tail, NULL);
+ }
++fields;
break;
diff --git a/loc2c.c b/loc2c.c
index d6504474..a6b62fdc 100644
--- a/loc2c.c
+++ b/loc2c.c
@@ -965,34 +965,12 @@ c_translate_location (struct obstack *pool,
void *fail_arg,
void (*emit_address) (void *fail_arg,
struct obstack *, Dwarf_Addr),
- int indent, Dwarf_Addr dwbias,
- Dwarf_Attribute *loc_attr, Dwarf_Addr address,
+ int indent, Dwarf_Addr dwbias, Dwarf_Addr pc_address,
+ const Dwarf_Op *expr, size_t len,
struct location **input, Dwarf_Attribute *fb_attr)
{
- ++indent;
-
- Dwarf_Op *expr;
- size_t len;
- switch (dwarf_getlocation_addr (loc_attr, address - dwbias, &expr, &len, 1))
- {
- case 1: /* Should always happen. */
- if (len == 0)
- goto inaccessible;
- break;
-
- default: /* Shouldn't happen. */
- case -1:
- (*fail) (fail_arg, N_("dwarf_addrloclists (form %#x): %s"),
- dwarf_whatform (fb_attr), dwarf_errmsg (-1));
- return NULL;
+ indent += 2;
- case 0: /* Shouldn't happen. */
- inaccessible:
- (*fail) (fail_arg, N_("not accessible at this address"));
- return NULL;
- }
-
- ++indent;
switch (*input == NULL ? loc_address : (*input)->type)
{
case loc_address:
@@ -1000,14 +978,14 @@ c_translate_location (struct obstack *pool,
This expression will compute starting with that on the stack. */
return location_from_address (pool, fail, fail_arg,
emit_address ?: &default_emit_address,
- indent, dwbias, expr, len, address,
+ indent, dwbias, expr, len, pc_address,
input, fb_attr);
case loc_noncontiguous:
case loc_register:
/* The starting point is not an address computation, but a
register. We can only handle limited computations from here. */
- return location_relative (pool, indent, dwbias, expr, len, address,
+ return location_relative (pool, indent, dwbias, expr, len, pc_address,
input, fb_attr);
default:
diff --git a/loc2c.h b/loc2c.h
index d6617d55..9b0a7868 100644
--- a/loc2c.h
+++ b/loc2c.h
@@ -26,8 +26,9 @@ struct location *c_translate_location (struct obstack *,
Dwarf_Addr),
int indent,
Dwarf_Addr bias,
- Dwarf_Attribute *loc_attr,
- Dwarf_Addr address,
+ Dwarf_Addr pc_address,
+ const Dwarf_Op *locexpr,
+ size_t locexprlen,
struct location **input,
Dwarf_Attribute *fb_attr);
diff --git a/tapsets.cxx b/tapsets.cxx
index 5e6497f4..fdf1b999 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -934,6 +934,37 @@ dwflpp
}
+ struct location *
+ translate_location(struct obstack *pool,
+ Dwarf_Attribute *attr, Dwarf_Addr pc,
+ Dwarf_Attribute *fb_attr,
+ struct location **tail)
+ {
+ Dwarf_Op *expr;
+ size_t len;
+
+ switch (dwarf_getlocation_addr (attr, pc - module_bias, &expr, &len, 1))
+ {
+ case 1: /* Should always happen. */
+ if (len > 0)
+ break;
+ /* Fall through. */
+
+ case 0: /* Shouldn't happen. */
+ throw semantic_error ("not accessible at this address");
+
+ default: /* Shouldn't happen. */
+ case -1:
+ throw semantic_error (string ("dwarf_getlocation_addr failed") +
+ string (dwarf_errmsg (-1)));
+ }
+
+ return c_translate_location (pool, &loc2c_error, this,
+ &loc2c_emit_address,
+ 1, module_bias,
+ pc, expr, len, tail, fb_attr);
+ }
+
Dwarf_Die *
translate_components(struct obstack *pool,
struct location **tail,
@@ -1015,9 +1046,7 @@ dwflpp
+ " :" + string(dwarf_errmsg (-1)));
}
else
- c_translate_location (pool, NULL, NULL, NULL, 1,
- module_bias, attr_mem, pc,
- tail, NULL);
+ translate_location (pool, attr_mem, pc, NULL, tail);
++i;
break;
@@ -1195,11 +1224,8 @@ dwflpp
/* Given $foo->bar->baz[NN], translate the location of foo. */
- struct location *head = c_translate_location (&pool, &loc2c_error, this,
- &loc2c_emit_address,
- 1, module_bias,
- &attr_mem, pc,
- &tail, fb_attr);
+ struct location *head = translate_location (&pool,
+ &attr_mem, pc, fb_attr, &tail);
if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
throw semantic_error("failed to retrieve type "