summaryrefslogtreecommitdiffstats
path: root/loc2c.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-09-16 15:22:45 -0700
committerRoland McGrath <roland@redhat.com>2009-09-16 15:22:45 -0700
commit45d7e32572c4aafde1428b305541330aaf2692f3 (patch)
tree6a26dc199f8f37f0d055889ce29a569bf4e0b896 /loc2c.c
parent6be6402d1514d149e6e6adf66a5c50b80b8bbb0f (diff)
downloadsystemtap-steved-45d7e32572c4aafde1428b305541330aaf2692f3.tar.gz
systemtap-steved-45d7e32572c4aafde1428b305541330aaf2692f3.tar.xz
systemtap-steved-45d7e32572c4aafde1428b305541330aaf2692f3.zip
* loc2c.c: Handle DW_OP_stack_value. Untested and probably unfinished.
Diffstat (limited to 'loc2c.c')
-rw-r--r--loc2c.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/loc2c.c b/loc2c.c
index 5cf59691..c5859df4 100644
--- a/loc2c.c
+++ b/loc2c.c
@@ -51,13 +51,13 @@ struct location
enum
{
- loc_address, loc_register, loc_noncontiguous,
+ loc_address, loc_register, loc_noncontiguous, loc_value,
loc_decl, loc_fragment, loc_final
} type;
struct location *frame_base;
union
{
- struct /* loc_address, loc_fragment, loc_final */
+ struct /* loc_address, loc_value, loc_fragment, loc_final */
{
const char *declare; /* Temporary that needs declared. */
char *program; /* C fragment, leaves address in s0. */
@@ -212,6 +212,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
size_t i;
+ bool tos_value = false;
bool used_deref = false;
inline const char *finish (struct location *piece)
{
@@ -221,12 +222,13 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
{
obstack_1grow (pool, '\0');
char *program = obstack_finish (pool);
- piece->type = loc_address;
+ piece->type = tos_value ? loc_value : loc_address;
piece->address.declare = NULL;
piece->address.program = program;
piece->address.stack_depth = max_stack;
piece->address.used_deref = used_deref;
used_deref = false;
+ tos_value = false;
}
else if (tos_register == -1)
DIE ("stack underflow");
@@ -250,6 +252,12 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
uint_fast8_t sp;
Dwarf_Word value;
+ if (tos_value
+ && expr[i].atom != DW_OP_nop
+ && expr[i].atom != DW_OP_piece
+ && expr[i].atom != DW_OP_bit_piece)
+ DIE ("operations follow DW_OP_stack_value");
+
switch (expr[i].atom)
{
/* Basic stack operations. */
@@ -525,6 +533,20 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
}
break;
+ case DW_OP_stack_value:
+ if (stack_depth > 1)
+ DIE ("DW_OP_stack_value left multiple values on stack");
+ else
+ {
+ /* Fetch a register to top of stack, or check for underflow.
+ Then mark the TOS as being a value. */
+ POP (tos);
+ assert (tos == 0);
+ PUSH;
+ tos_value = true;
+ }
+ break;
+
case DW_OP_call_frame_cfa:
// We pick this out when processing DW_AT_frame_base in
// so it really shouldn't turn up here.
@@ -1051,6 +1073,7 @@ c_translate_location (struct obstack *pool,
case loc_noncontiguous:
case loc_register:
+ case loc_value:
/* 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, pc_address,
@@ -1115,6 +1138,10 @@ emit_base_fetch (struct obstack *pool, Dwarf_Word byte_size,
switch (loc->type)
{
+ case loc_value:
+ obstack_printf (pool, "addr;");
+ break;
+
case loc_address:
if (byte_size != 0 && byte_size != (Dwarf_Word) -1)
obstack_printf (pool, "deref (%" PRIu64 ", addr);", byte_size);
@@ -1169,6 +1196,10 @@ emit_base_store (struct obstack *pool, Dwarf_Word byte_size,
FAIL (loc, N_("noncontiguous location for base store"));
break;
+ case loc_value:
+ FAIL (loc, N_("location is computed value, cannot store"));
+ break;
+
default:
abort ();
break;
@@ -1245,6 +1276,10 @@ discontiguify (struct obstack *pool, int indent, struct location *loc,
break;
}
+ case loc_value:
+ FAIL (loc, N_("stack value too big for fetch ???"));
+ break;
+
case loc_register:
FAIL (loc, N_("single register too big for fetch/store ???"));
break;
@@ -1675,6 +1710,9 @@ c_translate_addressof (struct obstack *pool, int indent,
case loc_noncontiguous:
FAIL (*input, N_("cannot take address of noncontiguous object"));
break;
+ case loc_value:
+ FAIL (*input, N_("cannot take address of computed value"));
+ break;
default:
abort();
@@ -1822,6 +1860,10 @@ c_translate_array (struct obstack *pool, int indent,
}
break;
+ case loc_value:
+ FAIL (*input, N_("cannot index into computed value"));
+ break;
+
default:
abort();
break;