gdb
PR gdb/12617: * value.h (value_from_contents): Declare. * value.c (value_from_contents): New function. * dwarf2read.c (dwarf_stack_op_name): Add new values. (dwarf2_get_die_type): New function. * dwarf2loc.c (dwarf_expr_get_base_type): New function. (allocate_piece_closure): Acquire reference to values. (read_pieced_value): Update for value-based expressions. (write_pieced_value): Likewise. (free_pieced_value_closure): Call value_free as needed. (dwarf2_evaluate_loc_desc_full): Set get_base_type field. Update for value-based expressions. * dwarf2loc.h (dwarf2_get_die_type): Declare. * dwarf2expr.h (struct dwarf_stack_value) <value>: Change type. <get_base_type>: New field. (struct dwarf_expr_piece) <v.value>: Change type. <v.regno>: New field. (struct dwarf_expr_context) <mark>: New field. (dwarf_expr_piece, dwarf_expr_fetch): Update. (dwarf_expr_pop, dwarf_expr_push): Remove. (dwarf_expr_push_address): Declare. * dwarf2expr.c (dwarf_arch_cookie): New global. (struct dwarf_gdbarch_types): New. (dwarf_gdbarch_types_init, dwarf_expr_address_type): New functions. (dwarf_expr_push): Change type of 'value' argument. Update. Now static. (dwarf_expr_push_address): New function. (dwarf_expr_pop): Now static. (dwarf_expr_fetch): Change return type. (dwarf_require_integral): New function. (dwarf_expr_fetch): Simplify. (add_piece): Update. (base_types_equal_p, dwarf_get_base_type, get_unsigned_type): New functions. (execute_stack_op) <sign_ext>: Remove. Use values for DWARF stack. <DW_OP_GNU_const_type, DW_OP_GNU_deref_type, DW_OP_GNU_regval_type, DW_OP_GNU_convert, DW_OP_GNU_reinterpret>: New cases. (_initialize_dwarf2expr): New function. (add_piece): Update. (new_dwarf_expr_context): Set new field. (free_dwarf_expr_context): Call value_free_to_mark. * dwarf2-frame.c (no_base_type): New function. (execute_stack_op): Set get_base_type field. Update. gdb/testsuite * gdb.dwarf2/typeddwarf.S: New file. * gdb.dwarf2/typeddwarf.c: New file. * gdb.dwarf2/typeddwarf.exp: New file.
This commit is contained in:
parent
e8d28ef4f3
commit
8a9b8146fd
13 changed files with 2971 additions and 123 deletions
|
@ -1,3 +1,52 @@
|
|||
2011-05-12 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR gdb/12617:
|
||||
* value.h (value_from_contents): Declare.
|
||||
* value.c (value_from_contents): New function.
|
||||
* dwarf2read.c (dwarf_stack_op_name): Add new values.
|
||||
(dwarf2_get_die_type): New function.
|
||||
* dwarf2loc.c (dwarf_expr_get_base_type): New function.
|
||||
(allocate_piece_closure): Acquire reference to values.
|
||||
(read_pieced_value): Update for value-based expressions.
|
||||
(write_pieced_value): Likewise.
|
||||
(free_pieced_value_closure): Call value_free as needed.
|
||||
(dwarf2_evaluate_loc_desc_full): Set get_base_type field.
|
||||
Update for value-based expressions.
|
||||
* dwarf2loc.h (dwarf2_get_die_type): Declare.
|
||||
* dwarf2expr.h (struct dwarf_stack_value) <value>: Change type.
|
||||
<get_base_type>: New field.
|
||||
(struct dwarf_expr_piece) <v.value>: Change type.
|
||||
<v.regno>: New field.
|
||||
(struct dwarf_expr_context) <mark>: New field.
|
||||
(dwarf_expr_piece, dwarf_expr_fetch): Update.
|
||||
(dwarf_expr_pop, dwarf_expr_push): Remove.
|
||||
(dwarf_expr_push_address): Declare.
|
||||
* dwarf2expr.c (dwarf_arch_cookie): New global.
|
||||
(struct dwarf_gdbarch_types): New.
|
||||
(dwarf_gdbarch_types_init, dwarf_expr_address_type): New
|
||||
functions.
|
||||
(dwarf_expr_push): Change type of 'value' argument. Update. Now
|
||||
static.
|
||||
(dwarf_expr_push_address): New function.
|
||||
(dwarf_expr_pop): Now static.
|
||||
(dwarf_expr_fetch): Change return type.
|
||||
(dwarf_require_integral): New function.
|
||||
(dwarf_expr_fetch): Simplify.
|
||||
(add_piece): Update.
|
||||
(base_types_equal_p, dwarf_get_base_type, get_unsigned_type): New
|
||||
functions.
|
||||
(execute_stack_op) <sign_ext>: Remove.
|
||||
Use values for DWARF stack.
|
||||
<DW_OP_GNU_const_type, DW_OP_GNU_deref_type,
|
||||
DW_OP_GNU_regval_type, DW_OP_GNU_convert, DW_OP_GNU_reinterpret>:
|
||||
New cases.
|
||||
(_initialize_dwarf2expr): New function.
|
||||
(add_piece): Update.
|
||||
(new_dwarf_expr_context): Set new field.
|
||||
(free_dwarf_expr_context): Call value_free_to_mark.
|
||||
* dwarf2-frame.c (no_base_type): New function.
|
||||
(execute_stack_op): Set get_base_type field. Update.
|
||||
|
||||
2011-05-12 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* dwarf2read.c (read_common_block): Fix formatting.
|
||||
|
|
|
@ -353,6 +353,14 @@ no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
|
|||
_("Support for DW_OP_call* is invalid in CFI"));
|
||||
}
|
||||
|
||||
/* Helper function for execute_stack_op. */
|
||||
|
||||
static struct type *
|
||||
no_base_type (struct dwarf_expr_context *ctx, size_t die)
|
||||
{
|
||||
error (_("Support for typed DWARF is not supported in CFI"));
|
||||
}
|
||||
|
||||
/* Execute the required actions for both the DW_CFA_restore and
|
||||
DW_CFA_restore_extended instructions. */
|
||||
static void
|
||||
|
@ -406,14 +414,15 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
|
|||
ctx->get_frame_pc = no_get_frame_pc;
|
||||
ctx->get_tls_address = no_get_tls_address;
|
||||
ctx->dwarf_call = no_dwarf_call;
|
||||
ctx->get_base_type = no_base_type;
|
||||
|
||||
dwarf_expr_push (ctx, initial, initial_in_stack_memory);
|
||||
dwarf_expr_push_address (ctx, initial, initial_in_stack_memory);
|
||||
dwarf_expr_eval (ctx, exp, len);
|
||||
|
||||
if (ctx->location == DWARF_VALUE_MEMORY)
|
||||
result = dwarf_expr_fetch_address (ctx, 0);
|
||||
else if (ctx->location == DWARF_VALUE_REGISTER)
|
||||
result = read_reg (this_frame, dwarf_expr_fetch (ctx, 0));
|
||||
result = read_reg (this_frame, value_as_long (dwarf_expr_fetch (ctx, 0)));
|
||||
else
|
||||
{
|
||||
/* This is actually invalid DWARF, but if we ever do run across
|
||||
|
|
474
gdb/dwarf2expr.c
474
gdb/dwarf2expr.c
|
@ -34,6 +34,61 @@
|
|||
static void execute_stack_op (struct dwarf_expr_context *,
|
||||
const gdb_byte *, const gdb_byte *);
|
||||
|
||||
/* Cookie for gdbarch data. */
|
||||
|
||||
static struct gdbarch_data *dwarf_arch_cookie;
|
||||
|
||||
/* This holds gdbarch-specific types used by the DWARF expression
|
||||
evaluator. See comments in execute_stack_op. */
|
||||
|
||||
struct dwarf_gdbarch_types
|
||||
{
|
||||
struct type *dw_types[3];
|
||||
};
|
||||
|
||||
/* Allocate and fill in dwarf_gdbarch_types for an arch. */
|
||||
|
||||
static void *
|
||||
dwarf_gdbarch_types_init (struct gdbarch *gdbarch)
|
||||
{
|
||||
struct dwarf_gdbarch_types *types
|
||||
= GDBARCH_OBSTACK_ZALLOC (gdbarch, struct dwarf_gdbarch_types);
|
||||
|
||||
/* The types themselves are lazily initialized. */
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/* Return the type used for DWARF operations where the type is
|
||||
unspecified in the DWARF spec. Only certain sizes are
|
||||
supported. */
|
||||
|
||||
static struct type *
|
||||
dwarf_expr_address_type (struct dwarf_expr_context *ctx)
|
||||
{
|
||||
struct dwarf_gdbarch_types *types = gdbarch_data (ctx->gdbarch,
|
||||
dwarf_arch_cookie);
|
||||
int ndx;
|
||||
|
||||
if (ctx->addr_size == 2)
|
||||
ndx = 0;
|
||||
else if (ctx->addr_size == 4)
|
||||
ndx = 1;
|
||||
else if (ctx->addr_size == 8)
|
||||
ndx = 2;
|
||||
else
|
||||
error (_("Unsupported address size in DWARF expressions: %d bits"),
|
||||
8 * ctx->addr_size);
|
||||
|
||||
if (types->dw_types[ndx] == NULL)
|
||||
types->dw_types[ndx]
|
||||
= arch_integer_type (ctx->gdbarch,
|
||||
8 * ctx->addr_size,
|
||||
0, "<signed DWARF address type>");
|
||||
|
||||
return types->dw_types[ndx];
|
||||
}
|
||||
|
||||
/* Create a new context for the expression evaluator. */
|
||||
|
||||
struct dwarf_expr_context *
|
||||
|
@ -49,6 +104,7 @@ new_dwarf_expr_context (void)
|
|||
retval->num_pieces = 0;
|
||||
retval->pieces = 0;
|
||||
retval->max_recursion_depth = 0x100;
|
||||
retval->mark = value_mark ();
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -57,6 +113,7 @@ new_dwarf_expr_context (void)
|
|||
void
|
||||
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
|
||||
{
|
||||
value_free_to_mark (ctx->mark);
|
||||
xfree (ctx->stack);
|
||||
xfree (ctx->pieces);
|
||||
xfree (ctx);
|
||||
|
@ -96,26 +153,32 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
|
|||
|
||||
/* Push VALUE onto CTX's stack. */
|
||||
|
||||
void
|
||||
dwarf_expr_push (struct dwarf_expr_context *ctx, ULONGEST value,
|
||||
static void
|
||||
dwarf_expr_push (struct dwarf_expr_context *ctx, struct value *value,
|
||||
int in_stack_memory)
|
||||
{
|
||||
struct dwarf_stack_value *v;
|
||||
|
||||
/* We keep all stack elements within the range defined by the
|
||||
DWARF address size. */
|
||||
if (ctx->addr_size < sizeof (ULONGEST))
|
||||
value &= ((ULONGEST) 1 << (ctx->addr_size * HOST_CHAR_BIT)) - 1;
|
||||
|
||||
dwarf_expr_grow_stack (ctx, 1);
|
||||
v = &ctx->stack[ctx->stack_len++];
|
||||
v->value = value;
|
||||
v->in_stack_memory = in_stack_memory;
|
||||
}
|
||||
|
||||
/* Pop the top item off of CTX's stack. */
|
||||
/* Push VALUE onto CTX's stack. */
|
||||
|
||||
void
|
||||
dwarf_expr_push_address (struct dwarf_expr_context *ctx, CORE_ADDR value,
|
||||
int in_stack_memory)
|
||||
{
|
||||
dwarf_expr_push (ctx,
|
||||
value_from_ulongest (dwarf_expr_address_type (ctx), value),
|
||||
in_stack_memory);
|
||||
}
|
||||
|
||||
/* Pop the top item off of CTX's stack. */
|
||||
|
||||
static void
|
||||
dwarf_expr_pop (struct dwarf_expr_context *ctx)
|
||||
{
|
||||
if (ctx->stack_len <= 0)
|
||||
|
@ -125,7 +188,7 @@ dwarf_expr_pop (struct dwarf_expr_context *ctx)
|
|||
|
||||
/* Retrieve the N'th item on CTX's stack. */
|
||||
|
||||
ULONGEST
|
||||
struct value *
|
||||
dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
|
||||
{
|
||||
if (ctx->stack_len <= n)
|
||||
|
@ -133,7 +196,39 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
|
|||
"stack only has %d elements on it."),
|
||||
n, ctx->stack_len);
|
||||
return ctx->stack[ctx->stack_len - (1 + n)].value;
|
||||
}
|
||||
|
||||
/* Require that TYPE be an integral type; throw an exception if not. */
|
||||
|
||||
static void
|
||||
dwarf_require_integral (struct type *type)
|
||||
{
|
||||
if (TYPE_CODE (type) != TYPE_CODE_INT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_CHAR
|
||||
&& TYPE_CODE (type) != TYPE_CODE_BOOL)
|
||||
error (_("integral type expected in DWARF expression"));
|
||||
}
|
||||
|
||||
/* Return the unsigned form of TYPE. TYPE is necessarily an integral
|
||||
type. */
|
||||
|
||||
static struct type *
|
||||
get_unsigned_type (struct gdbarch *gdbarch, struct type *type)
|
||||
{
|
||||
switch (TYPE_LENGTH (type))
|
||||
{
|
||||
case 1:
|
||||
return builtin_type (gdbarch)->builtin_uint8;
|
||||
case 2:
|
||||
return builtin_type (gdbarch)->builtin_uint16;
|
||||
case 4:
|
||||
return builtin_type (gdbarch)->builtin_uint32;
|
||||
case 8:
|
||||
return builtin_type (gdbarch)->builtin_uint64;
|
||||
default:
|
||||
error (_("no unsigned variant found for type, while evaluating "
|
||||
"DWARF expression"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Retrieve the N'th item on CTX's stack, converted to an address. */
|
||||
|
@ -141,7 +236,14 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
|
|||
CORE_ADDR
|
||||
dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n)
|
||||
{
|
||||
ULONGEST result = dwarf_expr_fetch (ctx, n);
|
||||
struct value *result_val = dwarf_expr_fetch (ctx, n);
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
|
||||
ULONGEST result;
|
||||
|
||||
dwarf_require_integral (value_type (result_val));
|
||||
result = extract_unsigned_integer (value_contents (result_val),
|
||||
TYPE_LENGTH (value_type (result_val)),
|
||||
byte_order);
|
||||
|
||||
/* For most architectures, calling extract_unsigned_integer() alone
|
||||
is sufficient for extracting an address. However, some
|
||||
|
@ -151,25 +253,9 @@ dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n)
|
|||
for those architectures which require it. */
|
||||
if (gdbarch_integer_to_address_p (ctx->gdbarch))
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
|
||||
gdb_byte *buf = alloca (ctx->addr_size);
|
||||
struct type *int_type;
|
||||
|
||||
switch (ctx->addr_size)
|
||||
{
|
||||
case 2:
|
||||
int_type = builtin_type (ctx->gdbarch)->builtin_uint16;
|
||||
break;
|
||||
case 4:
|
||||
int_type = builtin_type (ctx->gdbarch)->builtin_uint32;
|
||||
break;
|
||||
case 8:
|
||||
int_type = builtin_type (ctx->gdbarch)->builtin_uint64;
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Unsupported address size.\n"));
|
||||
}
|
||||
struct type *int_type = get_unsigned_type (ctx->gdbarch,
|
||||
value_type (result_val));
|
||||
|
||||
store_unsigned_integer (buf, ctx->addr_size, byte_order, result);
|
||||
return gdbarch_integer_to_address (ctx->gdbarch, int_type, buf);
|
||||
|
@ -188,7 +274,6 @@ dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n)
|
|||
"stack only has %d elements on it."),
|
||||
n, ctx->stack_len);
|
||||
return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory;
|
||||
|
||||
}
|
||||
|
||||
/* Return true if the expression stack is empty. */
|
||||
|
@ -238,8 +323,10 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset)
|
|||
else if (p->location == DWARF_VALUE_IMPLICIT_POINTER)
|
||||
{
|
||||
p->v.ptr.die = ctx->len;
|
||||
p->v.ptr.offset = (LONGEST) dwarf_expr_fetch (ctx, 0);
|
||||
p->v.ptr.offset = value_as_long (dwarf_expr_fetch (ctx, 0));
|
||||
}
|
||||
else if (p->location == DWARF_VALUE_REGISTER)
|
||||
p->v.regno = value_as_long (dwarf_expr_fetch (ctx, 0));
|
||||
else
|
||||
{
|
||||
p->v.value = dwarf_expr_fetch (ctx, 0);
|
||||
|
@ -335,6 +422,43 @@ dwarf_expr_require_composition (const gdb_byte *op_ptr, const gdb_byte *op_end,
|
|||
op_name);
|
||||
}
|
||||
|
||||
/* Return true iff the types T1 and T2 are "the same". This only does
|
||||
checks that might reasonably be needed to compare DWARF base
|
||||
types. */
|
||||
|
||||
static int
|
||||
base_types_equal_p (struct type *t1, struct type *t2)
|
||||
{
|
||||
if (TYPE_CODE (t1) != TYPE_CODE (t2))
|
||||
return 0;
|
||||
if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
|
||||
return 0;
|
||||
return TYPE_LENGTH (t1) == TYPE_LENGTH (t2);
|
||||
}
|
||||
|
||||
/* A convenience function to call get_base_type on CTX and return the
|
||||
result. DIE is the DIE whose type we need. SIZE is non-zero if
|
||||
this function should verify that the resulting type has the correct
|
||||
size. */
|
||||
|
||||
static struct type *
|
||||
dwarf_get_base_type (struct dwarf_expr_context *ctx, ULONGEST die, int size)
|
||||
{
|
||||
struct type *result;
|
||||
|
||||
if (ctx->get_base_type)
|
||||
{
|
||||
result = ctx->get_base_type (ctx, die);
|
||||
if (size != 0 && TYPE_LENGTH (result) != size)
|
||||
error (_("DW_OP_GNU_const_type has different sizes for type and data"));
|
||||
}
|
||||
else
|
||||
/* Anything will do. */
|
||||
result = builtin_type (ctx->gdbarch)->builtin_int;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The engine for the expression evaluator. Using the context in CTX,
|
||||
evaluate the expression between OP_PTR and OP_END. */
|
||||
|
||||
|
@ -342,10 +466,15 @@ static void
|
|||
execute_stack_op (struct dwarf_expr_context *ctx,
|
||||
const gdb_byte *op_ptr, const gdb_byte *op_end)
|
||||
{
|
||||
#define sign_ext(x) ((LONGEST) (((x) ^ sign_bit) - sign_bit))
|
||||
ULONGEST sign_bit = (ctx->addr_size >= sizeof (ULONGEST) ? 0
|
||||
: ((ULONGEST) 1) << (ctx->addr_size * 8 - 1));
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
|
||||
/* Old-style "untyped" DWARF values need special treatment in a
|
||||
couple of places, specifically DW_OP_mod and DW_OP_shr. We need
|
||||
a special type for these values so we can distinguish them from
|
||||
values that have an explicit type, because explicitly-typed
|
||||
values do not need special treatment. This special type must be
|
||||
different (in the `==' sense) from any base type coming from the
|
||||
CU. */
|
||||
struct type *address_type = dwarf_expr_address_type (ctx);
|
||||
|
||||
ctx->location = DWARF_VALUE_MEMORY;
|
||||
ctx->initialized = 1; /* Default is initialized. */
|
||||
|
@ -368,6 +497,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
int in_stack_memory = 0;
|
||||
ULONGEST uoffset, reg;
|
||||
LONGEST offset;
|
||||
struct value *result_val = NULL;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
|
@ -404,6 +534,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
case DW_OP_lit30:
|
||||
case DW_OP_lit31:
|
||||
result = op - DW_OP_lit0;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
|
||||
case DW_OP_addr:
|
||||
|
@ -416,47 +547,58 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
branching between the address and the TLS op. */
|
||||
if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address)
|
||||
result += ctx->offset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
|
||||
case DW_OP_const1u:
|
||||
result = extract_unsigned_integer (op_ptr, 1, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 1;
|
||||
break;
|
||||
case DW_OP_const1s:
|
||||
result = extract_signed_integer (op_ptr, 1, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 1;
|
||||
break;
|
||||
case DW_OP_const2u:
|
||||
result = extract_unsigned_integer (op_ptr, 2, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 2;
|
||||
break;
|
||||
case DW_OP_const2s:
|
||||
result = extract_signed_integer (op_ptr, 2, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 2;
|
||||
break;
|
||||
case DW_OP_const4u:
|
||||
result = extract_unsigned_integer (op_ptr, 4, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 4;
|
||||
break;
|
||||
case DW_OP_const4s:
|
||||
result = extract_signed_integer (op_ptr, 4, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 4;
|
||||
break;
|
||||
case DW_OP_const8u:
|
||||
result = extract_unsigned_integer (op_ptr, 8, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 8;
|
||||
break;
|
||||
case DW_OP_const8s:
|
||||
result = extract_signed_integer (op_ptr, 8, byte_order);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
op_ptr += 8;
|
||||
break;
|
||||
case DW_OP_constu:
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
|
||||
result = uoffset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_consts:
|
||||
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
|
||||
result = offset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
|
||||
/* The DW_OP_reg operations are required to occur alone in
|
||||
|
@ -502,6 +644,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
"or DW_OP_bit_piece."));
|
||||
|
||||
result = op - DW_OP_reg0;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
ctx->location = DWARF_VALUE_REGISTER;
|
||||
break;
|
||||
|
||||
|
@ -510,6 +653,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
|
||||
|
||||
result = reg;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
ctx->location = DWARF_VALUE_REGISTER;
|
||||
break;
|
||||
|
||||
|
@ -547,6 +691,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
/* The byte offset into the data. */
|
||||
op_ptr = read_sleb128 (op_ptr, op_end, &len);
|
||||
result = (ULONGEST) len;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
|
||||
ctx->location = DWARF_VALUE_IMPLICIT_POINTER;
|
||||
dwarf_expr_require_composition (op_ptr, op_end,
|
||||
|
@ -590,6 +735,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
|
||||
result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0);
|
||||
result += offset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
}
|
||||
break;
|
||||
case DW_OP_bregx:
|
||||
|
@ -598,6 +744,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
|
||||
result = (ctx->read_reg) (ctx->baton, reg);
|
||||
result += offset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
}
|
||||
break;
|
||||
case DW_OP_fbreg:
|
||||
|
@ -620,11 +767,14 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
if (ctx->location == DWARF_VALUE_MEMORY)
|
||||
result = dwarf_expr_fetch_address (ctx, 0);
|
||||
else if (ctx->location == DWARF_VALUE_REGISTER)
|
||||
result = (ctx->read_reg) (ctx->baton, dwarf_expr_fetch (ctx, 0));
|
||||
result
|
||||
= (ctx->read_reg) (ctx->baton,
|
||||
value_as_long (dwarf_expr_fetch (ctx, 0)));
|
||||
else
|
||||
error (_("Not implemented: computing frame "
|
||||
"base using explicit value operator"));
|
||||
result = result + offset;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
in_stack_memory = 1;
|
||||
ctx->stack_len = before_stack_len;
|
||||
ctx->location = DWARF_VALUE_MEMORY;
|
||||
|
@ -632,7 +782,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
break;
|
||||
|
||||
case DW_OP_dup:
|
||||
result = dwarf_expr_fetch (ctx, 0);
|
||||
result_val = dwarf_expr_fetch (ctx, 0);
|
||||
in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
|
||||
break;
|
||||
|
||||
|
@ -642,7 +792,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
|
||||
case DW_OP_pick:
|
||||
offset = *op_ptr++;
|
||||
result = dwarf_expr_fetch (ctx, offset);
|
||||
result_val = dwarf_expr_fetch (ctx, offset);
|
||||
in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset);
|
||||
break;
|
||||
|
||||
|
@ -662,7 +812,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
}
|
||||
|
||||
case DW_OP_over:
|
||||
result = dwarf_expr_fetch (ctx, 1);
|
||||
result_val = dwarf_expr_fetch (ctx, 1);
|
||||
in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1);
|
||||
break;
|
||||
|
||||
|
@ -685,14 +835,27 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
|
||||
case DW_OP_deref:
|
||||
case DW_OP_deref_size:
|
||||
case DW_OP_GNU_deref_type:
|
||||
{
|
||||
int addr_size = (op == DW_OP_deref ? ctx->addr_size : *op_ptr++);
|
||||
gdb_byte *buf = alloca (addr_size);
|
||||
CORE_ADDR addr = dwarf_expr_fetch_address (ctx, 0);
|
||||
struct type *type;
|
||||
|
||||
dwarf_expr_pop (ctx);
|
||||
|
||||
if (op == DW_OP_GNU_deref_type)
|
||||
{
|
||||
ULONGEST type_die;
|
||||
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
|
||||
type = dwarf_get_base_type (ctx, type_die, 0);
|
||||
}
|
||||
else
|
||||
type = address_type;
|
||||
|
||||
(ctx->read_mem) (ctx->baton, buf, addr, addr_size);
|
||||
result = extract_unsigned_integer (buf, addr_size, byte_order);
|
||||
result_val = value_from_contents_and_address (type, buf, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -700,27 +863,34 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
case DW_OP_neg:
|
||||
case DW_OP_not:
|
||||
case DW_OP_plus_uconst:
|
||||
/* Unary operations. */
|
||||
result = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_expr_pop (ctx);
|
||||
{
|
||||
/* Unary operations. */
|
||||
result_val = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_expr_pop (ctx);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case DW_OP_abs:
|
||||
if (sign_ext (result) < 0)
|
||||
result = -result;
|
||||
break;
|
||||
case DW_OP_neg:
|
||||
result = -result;
|
||||
break;
|
||||
case DW_OP_not:
|
||||
result = ~result;
|
||||
break;
|
||||
case DW_OP_plus_uconst:
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, ®);
|
||||
result += reg;
|
||||
break;
|
||||
}
|
||||
switch (op)
|
||||
{
|
||||
case DW_OP_abs:
|
||||
if (value_less (result_val,
|
||||
value_zero (value_type (result_val), not_lval)))
|
||||
result_val = value_neg (result_val);
|
||||
break;
|
||||
case DW_OP_neg:
|
||||
result_val = value_neg (result_val);
|
||||
break;
|
||||
case DW_OP_not:
|
||||
dwarf_require_integral (value_type (result_val));
|
||||
result_val = value_complement (result_val);
|
||||
break;
|
||||
case DW_OP_plus_uconst:
|
||||
dwarf_require_integral (value_type (result_val));
|
||||
result = value_as_long (result_val);
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, ®);
|
||||
result += reg;
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_OP_and:
|
||||
|
@ -742,7 +912,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
case DW_OP_ne:
|
||||
{
|
||||
/* Binary operations. */
|
||||
ULONGEST first, second;
|
||||
struct value *first, *second;
|
||||
|
||||
second = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_expr_pop (ctx);
|
||||
|
@ -750,62 +920,115 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
first = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_expr_pop (ctx);
|
||||
|
||||
if (! base_types_equal_p (value_type (first), value_type (second)))
|
||||
error (_("Incompatible types on DWARF stack"));
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case DW_OP_and:
|
||||
result = first & second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
result_val = value_binop (first, second, BINOP_BITWISE_AND);
|
||||
break;
|
||||
case DW_OP_div:
|
||||
if (!second)
|
||||
error (_("Division by zero"));
|
||||
result = sign_ext (first) / sign_ext (second);
|
||||
result_val = value_binop (first, second, BINOP_DIV);
|
||||
break;
|
||||
case DW_OP_minus:
|
||||
result = first - second;
|
||||
result_val = value_binop (first, second, BINOP_SUB);
|
||||
break;
|
||||
case DW_OP_mod:
|
||||
if (!second)
|
||||
error (_("Division by zero"));
|
||||
result = first % second;
|
||||
{
|
||||
int cast_back = 0;
|
||||
struct type *orig_type = value_type (first);
|
||||
|
||||
/* We have to special-case "old-style" untyped values
|
||||
-- these must have mod computed using unsigned
|
||||
math. */
|
||||
if (orig_type == address_type)
|
||||
{
|
||||
struct type *utype
|
||||
= get_unsigned_type (ctx->gdbarch, orig_type);
|
||||
|
||||
cast_back = 1;
|
||||
first = value_cast (utype, first);
|
||||
second = value_cast (utype, second);
|
||||
}
|
||||
/* Note that value_binop doesn't handle float or
|
||||
decimal float here. This seems unimportant. */
|
||||
result_val = value_binop (first, second, BINOP_MOD);
|
||||
if (cast_back)
|
||||
result_val = value_cast (orig_type, result_val);
|
||||
}
|
||||
break;
|
||||
case DW_OP_mul:
|
||||
result = first * second;
|
||||
result_val = value_binop (first, second, BINOP_MUL);
|
||||
break;
|
||||
case DW_OP_or:
|
||||
result = first | second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
result_val = value_binop (first, second, BINOP_BITWISE_IOR);
|
||||
break;
|
||||
case DW_OP_plus:
|
||||
result = first + second;
|
||||
result_val = value_binop (first, second, BINOP_ADD);
|
||||
break;
|
||||
case DW_OP_shl:
|
||||
result = first << second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
result_val = value_binop (first, second, BINOP_LSH);
|
||||
break;
|
||||
case DW_OP_shr:
|
||||
result = first >> second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
if (value_type (first) == address_type)
|
||||
{
|
||||
struct type *utype
|
||||
= get_unsigned_type (ctx->gdbarch, value_type (first));
|
||||
|
||||
first = value_cast (utype, first);
|
||||
}
|
||||
|
||||
result_val = value_binop (first, second, BINOP_RSH);
|
||||
/* Make sure we wind up with the same type we started
|
||||
with. */
|
||||
if (value_type (result_val) != value_type (second))
|
||||
result_val = value_cast (value_type (second), result_val);
|
||||
break;
|
||||
case DW_OP_shra:
|
||||
result = sign_ext (first) >> second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
result_val = value_binop (first, second, BINOP_RSH);
|
||||
break;
|
||||
case DW_OP_xor:
|
||||
result = first ^ second;
|
||||
dwarf_require_integral (value_type (first));
|
||||
dwarf_require_integral (value_type (second));
|
||||
result_val = value_binop (first, second, BINOP_BITWISE_XOR);
|
||||
break;
|
||||
case DW_OP_le:
|
||||
result = sign_ext (first) <= sign_ext (second);
|
||||
/* A <= B is !(B < A). */
|
||||
result = ! value_less (second, first);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_ge:
|
||||
result = sign_ext (first) >= sign_ext (second);
|
||||
/* A >= B is !(A < B). */
|
||||
result = ! value_less (first, second);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_eq:
|
||||
result = sign_ext (first) == sign_ext (second);
|
||||
result = value_equal (first, second);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_lt:
|
||||
result = sign_ext (first) < sign_ext (second);
|
||||
result = value_less (first, second);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_gt:
|
||||
result = sign_ext (first) > sign_ext (second);
|
||||
/* A > B is B < A. */
|
||||
result = value_less (second, first);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
case DW_OP_ne:
|
||||
result = sign_ext (first) != sign_ext (second);
|
||||
result = ! value_equal (first, second);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
|
@ -816,6 +1039,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
|
||||
case DW_OP_call_frame_cfa:
|
||||
result = (ctx->get_frame_cfa) (ctx->baton);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
in_stack_memory = 1;
|
||||
break;
|
||||
|
||||
|
@ -828,9 +1052,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
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);
|
||||
result = value_as_long (dwarf_expr_fetch (ctx, 0));
|
||||
dwarf_expr_pop (ctx);
|
||||
result = (ctx->get_tls_address) (ctx->baton, result);
|
||||
result_val = value_from_ulongest (address_type, result);
|
||||
break;
|
||||
|
||||
case DW_OP_skip:
|
||||
|
@ -840,11 +1065,17 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
goto no_push;
|
||||
|
||||
case DW_OP_bra:
|
||||
offset = extract_signed_integer (op_ptr, 2, byte_order);
|
||||
op_ptr += 2;
|
||||
if (dwarf_expr_fetch (ctx, 0) != 0)
|
||||
op_ptr += offset;
|
||||
dwarf_expr_pop (ctx);
|
||||
{
|
||||
struct value *val;
|
||||
|
||||
offset = extract_signed_integer (op_ptr, 2, byte_order);
|
||||
op_ptr += 2;
|
||||
val = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_require_integral (value_type (val));
|
||||
if (value_as_long (val) != 0)
|
||||
op_ptr += offset;
|
||||
dwarf_expr_pop (ctx);
|
||||
}
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_nop:
|
||||
|
@ -912,12 +1143,73 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
ctx->num_pieces = 0;
|
||||
goto abort_expression;
|
||||
|
||||
case DW_OP_GNU_const_type:
|
||||
{
|
||||
ULONGEST type_die;
|
||||
int n;
|
||||
const gdb_byte *data;
|
||||
struct type *type;
|
||||
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
|
||||
n = *op_ptr++;
|
||||
data = op_ptr;
|
||||
op_ptr += n;
|
||||
|
||||
type = dwarf_get_base_type (ctx, type_die, n);
|
||||
result_val = value_from_contents (type, data);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_OP_GNU_regval_type:
|
||||
{
|
||||
ULONGEST type_die;
|
||||
struct type *type;
|
||||
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, ®);
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
|
||||
|
||||
type = dwarf_get_base_type (ctx, type_die, 0);
|
||||
result = (ctx->read_reg) (ctx->baton, reg);
|
||||
result_val = value_from_ulongest (type, result);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_OP_GNU_convert:
|
||||
case DW_OP_GNU_reinterpret:
|
||||
{
|
||||
ULONGEST type_die;
|
||||
struct type *type;
|
||||
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
|
||||
|
||||
type = dwarf_get_base_type (ctx, type_die, 0);
|
||||
|
||||
result_val = dwarf_expr_fetch (ctx, 0);
|
||||
dwarf_expr_pop (ctx);
|
||||
|
||||
if (op == DW_OP_GNU_convert)
|
||||
result_val = value_cast (type, result_val);
|
||||
else if (type == value_type (result_val))
|
||||
{
|
||||
/* Nothing. */
|
||||
}
|
||||
else if (TYPE_LENGTH (type)
|
||||
!= TYPE_LENGTH (value_type (result_val)))
|
||||
error (_("DW_OP_GNU_reinterpret has wrong size"));
|
||||
else
|
||||
result_val
|
||||
= value_from_contents (type,
|
||||
value_contents_all (result_val));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error (_("Unhandled dwarf expression opcode 0x%x"), op);
|
||||
}
|
||||
|
||||
/* Most things push a result value. */
|
||||
dwarf_expr_push (ctx, result, in_stack_memory);
|
||||
gdb_assert (result_val != NULL);
|
||||
dwarf_expr_push (ctx, result_val, in_stack_memory);
|
||||
no_push:
|
||||
;
|
||||
}
|
||||
|
@ -931,5 +1223,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
abort_expression:
|
||||
ctx->recursion_depth--;
|
||||
gdb_assert (ctx->recursion_depth >= 0);
|
||||
#undef sign_ext
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_dwarf2expr (void)
|
||||
{
|
||||
dwarf_arch_cookie
|
||||
= gdbarch_data_register_post_init (dwarf_gdbarch_types_init);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ enum dwarf_value_location
|
|||
|
||||
struct dwarf_stack_value
|
||||
{
|
||||
ULONGEST value;
|
||||
struct value *value;
|
||||
|
||||
/* Non-zero if the piece is in memory and is known to be
|
||||
on the program's stack. It is always ok to set this to zero.
|
||||
|
@ -81,6 +81,10 @@ struct dwarf_expr_context
|
|||
/* Offset used to relocate DW_OP_addr argument. */
|
||||
CORE_ADDR offset;
|
||||
|
||||
/* The evaluator is value-based, and frees values up to this point
|
||||
when the expression context is destroyed. */
|
||||
struct value *mark;
|
||||
|
||||
/* An opaque argument provided by the caller, which will be passed
|
||||
to all of the callback functions. */
|
||||
void *baton;
|
||||
|
@ -111,6 +115,13 @@ struct dwarf_expr_context
|
|||
being passed to and returned from the called DWARF subroutine. */
|
||||
void (*dwarf_call) (struct dwarf_expr_context *ctx, size_t die_offset);
|
||||
|
||||
/* Return the base type given by the indicated DIE. This can throw
|
||||
an exception if the DIE is invalid or does not represent a base
|
||||
type. If can also be NULL in the special case where the
|
||||
callbacks are not performing evaluation, and thus it is
|
||||
meaningful to substitute a stub type of the correct size. */
|
||||
struct type *(*get_base_type) (struct dwarf_expr_context *ctx, size_t die);
|
||||
|
||||
#if 0
|
||||
/* Not yet implemented. */
|
||||
|
||||
|
@ -180,9 +191,11 @@ struct dwarf_expr_piece
|
|||
int in_stack_memory;
|
||||
} mem;
|
||||
|
||||
/* The piece's register number or literal value, for
|
||||
DWARF_VALUE_REGISTER or DWARF_VALUE_STACK pieces. */
|
||||
ULONGEST value;
|
||||
/* The piece's register number, for DWARF_VALUE_REGISTER pieces. */
|
||||
int regno;
|
||||
|
||||
/* The piece's literal value, for DWARF_VALUE_STACK pieces. */
|
||||
struct value *value;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -214,12 +227,12 @@ void free_dwarf_expr_context (struct dwarf_expr_context *ctx);
|
|||
struct cleanup *
|
||||
make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx);
|
||||
|
||||
void dwarf_expr_push (struct dwarf_expr_context *ctx, ULONGEST value,
|
||||
int in_stack_memory);
|
||||
void dwarf_expr_pop (struct dwarf_expr_context *ctx);
|
||||
void dwarf_expr_push_address (struct dwarf_expr_context *ctx,
|
||||
CORE_ADDR value,
|
||||
int in_stack_memory);
|
||||
void dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr,
|
||||
size_t len);
|
||||
ULONGEST dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
|
||||
struct value *dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
|
||||
CORE_ADDR dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n);
|
||||
int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n);
|
||||
|
||||
|
|
|
@ -286,6 +286,16 @@ dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
|
|||
ctx->get_frame_pc, ctx->baton);
|
||||
}
|
||||
|
||||
/* Callback function for dwarf2_evaluate_loc_desc. */
|
||||
|
||||
static struct type *
|
||||
dwarf_expr_get_base_type (struct dwarf_expr_context *ctx, size_t die_offset)
|
||||
{
|
||||
struct dwarf_expr_baton *debaton = ctx->baton;
|
||||
|
||||
return dwarf2_get_die_type (die_offset, debaton->per_cu);
|
||||
}
|
||||
|
||||
struct piece_closure
|
||||
{
|
||||
/* Reference count. */
|
||||
|
@ -313,6 +323,7 @@ allocate_piece_closure (struct dwarf2_per_cu_data *per_cu,
|
|||
int addr_size)
|
||||
{
|
||||
struct piece_closure *c = XZALLOC (struct piece_closure);
|
||||
int i;
|
||||
|
||||
c->refc = 1;
|
||||
c->per_cu = per_cu;
|
||||
|
@ -321,6 +332,9 @@ allocate_piece_closure (struct dwarf2_per_cu_data *per_cu,
|
|||
c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece);
|
||||
|
||||
memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece));
|
||||
for (i = 0; i < n_pieces; ++i)
|
||||
if (c->pieces[i].location == DWARF_VALUE_STACK)
|
||||
value_incref (c->pieces[i].v.value);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -576,7 +590,7 @@ read_pieced_value (struct value *v)
|
|||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
|
||||
int reg_offset = source_offset;
|
||||
|
||||
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
|
||||
|
@ -609,7 +623,7 @@ read_pieced_value (struct value *v)
|
|||
else
|
||||
{
|
||||
error (_("Unable to access DWARF register number %s"),
|
||||
paddress (arch, p->v.value));
|
||||
paddress (arch, p->v.regno));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -623,7 +637,6 @@ read_pieced_value (struct value *v)
|
|||
|
||||
case DWARF_VALUE_STACK:
|
||||
{
|
||||
struct gdbarch *gdbarch = get_type_arch (value_type (v));
|
||||
size_t n = this_size;
|
||||
|
||||
if (n > c->addr_size - source_offset)
|
||||
|
@ -634,18 +647,11 @@ read_pieced_value (struct value *v)
|
|||
{
|
||||
/* Nothing. */
|
||||
}
|
||||
else if (source_offset == 0)
|
||||
store_unsigned_integer (buffer, n,
|
||||
gdbarch_byte_order (gdbarch),
|
||||
p->v.value);
|
||||
else
|
||||
{
|
||||
gdb_byte bytes[sizeof (ULONGEST)];
|
||||
const gdb_byte *val_bytes = value_contents_all (p->v.value);
|
||||
|
||||
store_unsigned_integer (bytes, n + source_offset,
|
||||
gdbarch_byte_order (gdbarch),
|
||||
p->v.value);
|
||||
memcpy (buffer, bytes + source_offset, n);
|
||||
intermediate_buffer = val_bytes + source_offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -776,7 +782,7 @@ write_pieced_value (struct value *to, struct value *from)
|
|||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
|
||||
int reg_offset = dest_offset;
|
||||
|
||||
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
|
||||
|
@ -816,7 +822,7 @@ write_pieced_value (struct value *to, struct value *from)
|
|||
else
|
||||
{
|
||||
error (_("Unable to write to DWARF register number %s"),
|
||||
paddress (arch, p->v.value));
|
||||
paddress (arch, p->v.regno));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1033,6 +1039,12 @@ free_pieced_value_closure (struct value *v)
|
|||
--c->refc;
|
||||
if (c->refc == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c->n_pieces; ++i)
|
||||
if (c->pieces[i].location == DWARF_VALUE_STACK)
|
||||
value_free (c->pieces[i].v.value);
|
||||
|
||||
xfree (c->pieces);
|
||||
xfree (c);
|
||||
}
|
||||
|
@ -1106,6 +1118,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
|
|||
ctx->get_frame_pc = dwarf_expr_frame_pc;
|
||||
ctx->get_tls_address = dwarf_expr_tls_address;
|
||||
ctx->dwarf_call = dwarf_expr_dwarf_call;
|
||||
ctx->get_base_type = dwarf_expr_get_base_type;
|
||||
|
||||
TRY_CATCH (ex, RETURN_MASK_ERROR)
|
||||
{
|
||||
|
@ -1148,7 +1161,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
|
|||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
ULONGEST dwarf_regnum = dwarf_expr_fetch (ctx, 0);
|
||||
ULONGEST dwarf_regnum = value_as_long (dwarf_expr_fetch (ctx, 0));
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
|
||||
|
||||
if (byte_offset != 0)
|
||||
|
@ -1176,26 +1189,23 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
|
|||
|
||||
case DWARF_VALUE_STACK:
|
||||
{
|
||||
ULONGEST value = dwarf_expr_fetch (ctx, 0);
|
||||
bfd_byte *contents, *tem;
|
||||
size_t n = ctx->addr_size;
|
||||
struct value *value = dwarf_expr_fetch (ctx, 0);
|
||||
gdb_byte *contents;
|
||||
const gdb_byte *val_bytes;
|
||||
size_t n = TYPE_LENGTH (value_type (value));
|
||||
|
||||
if (byte_offset + TYPE_LENGTH (type) > n)
|
||||
invalid_synthetic_pointer ();
|
||||
|
||||
tem = alloca (n);
|
||||
store_unsigned_integer (tem, n,
|
||||
gdbarch_byte_order (ctx->gdbarch),
|
||||
value);
|
||||
|
||||
tem += byte_offset;
|
||||
val_bytes = value_contents_all (value);
|
||||
val_bytes += byte_offset;
|
||||
n -= byte_offset;
|
||||
|
||||
retval = allocate_value (type);
|
||||
contents = value_contents_raw (retval);
|
||||
if (n > TYPE_LENGTH (type))
|
||||
n = TYPE_LENGTH (type);
|
||||
memcpy (contents, tem, n);
|
||||
memcpy (contents, val_bytes, n);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block
|
|||
CORE_ADDR (*get_frame_pc) (void *baton),
|
||||
void *baton);
|
||||
|
||||
struct type *dwarf2_get_die_type (unsigned int die_offset,
|
||||
struct dwarf2_per_cu_data *per_cu);
|
||||
|
||||
/* Evaluate a location description, starting at DATA and with length
|
||||
SIZE, to find the current location of variable of TYPE in the context
|
||||
of FRAME. */
|
||||
|
|
|
@ -13094,6 +13094,18 @@ dwarf_stack_op_name (unsigned op)
|
|||
return "DW_OP_GNU_uninit";
|
||||
case DW_OP_GNU_implicit_pointer:
|
||||
return "DW_OP_GNU_implicit_pointer";
|
||||
case DW_OP_GNU_entry_value:
|
||||
return "DW_OP_GNU_entry_value";
|
||||
case DW_OP_GNU_const_type:
|
||||
return "DW_OP_GNU_const_type";
|
||||
case DW_OP_GNU_regval_type:
|
||||
return "DW_OP_GNU_regval_type";
|
||||
case DW_OP_GNU_deref_type:
|
||||
return "DW_OP_GNU_deref_type";
|
||||
case DW_OP_GNU_convert:
|
||||
return "DW_OP_GNU_convert";
|
||||
case DW_OP_GNU_reinterpret:
|
||||
return "DW_OP_GNU_reinterpret";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -13652,6 +13664,31 @@ dwarf2_fetch_die_location_block (unsigned int offset,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* Return the type of the DIE at DIE_OFFSET in the CU named by
|
||||
PER_CU. */
|
||||
|
||||
struct type *
|
||||
dwarf2_get_die_type (unsigned int die_offset,
|
||||
struct dwarf2_per_cu_data *per_cu)
|
||||
{
|
||||
struct dwarf2_cu *cu = per_cu->cu;
|
||||
struct die_info *die;
|
||||
struct type *result;
|
||||
|
||||
dw2_setup (per_cu->objfile);
|
||||
|
||||
die = follow_die_offset (die_offset, &cu);
|
||||
if (!die)
|
||||
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
|
||||
die_offset, per_cu->cu->objfile->name);
|
||||
|
||||
result = get_die_type (die, cu);
|
||||
if (result == NULL)
|
||||
result = read_type_die_1 (die, cu);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Follow the signature attribute ATTR in SRC_DIE.
|
||||
On entry *REF_CU is the CU of SRC_DIE.
|
||||
On exit *REF_CU is the CU of the result. */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2011-05-12 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.dwarf2/typeddwarf.S: New file.
|
||||
* gdb.dwarf2/typeddwarf.c: New file.
|
||||
* gdb.dwarf2/typeddwarf.exp: New file.
|
||||
|
||||
2011-05-12 Marek Polacek <mpolacek@redhat.com>
|
||||
|
||||
* gdb.mi/mi-basics.exp: Fix races. Honour the
|
||||
|
|
2225
gdb/testsuite/gdb.dwarf2/typeddwarf.S
Normal file
2225
gdb/testsuite/gdb.dwarf2/typeddwarf.S
Normal file
File diff suppressed because it is too large
Load diff
93
gdb/testsuite/gdb.dwarf2/typeddwarf.c
Normal file
93
gdb/testsuite/gdb.dwarf2/typeddwarf.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
|
||||
/* { dg-options "-g" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
volatile int vv;
|
||||
extern void *memcpy (void *, const void *, size_t);
|
||||
|
||||
__attribute__((noinline, noclone)) void
|
||||
f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long long h, unsigned long long i)
|
||||
{
|
||||
double j = d; /* { dg-final { gdb-test 29 "j" "4" } } */
|
||||
long long l; /* { dg-final { gdb-test 29 "l" "4616189618054758400" } } */
|
||||
memcpy (&l, &j, sizeof (l));
|
||||
long long m; /* { dg-final { gdb-test 29 "m" "4613937818241073152" } } */
|
||||
memcpy (&m, &c, sizeof (l));
|
||||
float n = i; /* { dg-final { gdb-test 29 "n" "9" } } */
|
||||
double o = h; /* { dg-final { gdb-test 29 "o" "8" } } */
|
||||
float p = g; /* { dg-final { gdb-test 29 "p" "7" } } */
|
||||
double q = f; /* { dg-final { gdb-test 29 "q" "6" } } */
|
||||
unsigned long long r = a; /* { dg-final { gdb-test 29 "r" "1" } } */
|
||||
long long s = c; /* { dg-final { gdb-test 29 "s" "3" } } */
|
||||
unsigned t = d; /* { dg-final { gdb-test 29 "t" "4" } } */
|
||||
int u = b; /* { dg-final { gdb-test 29 "u" "2" } } */
|
||||
float v = a; /* { dg-final { gdb-test 29 "v" "1" } } */
|
||||
double w = d / 4.0; /* { dg-final { gdb-test 29 "w" "1" } } */
|
||||
double x = a + b + 1.0; /* { dg-final { gdb-test 29 "x" "4" } } */
|
||||
double y = b + c + 2.0; /* { dg-final { gdb-test 29 "y" "7" } } */
|
||||
float z = d + e + 3.0f; /* { dg-final { gdb-test 29 "z" "12" } } */
|
||||
vv++;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone)) void
|
||||
f2 (double a, double b, double c, float d, float e, int f, unsigned int g, long long h, unsigned long long i)
|
||||
{
|
||||
double j = d; /* { dg-final { gdb-test 53 "j" "4" } } */
|
||||
long long l; /* { dg-final { gdb-test 53 "l" "4616189618054758400" } } */
|
||||
memcpy (&l, &j, sizeof (l));
|
||||
long long m; /* { dg-final { gdb-test 53 "m" "4613937818241073152" } } */
|
||||
memcpy (&m, &c, sizeof (l));
|
||||
float n = i; /* { dg-final { xfail-gdb-test 53 "n" "9" } } */
|
||||
double o = h; /* { dg-final { xfail-gdb-test 53 "o" "8" } } */
|
||||
float p = g; /* { dg-final { gdb-test 53 "p" "7" } } */
|
||||
double q = f; /* { dg-final { gdb-test 53 "q" "6" } } */
|
||||
unsigned long long r = a; /* { dg-final { gdb-test 53 "r" "1" } } */
|
||||
long long s = c; /* { dg-final { gdb-test 53 "s" "3" } } */
|
||||
unsigned t = d; /* { dg-final { gdb-test 53 "t" "4" } } */
|
||||
int u = b; /* { dg-final { gdb-test 53 "u" "2" } } */
|
||||
float v = a; /* { dg-final { gdb-test 53 "v" "1" } } */
|
||||
double w = d / 4.0; /* { dg-final { gdb-test 53 "w" "1" } } */
|
||||
double x = a + b - 3 + 1.0e20;/* { dg-final { gdb-test 53 "x" "1e\\+20" } } */
|
||||
double y = b + c * 7.0; /* { dg-final { gdb-test 53 "y" "23" } } */
|
||||
float z = d + e + 3.0f; /* { dg-final { gdb-test 53 "z" "12" } } */
|
||||
vv++;
|
||||
vv = a;
|
||||
vv = b;
|
||||
vv = c;
|
||||
vv = d;
|
||||
vv = e;
|
||||
vv = f;
|
||||
vv = g;
|
||||
vv = h;
|
||||
vv = i;
|
||||
vv = j;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone)) void
|
||||
f3 (long long a, int b, long long c, unsigned d)
|
||||
{
|
||||
long long w = (a > d) ? a : d;/* { dg-final { gdb-test 73 "w" "4" } } */
|
||||
long long x = a + b + 7; /* { dg-final { gdb-test 73 "x" "10" } } */
|
||||
long long y = c + d + 0x912345678LL;/* { dg-final { gdb-test 73 "y" "38960125567" } } */
|
||||
int z = (x + y); /* { dg-final { gdb-test 73 "z" "305419913" } } */
|
||||
vv++;
|
||||
}
|
||||
|
||||
__attribute__((noinline, noclone)) void
|
||||
f4 (_Decimal32 a, _Decimal64 b, _Decimal128 c)
|
||||
{
|
||||
_Decimal32 w = a * 8.0DF + 6.0DF;/* { dg-final { xfail-gdb-test 82 "(int)w" "70" } } */
|
||||
_Decimal64 x = b / 8.0DD - 6.0DD;/* { dg-final { xfail-gdb-test 82 "(int)x" "-4" } } */
|
||||
_Decimal128 y = -c / 8.0DL; /* { dg-final { xfail-gdb-test 82 "(int)y" "-8" } } */
|
||||
vv++;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
f1 (1.0, 2.0, 3.0, 4.0f, 5.0f, 6, 7, 8, 9);
|
||||
f2 (1.0, 2.0, 3.0, 4.0f, 5.0f, 6, 7, 8, 9);
|
||||
f3 (1, 2, 3, 4);
|
||||
f4 (8.0DF, 16.0DD, 64.0DL);
|
||||
return 0;
|
||||
}
|
91
gdb/testsuite/gdb.dwarf2/typeddwarf.exp
Normal file
91
gdb/testsuite/gdb.dwarf2/typeddwarf.exp
Normal file
|
@ -0,0 +1,91 @@
|
|||
# Copyright 2011 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
load_lib dwarf.exp
|
||||
|
||||
set test "typeddwarf"
|
||||
|
||||
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
if ![dwarf2_support] {
|
||||
return 0
|
||||
}
|
||||
|
||||
# This test can only be run on x86 targets.
|
||||
if { ![istarget i?86-*] } {
|
||||
return 0
|
||||
}
|
||||
|
||||
if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
global tests
|
||||
set tests(_) -
|
||||
unset tests(_)
|
||||
|
||||
proc gdb-test {line var value} {
|
||||
global tests
|
||||
|
||||
lappend tests($line) [list $var $value 0]
|
||||
}
|
||||
|
||||
proc xfail-gdb-test {line var value} {
|
||||
global tests
|
||||
|
||||
lappend tests($line) [list $var $value 1]
|
||||
}
|
||||
|
||||
proc scan_gdb_tests {} {
|
||||
global srcdir subdir test
|
||||
|
||||
set file "$srcdir/$subdir/$test.c"
|
||||
|
||||
set fd [open "$file"]
|
||||
while {![eof $fd]} {
|
||||
set line [gets $fd]
|
||||
if {! [regexp "\{ (gdb-test .+) \} \}" $line ignore test_cmd]} {
|
||||
continue
|
||||
}
|
||||
|
||||
eval $test_cmd
|
||||
}
|
||||
close $fd
|
||||
}
|
||||
|
||||
scan_gdb_tests
|
||||
|
||||
foreach line [lsort [array names tests]] {
|
||||
gdb_test "break typeddwarf.c:$line" "Breakpoint .*" \
|
||||
"set breakpoint at typeddwarf.c:$line"
|
||||
gdb_continue_to_breakpoint "continue to typeddwarf.c:$line"
|
||||
|
||||
foreach test $tests($line) {
|
||||
set var [lindex $test 0]
|
||||
set value [lindex $test 1]
|
||||
set should_xfail [lindex $test 2]
|
||||
|
||||
if {$should_xfail} {
|
||||
setup_xfail *-*-*
|
||||
}
|
||||
|
||||
gdb_test "print $var" \
|
||||
" = $value" \
|
||||
"check value of $var at typeddwarf.c:$line"
|
||||
}
|
||||
}
|
13
gdb/value.c
13
gdb/value.c
|
@ -2965,6 +2965,19 @@ value_from_contents_and_address (struct type *type,
|
|||
return v;
|
||||
}
|
||||
|
||||
/* Create a value of type TYPE holding the contents CONTENTS.
|
||||
The new value is `not_lval'. */
|
||||
|
||||
struct value *
|
||||
value_from_contents (struct type *type, const gdb_byte *contents)
|
||||
{
|
||||
struct value *result;
|
||||
|
||||
result = allocate_value (type);
|
||||
memcpy (value_contents_raw (result), contents, TYPE_LENGTH (type));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct value *
|
||||
value_from_double (struct type *type, DOUBLEST num)
|
||||
{
|
||||
|
|
|
@ -479,6 +479,7 @@ extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr);
|
|||
extern struct value *value_from_contents_and_address (struct type *,
|
||||
const gdb_byte *,
|
||||
CORE_ADDR);
|
||||
extern struct value *value_from_contents (struct type *, const gdb_byte *);
|
||||
|
||||
extern struct value *default_value_from_register (struct type *type,
|
||||
int regnum,
|
||||
|
|
Loading…
Reference in a new issue