* 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:
Tom Tromey 2009-09-11 18:38:39 +00:00
parent a05e8785c7
commit cec03d703f
8 changed files with 822 additions and 80 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

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