summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dwflpp.cxx20
-rw-r--r--loc2c-test.c33
-rw-r--r--loc2c.c31
-rw-r--r--loc2c.h7
4 files changed, 86 insertions, 5 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index de994c18..17bce608 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -1449,6 +1449,24 @@ dwflpp::translate_location(struct obstack *pool,
struct location **tail,
const target_symbol *e)
{
+
+ /* DW_AT_data_member_location, can be either constant offsets
+ (struct member fields), or full blown location expressions. */
+ if (dwarf_whatattr (attr) == DW_AT_data_member_location)
+ {
+ unsigned int form = dwarf_whatform (attr);
+ if (form == DW_FORM_data1 || form == DW_FORM_data2
+ || form == DW_FORM_sdata || form == DW_FORM_udata)
+ {
+ Dwarf_Sword off;
+ if (dwarf_formsdata (attr, &off) != 0)
+ throw semantic_error (string ("dwarf_formsdata failed, ")
+ + string (dwarf_errmsg (-1)), e->tok);
+ c_translate_add_offset (pool, 1, NULL, off, tail);
+ return *tail;
+ }
+ }
+
Dwarf_Op *expr;
size_t len;
@@ -1470,7 +1488,7 @@ dwflpp::translate_location(struct obstack *pool,
default: /* Shouldn't happen. */
case -1:
- throw semantic_error (string ("dwarf_getlocation_addr failed") +
+ throw semantic_error (string ("dwarf_getlocation_addr failed, ") +
string (dwarf_errmsg (-1)),
e->tok);
}
diff --git a/loc2c-test.c b/loc2c-test.c
index 01108573..688f4a8b 100644
--- a/loc2c-test.c
+++ b/loc2c-test.c
@@ -214,10 +214,35 @@ handle_variable (Dwarf_Die *scopes, int nscopes, int out,
}
else
{
- locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len);
- c_translate_location (&pool, NULL, NULL, NULL,
- 1, cubias, pc, locexpr, locexpr_len,
- &tail, NULL);
+ /* We are expection a block, constant or loclistptr. */
+ unsigned int form = dwarf_whatform (&attr_mem);
+ Dwarf_Sword off;
+ switch (form)
+ {
+ /* constant */
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ if (dwarf_formsdata (&attr_mem, &off) != 0)
+ error (2, 0, _("Bad offset for %s %s: %s"),
+ typetag == DW_TAG_union_type ? "union" : "struct",
+ dwarf_diename_integrate (die) ?: "<anonymous>",
+ dwarf_errmsg (-1));
+ if (off != 0)
+ c_translate_add_offset (&pool, 1,
+ dwarf_diename_integrate (die)
+ ?: "", off, &tail);
+ break;
+
+ default:
+ locexpr = get_location (cubias, pc, &attr_mem,
+ &locexpr_len);
+ c_translate_location (&pool, NULL, NULL, NULL,
+ 1, cubias, pc, locexpr, locexpr_len,
+ &tail, NULL);
+ break;
+ }
}
++fields;
break;
diff --git a/loc2c.c b/loc2c.c
index f95400bb..5f4e4495 100644
--- a/loc2c.c
+++ b/loc2c.c
@@ -1669,7 +1669,38 @@ c_translate_pointer_store (struct obstack *pool, int indent,
}
+/* Translate a fragment to add an offset to the currently calculated
+ address of the input location. Used for struct fields. Only works
+ when location is already an actual base address.
+*/
+void
+c_translate_add_offset (struct obstack *pool, int indent, const char *comment,
+ Dwarf_Sword off, struct location **input)
+{
+ indent++;
+ if (comment == NULL || comment[0] == '\0')
+ comment = "field offset";
+ switch ((*input)->type)
+ {
+ case loc_address:
+ obstack_printf (pool, "%*saddr += " SFORMAT "; // %s\n",
+ indent * 2 + 2, "", off, comment);
+ *input = (*input)->next = new_synthetic_loc (pool, *input, false);
+ break;
+
+ case loc_register:
+ FAIL (*input, N_("cannot add offset of object in register"));
+ break;
+ case loc_noncontiguous:
+ FAIL (*input, N_("cannot add offset of noncontiguous object"));
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+}
/* Determine the element stride of an array type. */
static Dwarf_Word
diff --git a/loc2c.h b/loc2c.h
index 0ad5ae99..eb1f39d6 100644
--- a/loc2c.h
+++ b/loc2c.h
@@ -85,6 +85,13 @@ c_translate_pointer_store (struct obstack *pool, int indent,
Dwarf_Die *typedie, struct location **input,
const char *rvalue);
+/* Translate a fragment to add an offset to the currently calculated
+ address of the input location. Used for struct fields. Only works
+ when location is already an actual base address. */
+void
+c_translate_add_offset (struct obstack *pool, int indent, const char *comment,
+ Dwarf_Sword off, struct location **input);
+
/* Translate a C fragment for a direct argument VALUE. On errors, call FAIL,
which should not return. Any later errors will use FAIL and FAIL_ARG from
this translate call. On success, return the fragment created. */