diff options
-rw-r--r-- | loc2c-test.c | 36 | ||||
-rw-r--r-- | loc2c.c | 103 | ||||
-rw-r--r-- | loc2c.h | 14 |
3 files changed, 137 insertions, 16 deletions
diff --git a/loc2c-test.c b/loc2c-test.c index 495a95f1..17edf1a8 100644 --- a/loc2c-test.c +++ b/loc2c-test.c @@ -122,22 +122,29 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out, } } - Dwarf_Attribute attr_mem; + struct location *head, *tail = NULL; - if (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL) - error (2, 0, _("cannot get location of variable: %s"), - dwarf_errmsg (-1)); + Dwarf_Attribute attr_mem; + if (dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) != NULL) + /* There is no location expression, but a constant value instead. */ + head = tail = c_translate_constant (&pool, &fail, NULL, NULL, + 1, cubias, &attr_mem); + else + { -#define FIELD "addr" -#define emit(fmt, ...) printf (" addr = " fmt "\n", ## __VA_ARGS__) + if (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL) + error (2, 0, _("cannot get location of variable: %s"), + dwarf_errmsg (-1)); - size_t locexpr_len; - const Dwarf_Op *locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len); + 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, pc, &attr_mem, locexpr, locexpr_len, - &tail, fb_attr, cfa_ops); + head = c_translate_location (&pool, &fail, NULL, NULL, + 1, cubias, pc, &attr_mem, + locexpr, locexpr_len, + &tail, fb_attr, cfa_ops); + } if (dwarf_attr_integrate (vardie, DW_AT_type, &attr_mem) == NULL) error (2, 0, _("cannot get type of variable: %s"), @@ -244,8 +251,9 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out, else #endif { - locexpr = get_location (cubias, pc, &attr_mem, - &locexpr_len); + size_t locexpr_len; + const Dwarf_Op *locexpr = get_location (cubias, pc, &attr_mem, + &locexpr_len); c_translate_location (&pool, NULL, NULL, NULL, 1, cubias, pc, &attr_mem, locexpr, locexpr_len, @@ -1152,6 +1152,105 @@ c_translate_location (struct obstack *pool, return NULL; } +/* Translate a DW_AT_const_value attribute as if it were a location of + constant-value flavor. */ + +struct location * +c_translate_constant (struct obstack *pool, + void (*fail) (void *arg, + const char *fmt, ...) + __attribute__ ((noreturn, + format (printf, 2, 3))), + void *fail_arg, + void (*emit_address) (void *fail_arg, + struct obstack *, + Dwarf_Addr), + int indent, Dwarf_Addr dwbias, Dwarf_Attribute *attr) +{ + indent += 2; + + struct location *loc = obstack_alloc (pool, sizeof *loc); + loc->fail = fail; + loc->fail_arg = fail_arg; + loc->emit_address = emit_address ?: &default_emit_address; + loc->byte_size = 0; + loc->frame_base = NULL; + loc->address.stack_depth = 0; + loc->address.declare = NULL; + loc->address.used_deref = false; + + switch (dwarf_whatform (attr)) + { + case DW_FORM_addr: + { + Dwarf_Addr addr; + if (dwarf_formaddr (attr, &addr) != 0) + { + FAIL (loc, N_("cannot get constant address: %s"), + dwarf_errmsg (-1)); + return NULL; + } + loc->type = loc_value; + obstack_printf (pool, "%*saddr = ", indent * 2, ""); + (*loc->emit_address) (loc->fail_arg, pool, dwbias + addr); + obstack_grow (pool, ";\n", 3); + loc->address.program = obstack_finish (pool); + break; + } + + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + { + Dwarf_Block block; + if (dwarf_formblock (attr, &block) != 0) + { + FAIL (loc, N_("cannot get constant block: %s"), dwarf_errmsg (-1)); + return NULL; + } + loc->type = loc_constant; + loc->byte_size = block.length; + loc->constant_block = block.data; + break; + } + + case DW_FORM_string: + case DW_FORM_strp: + { + const char *string = dwarf_formstring (attr); + if (string == NULL) + { + FAIL (loc, N_("cannot get string constant: %s"), dwarf_errmsg (-1)); + return NULL; + } + loc->type = loc_constant; + loc->byte_size = strlen (string) + 1; + loc->constant_block = string; + break; + } + + default: + { + Dwarf_Sword value; + if (dwarf_formsdata (attr, &value) != 0) + { + FAIL (loc, N_("cannot get constant value: %s"), dwarf_errmsg (-1)); + return NULL; + } + loc->type = loc_value; + obstack_printf (pool, "%*saddr = %" PRId64 "L\n;", + indent * 2, "", value); + obstack_1grow (pool, '\0'); + loc->address.program = obstack_finish (pool); + break; + } + } + + return loc; +} + + /* 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. */ @@ -1166,7 +1265,7 @@ c_translate_argument (struct obstack *pool, { indent += 2; - obstack_printf(pool, "%*saddr = %s;\n", indent * 2, "", value); + obstack_printf (pool, "%*saddr = %s;\n", indent * 2, "", value); obstack_1grow (pool, '\0'); char *program = obstack_finish (pool); @@ -1174,7 +1273,7 @@ c_translate_argument (struct obstack *pool, loc->next = NULL; loc->fail = fail; loc->fail_arg = fail_arg; - loc->emit_address = emit_address; + loc->emit_address = emit_address ?: &default_emit_address; loc->ops = NULL; loc->nops = 0; loc->byte_size = 0; @@ -41,6 +41,20 @@ struct location *c_translate_location (struct obstack *, Dwarf_Attribute *fb_attr, const Dwarf_Op *cfa_ops); +/* Translate a fragment for a compile-time constant from DW_AT_const_value. + */ +struct location *c_translate_constant (struct obstack *, + void (*fail) (void *arg, + const char *fmt, ...) + __attribute__ ((noreturn, + format (printf, 2, 3))), + void *fail_arg, + void (*emit_address) (void *fail_arg, + struct obstack *, + Dwarf_Addr), + int indent, Dwarf_Addr dwbias, + Dwarf_Attribute *attr); + /* Translate a fragment to dereference the given DW_TAG_pointer_type DIE, where *INPUT is the location of the pointer with that type. */ void c_translate_pointer (struct obstack *pool, int indent, |