retval->stack_len = 0;
retval->stack_allocated = 10;
retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
+ retval->num_pieces = 0;
+ retval->pieces = 0;
return retval;
}
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
{
xfree (ctx->stack);
+ xfree (ctx->pieces);
xfree (ctx);
}
}
+/* Add a new piece to CTX's piece list. */
+static void
+add_piece (struct dwarf_expr_context *ctx,
+ int in_reg, CORE_ADDR value, ULONGEST size)
+{
+ struct dwarf_expr_piece *p;
+
+ ctx->num_pieces++;
+
+ if (ctx->pieces)
+ ctx->pieces = xrealloc (ctx->pieces,
+ (ctx->num_pieces
+ * sizeof (struct dwarf_expr_piece)));
+ else
+ ctx->pieces = xmalloc (ctx->num_pieces
+ * sizeof (struct dwarf_expr_piece));
+
+ p = &ctx->pieces[ctx->num_pieces - 1];
+ p->in_reg = in_reg;
+ p->value = value;
+ p->size = size;
+}
+
/* Evaluate the expression at ADDR (LEN bytes long) using the context
CTX. */
error ("dwarf2_read_address: Corrupted DWARF expression.");
*bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
- result = extract_address (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+ /* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2
+ address is always unsigned. That may or may not be true. */
+ result = extract_unsigned_integer (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
return result;
}
result = dwarf_expr_fetch (ctx, 0);
if (ctx->in_reg)
result = (ctx->read_reg) (ctx->baton, result);
- else
- {
- char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
- int bytes_read;
-
- (ctx->read_mem) (ctx->baton, buf, result,
- TARGET_ADDR_BIT / TARGET_CHAR_BIT);
- result = dwarf2_read_address (buf,
- buf + (TARGET_ADDR_BIT
- / TARGET_CHAR_BIT),
- &bytes_read);
- }
result = result + offset;
ctx->stack_len = before_stack_len;
ctx->in_reg = 0;
second = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
- first = dwarf_expr_fetch (ctx, 1);
+ first = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
val1 = value_from_longest (unsigned_address_type (), first);
break;
case DW_OP_div:
binop = BINOP_DIV;
+ break;
case DW_OP_minus:
binop = BINOP_SUB;
break;
break;
case DW_OP_shr:
binop = BINOP_RSH;
+ break;
case DW_OP_shra:
binop = BINOP_RSH;
val1 = value_from_longest (signed_address_type (), first);
break;
case DW_OP_GNU_push_tls_address:
+ /* Variable is at a constant offset in the thread-local
+ storage block into the objfile for the current thread and
+ the dynamic linker module containing this expression. Here
+ we return returns the offset from that base. The top of the
+ stack has the offset from the beginning of the thread
+ control block at which the variable is located. Nothing
+ should follow this operator, so the top of stack would be
+ returned. */
result = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
result = (ctx->get_tls_address) (ctx->baton, result);
case DW_OP_nop:
goto no_push;
+ case DW_OP_piece:
+ {
+ ULONGEST size;
+ CORE_ADDR addr_or_regnum;
+
+ /* Record the piece. */
+ op_ptr = read_uleb128 (op_ptr, op_end, &size);
+ addr_or_regnum = dwarf_expr_fetch (ctx, 0);
+ add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
+
+ /* Pop off the address/regnum, and clear the in_reg flag. */
+ dwarf_expr_pop (ctx);
+ ctx->in_reg = 0;
+ }
+ goto no_push;
+
default:
- error ("Unhandled dwarf expression opcode");
+ error ("Unhandled dwarf expression opcode 0x%x", op);
}
/* Most things push a result value. */