gdb
* dwarf2loc.c (struct piece_closure) <arch>: New field. (dwarf2_evaluate_loc_desc): Update. (dwarf2_loc_desc_needs_frame): Likewise. (allocate_piece_closure): Initialize new field. (read_pieced_value): Update. (write_pieced_value): Update. (copy_pieced_value_closure): Update. * dwarf2expr.h (enum dwarf_value_location): New. (struct dwarf_expr_context) <in_reg>: Remove. <location, len, data>: New fields. (struct dwarf_expr_piece) <in_reg, value>: Remove. <location, v>: New fields. * dwarf2expr.c (add_piece): Remove in_reg, value arguments. Update. (require_composition): New function. (execute_stack_op): Update. <DW_OP_implicit_value, DW_OP_stack_value>: New cases. <DW_OP_reg0>: Set location, not in_reg. <DW_OP_regx>: Likewise. Use require_composition. <DW_OP_fbreg>: Update. <DW_OP_piece>: Likewise. * dwarf2-frame.c (execute_stack_op): Update. gdb/testsuite * gdb.dwarf2/valop.S: New file. * gdb.dwarf2/valop.exp: New file.
This commit is contained in:
parent
a05e8785c7
commit
cec03d703f
8 changed files with 822 additions and 80 deletions
|
@ -1,3 +1,28 @@
|
|||
2009-09-11 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* dwarf2loc.c (struct piece_closure) <arch>: New field.
|
||||
(dwarf2_evaluate_loc_desc): Update.
|
||||
(dwarf2_loc_desc_needs_frame): Likewise.
|
||||
(allocate_piece_closure): Initialize new field.
|
||||
(read_pieced_value): Update.
|
||||
(write_pieced_value): Update.
|
||||
(copy_pieced_value_closure): Update.
|
||||
* dwarf2expr.h (enum dwarf_value_location): New.
|
||||
(struct dwarf_expr_context) <in_reg>: Remove.
|
||||
<location, len, data>: New fields.
|
||||
(struct dwarf_expr_piece) <in_reg, value>: Remove.
|
||||
<location, v>: New fields.
|
||||
* dwarf2expr.c (add_piece): Remove in_reg, value arguments.
|
||||
Update.
|
||||
(require_composition): New function.
|
||||
(execute_stack_op): Update.
|
||||
<DW_OP_implicit_value, DW_OP_stack_value>: New cases.
|
||||
<DW_OP_reg0>: Set location, not in_reg.
|
||||
<DW_OP_regx>: Likewise. Use require_composition.
|
||||
<DW_OP_fbreg>: Update.
|
||||
<DW_OP_piece>: Likewise.
|
||||
* dwarf2-frame.c (execute_stack_op): Update.
|
||||
|
||||
2009-09-10 Anthony Green <green@moxielogic.com>
|
||||
|
||||
* moxie-tdep.c (moxie_analyze_prologue): Recognize new prologue
|
||||
|
|
|
@ -379,8 +379,15 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
|
|||
dwarf_expr_eval (ctx, exp, len);
|
||||
result = dwarf_expr_fetch (ctx, 0);
|
||||
|
||||
if (ctx->in_reg)
|
||||
if (ctx->location == DWARF_VALUE_REGISTER)
|
||||
result = read_reg (this_frame, result);
|
||||
else if (ctx->location != DWARF_VALUE_MEMORY)
|
||||
{
|
||||
/* This is actually invalid DWARF, but if we ever do run across
|
||||
it somehow, we might as well support it. So, instead, report
|
||||
it as unimplemented. */
|
||||
error (_("Not implemented: computing unwound register using explicit value operator"));
|
||||
}
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
|
|
|
@ -125,8 +125,7 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
|
|||
|
||||
/* Add a new piece to CTX's piece list. */
|
||||
static void
|
||||
add_piece (struct dwarf_expr_context *ctx,
|
||||
int in_reg, CORE_ADDR value, ULONGEST size)
|
||||
add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
|
||||
{
|
||||
struct dwarf_expr_piece *p;
|
||||
|
||||
|
@ -141,9 +140,15 @@ add_piece (struct dwarf_expr_context *ctx,
|
|||
* sizeof (struct dwarf_expr_piece));
|
||||
|
||||
p = &ctx->pieces[ctx->num_pieces - 1];
|
||||
p->in_reg = in_reg;
|
||||
p->value = value;
|
||||
p->location = ctx->location;
|
||||
p->size = size;
|
||||
if (p->location == DWARF_VALUE_LITERAL)
|
||||
{
|
||||
p->v.literal.data = ctx->data;
|
||||
p->v.literal.length = ctx->len;
|
||||
}
|
||||
else
|
||||
p->v.value = dwarf_expr_fetch (ctx, 0);
|
||||
}
|
||||
|
||||
/* Evaluate the expression at ADDR (LEN bytes long) using the context
|
||||
|
@ -287,6 +292,23 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Check that the current operator is either at the end of an
|
||||
expression, or that it is followed by a composition operator. */
|
||||
|
||||
static void
|
||||
require_composition (gdb_byte *op_ptr, gdb_byte *op_end, const char *op_name)
|
||||
{
|
||||
/* It seems like DW_OP_GNU_uninit should be handled here. However,
|
||||
it doesn't seem to make sense for DW_OP_*_value, and it was not
|
||||
checked at the other place that this function is called. */
|
||||
if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece)
|
||||
error (_("DWARF-2 expression error: `%s' operations must be "
|
||||
"used either alone or in conjuction with DW_OP_piece "
|
||||
"or DW_OP_bit_piece."),
|
||||
op_name);
|
||||
}
|
||||
|
||||
/* The engine for the expression evaluator. Using the context in CTX,
|
||||
evaluate the expression between OP_PTR and OP_END. */
|
||||
|
||||
|
@ -295,8 +317,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
gdb_byte *op_ptr, gdb_byte *op_end)
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
|
||||
|
||||
ctx->in_reg = 0;
|
||||
ctx->location = DWARF_VALUE_MEMORY;
|
||||
ctx->initialized = 1; /* Default is initialized. */
|
||||
|
||||
if (ctx->recursion_depth > ctx->max_recursion_depth)
|
||||
|
@ -436,20 +457,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
"used either alone or in conjuction with DW_OP_piece."));
|
||||
|
||||
result = op - DW_OP_reg0;
|
||||
ctx->in_reg = 1;
|
||||
|
||||
ctx->location = DWARF_VALUE_REGISTER;
|
||||
break;
|
||||
|
||||
case DW_OP_regx:
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, ®);
|
||||
if (op_ptr != op_end && *op_ptr != DW_OP_piece)
|
||||
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
|
||||
"used either alone or in conjuction with DW_OP_piece."));
|
||||
require_composition (op_ptr, op_end, "DW_OP_regx");
|
||||
|
||||
result = reg;
|
||||
ctx->in_reg = 1;
|
||||
ctx->location = DWARF_VALUE_REGISTER;
|
||||
break;
|
||||
|
||||
case DW_OP_implicit_value:
|
||||
{
|
||||
ULONGEST len;
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &len);
|
||||
if (op_ptr + len > op_end)
|
||||
error (_("DW_OP_implicit_value: too few bytes available."));
|
||||
ctx->len = len;
|
||||
ctx->data = op_ptr;
|
||||
ctx->location = DWARF_VALUE_LITERAL;
|
||||
op_ptr += len;
|
||||
require_composition (op_ptr, op_end, "DW_OP_implicit_value");
|
||||
}
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_stack_value:
|
||||
ctx->location = DWARF_VALUE_STACK;
|
||||
require_composition (op_ptr, op_end, "DW_OP_stack_value");
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_breg0:
|
||||
case DW_OP_breg1:
|
||||
case DW_OP_breg2:
|
||||
|
@ -513,12 +550,15 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
specific this_base method. */
|
||||
(ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
|
||||
dwarf_expr_eval (ctx, datastart, datalen);
|
||||
if (ctx->location == DWARF_VALUE_LITERAL
|
||||
|| ctx->location == DWARF_VALUE_STACK)
|
||||
error (_("Not implemented: computing frame base using explicit value operator"));
|
||||
result = dwarf_expr_fetch (ctx, 0);
|
||||
if (ctx->in_reg)
|
||||
if (ctx->location == DWARF_VALUE_REGISTER)
|
||||
result = (ctx->read_reg) (ctx->baton, result);
|
||||
result = result + offset;
|
||||
ctx->stack_len = before_stack_len;
|
||||
ctx->in_reg = 0;
|
||||
ctx->location = DWARF_VALUE_MEMORY;
|
||||
}
|
||||
break;
|
||||
case DW_OP_dup:
|
||||
|
@ -758,12 +798,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
|||
|
||||
/* Record the piece. */
|
||||
op_ptr = read_uleb128 (op_ptr, op_end, &size);
|
||||
addr_or_regnum = dwarf_expr_fetch (ctx, 0);
|
||||
add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
|
||||
add_piece (ctx, size);
|
||||
|
||||
/* Pop off the address/regnum, and clear the in_reg flag. */
|
||||
dwarf_expr_pop (ctx);
|
||||
ctx->in_reg = 0;
|
||||
/* Pop off the address/regnum, and reset the location
|
||||
type. */
|
||||
if (ctx->location != DWARF_VALUE_LITERAL)
|
||||
dwarf_expr_pop (ctx);
|
||||
ctx->location = DWARF_VALUE_MEMORY;
|
||||
}
|
||||
goto no_push;
|
||||
|
||||
|
|
|
@ -23,6 +23,19 @@
|
|||
#if !defined (DWARF2EXPR_H)
|
||||
#define DWARF2EXPR_H
|
||||
|
||||
/* The location of a value. */
|
||||
enum dwarf_value_location
|
||||
{
|
||||
/* The piece is in memory. */
|
||||
DWARF_VALUE_MEMORY,
|
||||
/* The piece is in a register. */
|
||||
DWARF_VALUE_REGISTER,
|
||||
/* The piece is on the stack. */
|
||||
DWARF_VALUE_STACK,
|
||||
/* The piece is a literal. */
|
||||
DWARF_VALUE_LITERAL
|
||||
};
|
||||
|
||||
/* The expression evaluator works with a dwarf_expr_context, describing
|
||||
its current state and its callbacks. */
|
||||
struct dwarf_expr_context
|
||||
|
@ -80,9 +93,13 @@ struct dwarf_expr_context
|
|||
depth we'll tolerate before raising an error. */
|
||||
int recursion_depth, max_recursion_depth;
|
||||
|
||||
/* Non-zero if the result is in a register. The register number
|
||||
will be on the expression stack. */
|
||||
int in_reg;
|
||||
/* Location of the value. */
|
||||
enum dwarf_value_location location;
|
||||
|
||||
/* For VALUE_LITERAL, a the current literal value's length and
|
||||
data. */
|
||||
ULONGEST len;
|
||||
gdb_byte *data;
|
||||
|
||||
/* Initialization status of variable: Non-zero if variable has been
|
||||
initialized; zero otherwise. */
|
||||
|
@ -93,9 +110,9 @@ struct dwarf_expr_context
|
|||
|
||||
Each time DW_OP_piece is executed, we add a new element to the
|
||||
end of this array, recording the current top of the stack, the
|
||||
current in_reg flag, and the size given as the operand to
|
||||
DW_OP_piece. We then pop the top value from the stack, clear the
|
||||
in_reg flag, and resume evaluation.
|
||||
current location, and the size given as the operand to
|
||||
DW_OP_piece. We then pop the top value from the stack, rest the
|
||||
location, and resume evaluation.
|
||||
|
||||
The Dwarf spec doesn't say whether DW_OP_piece pops the top value
|
||||
from the stack. We do, ensuring that clients of this interface
|
||||
|
@ -106,12 +123,11 @@ struct dwarf_expr_context
|
|||
|
||||
If an expression never uses DW_OP_piece, num_pieces will be zero.
|
||||
(It would be nice to present these cases as expressions yielding
|
||||
a single piece, with in_reg clear, so that callers need not
|
||||
distinguish between the no-DW_OP_piece and one-DW_OP_piece cases.
|
||||
But expressions with no DW_OP_piece operations have no value to
|
||||
place in a piece's 'size' field; the size comes from the
|
||||
surrounding data. So the two cases need to be handled
|
||||
separately.) */
|
||||
a single piece, so that callers need not distinguish between the
|
||||
no-DW_OP_piece and one-DW_OP_piece cases. But expressions with
|
||||
no DW_OP_piece operations have no value to place in a piece's
|
||||
'size' field; the size comes from the surrounding data. So the
|
||||
two cases need to be handled separately.) */
|
||||
int num_pieces;
|
||||
struct dwarf_expr_piece *pieces;
|
||||
};
|
||||
|
@ -120,13 +136,22 @@ struct dwarf_expr_context
|
|||
/* A piece of an object, as recorded by DW_OP_piece. */
|
||||
struct dwarf_expr_piece
|
||||
{
|
||||
/* If IN_REG is zero, then the piece is in memory, and VALUE is its address.
|
||||
If IN_REG is non-zero, then the piece is in a register, and VALUE
|
||||
is the register number. */
|
||||
int in_reg;
|
||||
enum dwarf_value_location location;
|
||||
|
||||
/* This piece's address or register number. */
|
||||
CORE_ADDR value;
|
||||
union
|
||||
{
|
||||
/* This piece's address or register number. */
|
||||
CORE_ADDR value;
|
||||
|
||||
struct
|
||||
{
|
||||
/* A pointer to the data making up this piece, for literal
|
||||
pieces. */
|
||||
gdb_byte *data;
|
||||
/* The length of the available data. */
|
||||
ULONGEST length;
|
||||
} literal;
|
||||
} v;
|
||||
|
||||
/* The length of the piece, in bytes. */
|
||||
ULONGEST size;
|
||||
|
|
163
gdb/dwarf2loc.c
163
gdb/dwarf2loc.c
|
@ -220,6 +220,9 @@ struct piece_closure
|
|||
/* The number of pieces used to describe this variable. */
|
||||
int n_pieces;
|
||||
|
||||
/* The architecture, used only for DWARF_VALUE_STACK. */
|
||||
struct gdbarch *arch;
|
||||
|
||||
/* The pieces themselves. */
|
||||
struct dwarf_expr_piece *pieces;
|
||||
};
|
||||
|
@ -228,11 +231,13 @@ struct piece_closure
|
|||
PIECES. */
|
||||
|
||||
static struct piece_closure *
|
||||
allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces)
|
||||
allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces,
|
||||
struct gdbarch *arch)
|
||||
{
|
||||
struct piece_closure *c = XZALLOC (struct piece_closure);
|
||||
|
||||
c->n_pieces = n_pieces;
|
||||
c->arch = arch;
|
||||
c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece);
|
||||
|
||||
memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece));
|
||||
|
@ -253,24 +258,49 @@ read_pieced_value (struct value *v)
|
|||
for (i = 0; i < c->n_pieces; i++)
|
||||
{
|
||||
struct dwarf_expr_piece *p = &c->pieces[i];
|
||||
switch (p->location)
|
||||
{
|
||||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
bfd_byte regval[MAX_REGISTER_SIZE];
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
|
||||
p->v.value);
|
||||
get_frame_register (frame, gdb_regnum, regval);
|
||||
memcpy (contents + offset, regval, p->size);
|
||||
}
|
||||
break;
|
||||
|
||||
if (frame == NULL)
|
||||
{
|
||||
memset (contents + offset, 0, p->size);
|
||||
set_value_optimized_out (v, 1);
|
||||
}
|
||||
else if (p->in_reg)
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
gdb_byte regval[MAX_REGISTER_SIZE];
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value);
|
||||
case DWARF_VALUE_MEMORY:
|
||||
read_memory (p->v.value, contents + offset, p->size);
|
||||
break;
|
||||
|
||||
get_frame_register (frame, gdb_regnum, regval);
|
||||
memcpy (contents + offset, regval, p->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_memory (p->value, contents + offset, p->size);
|
||||
case DWARF_VALUE_STACK:
|
||||
{
|
||||
gdb_byte bytes[sizeof (ULONGEST)];
|
||||
size_t n;
|
||||
int addr_size = gdbarch_addr_bit (c->arch) / 8;
|
||||
store_unsigned_integer (bytes, addr_size,
|
||||
gdbarch_byte_order (c->arch),
|
||||
p->v.value);
|
||||
n = p->size;
|
||||
if (n > addr_size)
|
||||
n = addr_size;
|
||||
memcpy (contents + offset, bytes, n);
|
||||
}
|
||||
break;
|
||||
|
||||
case DWARF_VALUE_LITERAL:
|
||||
{
|
||||
size_t n = p->size;
|
||||
if (n > p->v.literal.length)
|
||||
n = p->v.literal.length;
|
||||
memcpy (contents + offset, p->v.literal.data, n);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__, _("invalid location type"));
|
||||
}
|
||||
offset += p->size;
|
||||
}
|
||||
|
@ -295,15 +325,21 @@ write_pieced_value (struct value *to, struct value *from)
|
|||
for (i = 0; i < c->n_pieces; i++)
|
||||
{
|
||||
struct dwarf_expr_piece *p = &c->pieces[i];
|
||||
if (p->in_reg)
|
||||
switch (p->location)
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value);
|
||||
put_frame_register (frame, gdb_regnum, contents + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_memory (p->value, contents + offset, p->size);
|
||||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value);
|
||||
put_frame_register (frame, gdb_regnum, contents + offset);
|
||||
}
|
||||
break;
|
||||
case DWARF_VALUE_MEMORY:
|
||||
write_memory (p->v.value, contents + offset, p->size);
|
||||
break;
|
||||
default:
|
||||
set_value_optimized_out (to, 1);
|
||||
return;
|
||||
}
|
||||
offset += p->size;
|
||||
}
|
||||
|
@ -314,7 +350,7 @@ copy_pieced_value_closure (struct value *v)
|
|||
{
|
||||
struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
|
||||
|
||||
return allocate_piece_closure (c->n_pieces, c->pieces);
|
||||
return allocate_piece_closure (c->n_pieces, c->pieces, c->arch);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -376,28 +412,71 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
|||
struct piece_closure *c;
|
||||
struct frame_id frame_id = get_frame_id (frame);
|
||||
|
||||
c = allocate_piece_closure (ctx->num_pieces, ctx->pieces);
|
||||
c = allocate_piece_closure (ctx->num_pieces, ctx->pieces, ctx->gdbarch);
|
||||
retval = allocate_computed_value (SYMBOL_TYPE (var),
|
||||
&pieced_value_funcs,
|
||||
c);
|
||||
VALUE_FRAME_ID (retval) = frame_id;
|
||||
}
|
||||
else if (ctx->in_reg)
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
|
||||
retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
|
||||
switch (ctx->location)
|
||||
{
|
||||
case DWARF_VALUE_REGISTER:
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
|
||||
int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
|
||||
retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
|
||||
}
|
||||
break;
|
||||
|
||||
retval = allocate_value (SYMBOL_TYPE (var));
|
||||
VALUE_LVAL (retval) = lval_memory;
|
||||
set_value_lazy (retval, 1);
|
||||
set_value_stack (retval, 1);
|
||||
set_value_address (retval, address);
|
||||
case DWARF_VALUE_MEMORY:
|
||||
{
|
||||
CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
|
||||
|
||||
retval = allocate_value (SYMBOL_TYPE (var));
|
||||
VALUE_LVAL (retval) = lval_memory;
|
||||
set_value_lazy (retval, 1);
|
||||
set_value_stack (retval, 1);
|
||||
set_value_address (retval, address);
|
||||
}
|
||||
break;
|
||||
|
||||
case DWARF_VALUE_STACK:
|
||||
{
|
||||
gdb_byte bytes[sizeof (ULONGEST)];
|
||||
ULONGEST value = (ULONGEST) dwarf_expr_fetch (ctx, 0);
|
||||
bfd_byte *contents;
|
||||
size_t n = ctx->addr_size;
|
||||
|
||||
store_unsigned_integer (bytes, ctx->addr_size,
|
||||
gdbarch_byte_order (ctx->gdbarch),
|
||||
value);
|
||||
retval = allocate_value (SYMBOL_TYPE (var));
|
||||
contents = value_contents_raw (retval);
|
||||
if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
|
||||
n = TYPE_LENGTH (SYMBOL_TYPE (var));
|
||||
memcpy (contents, bytes, n);
|
||||
}
|
||||
break;
|
||||
|
||||
case DWARF_VALUE_LITERAL:
|
||||
{
|
||||
bfd_byte *contents;
|
||||
size_t n = ctx->len;
|
||||
|
||||
retval = allocate_value (SYMBOL_TYPE (var));
|
||||
contents = value_contents_raw (retval);
|
||||
if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
|
||||
n = TYPE_LENGTH (SYMBOL_TYPE (var));
|
||||
memcpy (contents, ctx->data, n);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__, _("invalid location type"));
|
||||
}
|
||||
}
|
||||
|
||||
set_value_initialized (retval, ctx->initialized);
|
||||
|
@ -494,7 +573,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
|
|||
|
||||
dwarf_expr_eval (ctx, data, size);
|
||||
|
||||
in_reg = ctx->in_reg;
|
||||
in_reg = ctx->location == DWARF_VALUE_REGISTER;
|
||||
|
||||
if (ctx->num_pieces > 0)
|
||||
{
|
||||
|
@ -503,7 +582,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
|
|||
/* If the location has several pieces, and any of them are in
|
||||
registers, then we will need a frame to fetch them from. */
|
||||
for (i = 0; i < ctx->num_pieces; i++)
|
||||
if (ctx->pieces[i].in_reg)
|
||||
if (ctx->pieces[i].location == DWARF_VALUE_REGISTER)
|
||||
in_reg = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-09-11 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.dwarf2/valop.S: New file.
|
||||
* gdb.dwarf2/valop.exp: New file.
|
||||
|
||||
2009-09-11 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* gdb.threads/current-lwp-dead.exp: Only run this on Linux.
|
||||
|
|
505
gdb/testsuite/gdb.dwarf2/valop.S
Normal file
505
gdb/testsuite/gdb.dwarf2/valop.S
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
Copyright 2009 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/>.
|
||||
*/
|
||||
|
||||
/* This was compiled from a trivial program just to test the
|
||||
DW_OP_stack_value and DW_OP_implicit_value operators:
|
||||
|
||||
unsigned int func (unsigned int arg) __attribute__ ((__noinline__));
|
||||
|
||||
unsigned int func (unsigned int arg)
|
||||
{
|
||||
unsigned int uses_stack_op = 23;
|
||||
unsigned int uses_lit_op = 0x7fffffff;
|
||||
unsigned int result = arg;
|
||||
|
||||
if (arg % 2)
|
||||
result += uses_lit_op + uses_stack_op;
|
||||
else
|
||||
{
|
||||
++uses_stack_op;
|
||||
++uses_lit_op;
|
||||
|
||||
result -= uses_stack_op + uses_lit_op;
|
||||
}
|
||||
|
||||
return result * uses_stack_op; // line 19, see the .exp file
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
return func (1024);
|
||||
}
|
||||
|
||||
Then it was compiled with:
|
||||
|
||||
gcc -fvar-tracking{,-assignments} -gdwarf-3
|
||||
-fno-inline{,-functions,-small-functions,-functions-called-once}
|
||||
-O2
|
||||
|
||||
*/
|
||||
|
||||
.file "valop.c"
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.Ldebug_abbrev0:
|
||||
.section .debug_info,"",@progbits
|
||||
.Ldebug_info0:
|
||||
.section .debug_line,"",@progbits
|
||||
.Ldebug_line0:
|
||||
.text
|
||||
.Ltext0:
|
||||
.p2align 4,,15
|
||||
.globl func
|
||||
.type func, @function
|
||||
func:
|
||||
.LFB0:
|
||||
.file 1 "valop.c"
|
||||
.loc 1 4 0
|
||||
.cfi_startproc
|
||||
.LVL0:
|
||||
pushl %ebp
|
||||
.cfi_def_cfa_offset 8
|
||||
movl %esp, %ebp
|
||||
.cfi_offset 5, -8
|
||||
.cfi_def_cfa_register 5
|
||||
.loc 1 4 0
|
||||
movl 8(%ebp), %eax
|
||||
.LVL1:
|
||||
.loc 1 9 0
|
||||
testb $1, %al
|
||||
jne .L5
|
||||
.LVL2:
|
||||
.loc 1 16 0
|
||||
addl $2147483624, %eax
|
||||
.LVL3:
|
||||
.loc 1 13 0
|
||||
movl $24, %edx
|
||||
.LVL4:
|
||||
.loc 1 16 0
|
||||
imull %edx, %eax
|
||||
.LVL5:
|
||||
.loc 1 20 0
|
||||
popl %ebp
|
||||
.cfi_remember_state
|
||||
.cfi_restore 5
|
||||
.cfi_def_cfa 4, 4
|
||||
ret
|
||||
.LVL6:
|
||||
.p2align 4,,7
|
||||
.p2align 3
|
||||
.L5:
|
||||
.cfi_restore_state
|
||||
.loc 1 10 0
|
||||
subl $2147483626, %eax
|
||||
.LVL7:
|
||||
.loc 1 5 0
|
||||
movl $23, %edx
|
||||
.LVL8:
|
||||
.loc 1 16 0
|
||||
imull %edx, %eax
|
||||
.LVL9:
|
||||
.loc 1 20 0
|
||||
popl %ebp
|
||||
.cfi_def_cfa 4, 4
|
||||
.cfi_restore 5
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE0:
|
||||
.size func, .-func
|
||||
.p2align 4,,15
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
.LFB1:
|
||||
.loc 1 23 0
|
||||
.cfi_startproc
|
||||
.LVL10:
|
||||
pushl %ebp
|
||||
.cfi_def_cfa_offset 8
|
||||
movl %esp, %ebp
|
||||
.cfi_offset 5, -8
|
||||
.cfi_def_cfa_register 5
|
||||
subl $4, %esp
|
||||
.loc 1 24 0
|
||||
movl $1024, (%esp)
|
||||
call func
|
||||
.LVL11:
|
||||
.loc 1 25 0
|
||||
leave
|
||||
.cfi_restore 5
|
||||
.cfi_def_cfa 4, 4
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE1:
|
||||
.size _start, .-_start
|
||||
.Letext0:
|
||||
.section .debug_loc,"",@progbits
|
||||
.Ldebug_loc0:
|
||||
.LLST0:
|
||||
.long .LVL0-.Ltext0
|
||||
.long .LVL2-.Ltext0
|
||||
.value 0x4
|
||||
.byte 0x47
|
||||
.byte 0x9f
|
||||
.byte 0x93
|
||||
.uleb128 0x4
|
||||
.long .LVL2-.Ltext0
|
||||
.long .LVL4-.Ltext0
|
||||
.value 0x4
|
||||
.byte 0x48
|
||||
.byte 0x9f
|
||||
.byte 0x93
|
||||
.uleb128 0x4
|
||||
.long .LVL4-.Ltext0
|
||||
.long .LVL6-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x52
|
||||
.long .LVL6-.Ltext0
|
||||
.long .LVL8-.Ltext0
|
||||
.value 0x4
|
||||
.byte 0x47
|
||||
.byte 0x9f
|
||||
.byte 0x93
|
||||
.uleb128 0x4
|
||||
.long .LVL8-.Ltext0
|
||||
.long .LFE0-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x52
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.LLST1:
|
||||
.long .LVL0-.Ltext0
|
||||
.long .LVL2-.Ltext0
|
||||
.value 0x6
|
||||
.byte 0x9e
|
||||
.uleb128 0x4
|
||||
.long 0x7fffffff
|
||||
.long .LVL2-.Ltext0
|
||||
.long .LVL6-.Ltext0
|
||||
.value 0x6
|
||||
.byte 0x9e
|
||||
.uleb128 0x4
|
||||
.long 0x80000000
|
||||
.long .LVL6-.Ltext0
|
||||
.long .LFE0-.Ltext0
|
||||
.value 0x6
|
||||
.byte 0x9e
|
||||
.uleb128 0x4
|
||||
.long 0x7fffffff
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.LLST2:
|
||||
.long .LVL1-.Ltext0
|
||||
.long .LVL3-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x50
|
||||
.long .LVL3-.Ltext0
|
||||
.long .LVL5-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x50
|
||||
.long .LVL6-.Ltext0
|
||||
.long .LVL7-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x50
|
||||
.long .LVL7-.Ltext0
|
||||
.long .LVL9-.Ltext0
|
||||
.value 0x1
|
||||
.byte 0x50
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.LLST3:
|
||||
.long .LVL10-.Ltext0
|
||||
.long .LVL11-1-.Ltext0
|
||||
.value 0x2
|
||||
.byte 0x91
|
||||
.sleb128 0
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.LLST4:
|
||||
.long .LVL10-.Ltext0
|
||||
.long .LVL11-1-.Ltext0
|
||||
.value 0x2
|
||||
.byte 0x91
|
||||
.sleb128 4
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.section .debug_info
|
||||
.long 0xd4
|
||||
.value 0x3
|
||||
.long .Ldebug_abbrev0
|
||||
.byte 0x4
|
||||
.uleb128 0x1
|
||||
.long .LASF9
|
||||
.byte 0x1
|
||||
.long .LASF10
|
||||
.long .LASF11
|
||||
.long .Ltext0
|
||||
.long .Letext0
|
||||
.long .Ldebug_line0
|
||||
.uleb128 0x2
|
||||
.byte 0x1
|
||||
.long .LASF3
|
||||
.byte 0x1
|
||||
.byte 0x3
|
||||
.byte 0x1
|
||||
.long 0x7c
|
||||
.long .LFB0
|
||||
.long .LFE0
|
||||
.byte 0x1
|
||||
.byte 0x9c
|
||||
.long 0x7c
|
||||
.uleb128 0x3
|
||||
.string "arg"
|
||||
.byte 0x1
|
||||
.byte 0x3
|
||||
.long 0x7c
|
||||
.byte 0x2
|
||||
.byte 0x91
|
||||
.sleb128 0
|
||||
.uleb128 0x4
|
||||
.long .LASF0
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.long 0x7c
|
||||
.long .LLST0
|
||||
.uleb128 0x4
|
||||
.long .LASF1
|
||||
.byte 0x1
|
||||
.byte 0x6
|
||||
.long 0x7c
|
||||
.long .LLST1
|
||||
.uleb128 0x4
|
||||
.long .LASF2
|
||||
.byte 0x1
|
||||
.byte 0x7
|
||||
.long 0x7c
|
||||
.long .LLST2
|
||||
.byte 0x0
|
||||
.uleb128 0x5
|
||||
.byte 0x4
|
||||
.byte 0x7
|
||||
.long .LASF7
|
||||
.uleb128 0x2
|
||||
.byte 0x1
|
||||
.long .LASF4
|
||||
.byte 0x1
|
||||
.byte 0x16
|
||||
.byte 0x1
|
||||
.long 0xbd
|
||||
.long .LFB1
|
||||
.long .LFE1
|
||||
.byte 0x1
|
||||
.byte 0x9c
|
||||
.long 0xbd
|
||||
.uleb128 0x6
|
||||
.long .LASF5
|
||||
.byte 0x1
|
||||
.byte 0x16
|
||||
.long 0xbd
|
||||
.long .LLST3
|
||||
.uleb128 0x6
|
||||
.long .LASF6
|
||||
.byte 0x1
|
||||
.byte 0x16
|
||||
.long 0xc4
|
||||
.long .LLST4
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.byte 0x4
|
||||
.byte 0x5
|
||||
.string "int"
|
||||
.uleb128 0x8
|
||||
.byte 0x4
|
||||
.long 0xca
|
||||
.uleb128 0x8
|
||||
.byte 0x4
|
||||
.long 0xd0
|
||||
.uleb128 0x5
|
||||
.byte 0x1
|
||||
.byte 0x6
|
||||
.long .LASF8
|
||||
.byte 0x0
|
||||
.section .debug_abbrev
|
||||
.uleb128 0x1
|
||||
.uleb128 0x11
|
||||
.byte 0x1
|
||||
.uleb128 0x25
|
||||
.uleb128 0xe
|
||||
.uleb128 0x13
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x1b
|
||||
.uleb128 0xe
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x1
|
||||
.uleb128 0x10
|
||||
.uleb128 0x6
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x2
|
||||
.uleb128 0x2e
|
||||
.byte 0x1
|
||||
.uleb128 0x3f
|
||||
.uleb128 0xc
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x27
|
||||
.uleb128 0xc
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x1
|
||||
.uleb128 0x40
|
||||
.uleb128 0xa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x13
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x3
|
||||
.uleb128 0x5
|
||||
.byte 0x0
|
||||
.uleb128 0x3
|
||||
.uleb128 0x8
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x2
|
||||
.uleb128 0xa
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x4
|
||||
.uleb128 0x34
|
||||
.byte 0x0
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x2
|
||||
.uleb128 0x6
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x5
|
||||
.uleb128 0x24
|
||||
.byte 0x0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3e
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x6
|
||||
.uleb128 0x5
|
||||
.byte 0x0
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x2
|
||||
.uleb128 0x6
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.uleb128 0x24
|
||||
.byte 0x0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3e
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3
|
||||
.uleb128 0x8
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.uleb128 0x8
|
||||
.uleb128 0xf
|
||||
.byte 0x0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.section .debug_pubnames,"",@progbits
|
||||
.long 0x20
|
||||
.value 0x2
|
||||
.long .Ldebug_info0
|
||||
.long 0xd8
|
||||
.long 0x25
|
||||
.string "func"
|
||||
.long 0x83
|
||||
.string "main"
|
||||
.long 0x0
|
||||
.section .debug_aranges,"",@progbits
|
||||
.long 0x1c
|
||||
.value 0x2
|
||||
.long .Ldebug_info0
|
||||
.byte 0x4
|
||||
.byte 0x0
|
||||
.value 0x0
|
||||
.value 0x0
|
||||
.long .Ltext0
|
||||
.long .Letext0-.Ltext0
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.LASF7:
|
||||
.string "unsigned int"
|
||||
.LASF3:
|
||||
.string "func"
|
||||
.LASF0:
|
||||
.string "uses_stack_op"
|
||||
.LASF5:
|
||||
.string "argc"
|
||||
.LASF10:
|
||||
.string "valop.c"
|
||||
.LASF2:
|
||||
.string "result"
|
||||
.LASF8:
|
||||
.string "char"
|
||||
.LASF9:
|
||||
.string "GNU C 4.5.0 20090818 (experimental) [var-tracking-assignments-branch revision 150964]"
|
||||
.LASF4:
|
||||
.string "main"
|
||||
.LASF11:
|
||||
.string "/tmp"
|
||||
.LASF1:
|
||||
.string "uses_lit_op"
|
||||
.LASF6:
|
||||
.string "argv"
|
||||
.ident "GCC: (GNU) 4.5.0 20090818 (experimental) [var-tracking-assignments-branch revision 150964]"
|
||||
.section .note.GNU-stack,"",@progbits
|
55
gdb/testsuite/gdb.dwarf2/valop.exp
Normal file
55
gdb/testsuite/gdb.dwarf2/valop.exp
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Copyright 2009 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/>.
|
||||
|
||||
# Test DW_OP_stack_value and DW_OP_implicit_value.
|
||||
|
||||
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
# For now pick a sampling of likely targets.
|
||||
if {![istarget *-*-linux*]
|
||||
&& ![istarget *-*-gnu*]
|
||||
&& ![istarget *-*-elf*]
|
||||
&& ![istarget *-*-openbsd*]
|
||||
&& ![istarget arm-*-eabi*]
|
||||
&& ![istarget powerpc-*-eabi*]} {
|
||||
return 0
|
||||
}
|
||||
# This test can only be run on x86 targets.
|
||||
if {![istarget i?86-*]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
set testfile "valop"
|
||||
set srcfile ${testfile}.S
|
||||
set binfile ${objdir}/${subdir}/${testfile}.x
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
|
||||
[list {additional_flags=-nostdlib}]] != "" } {
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
gdb_load ${binfile}
|
||||
|
||||
if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_test "break valop.c:19" "Breakpoint 2.*" "set breakpoint for valop"
|
||||
gdb_continue_to_breakpoint "continue to breakpoint for valop"
|
||||
|
||||
gdb_test "print uses_stack_op" " = 24" "print uses_stack_op"
|
||||
gdb_test "print uses_lit_op" " = 2147483648" "print uses_lit_op"
|
Loading…
Reference in a new issue