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:
Tom Tromey 2011-05-12 17:40:55 +00:00
parent e8d28ef4f3
commit 8a9b8146fd
13 changed files with 2971 additions and 123 deletions

View File

@ -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.

View File

@ -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

View File

@ -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, &reg);
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, &reg);
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, &reg);
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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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. */

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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;
}

View 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"
}
}

View File

@ -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)
{

View File

@ -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,