Update intree gdb/kgdb to handle 2 dwarf types:
DW_OP_GNU_uninit DW_OP_piece This squashes the warnings about type 0x93 not known in kgdb when opening a kernel crash dump. Upstream refs: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=87808bd699575a850139a1f916512ab7a47fd496 https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=42be36b328ae784ae6981da7c7cab95b67ed7737 https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=23572ecadc89af384c1804ad7692f32c55fbfc80 Differential Revision: https://reviews.freebsd.org/D2534 Reviewed by: emaste, jhb, davide
This commit is contained in:
parent
587b51331a
commit
76da95eba4
@ -547,6 +547,7 @@ enum dwarf_location_atom
|
|||||||
DW_OP_bit_piece = 0x9d,
|
DW_OP_bit_piece = 0x9d,
|
||||||
/* GNU extensions. */
|
/* GNU extensions. */
|
||||||
DW_OP_GNU_push_tls_address = 0xe0,
|
DW_OP_GNU_push_tls_address = 0xe0,
|
||||||
|
DW_OP_GNU_uninit = 0xf0,
|
||||||
/* HP extensions. */
|
/* HP extensions. */
|
||||||
DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
|
DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
|
||||||
DW_OP_HP_is_value = 0xe1,
|
DW_OP_HP_is_value = 0xe1,
|
||||||
|
@ -559,6 +559,10 @@ c_value_print (struct value *val, struct ui_file *stream, int format,
|
|||||||
fprintf_filtered (stream, ") ");
|
fprintf_filtered (stream, ") ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!value_initialized (val))
|
||||||
|
fprintf_filtered (stream, " [uninitialized] ");
|
||||||
|
|
||||||
if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
|
if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
|
||||||
{
|
{
|
||||||
/* Attempt to determine real type of object */
|
/* Attempt to determine real type of object */
|
||||||
|
@ -42,6 +42,8 @@ new_dwarf_expr_context (void)
|
|||||||
retval->stack_len = 0;
|
retval->stack_len = 0;
|
||||||
retval->stack_allocated = 10;
|
retval->stack_allocated = 10;
|
||||||
retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
|
retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
|
||||||
|
retval->num_pieces = 0;
|
||||||
|
retval->pieces = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +53,7 @@ void
|
|||||||
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
|
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
|
||||||
{
|
{
|
||||||
xfree (ctx->stack);
|
xfree (ctx->stack);
|
||||||
|
xfree (ctx->pieces);
|
||||||
xfree (ctx);
|
xfree (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +103,29 @@ 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)
|
||||||
|
{
|
||||||
|
struct dwarf_expr_piece *p;
|
||||||
|
|
||||||
|
ctx->num_pieces++;
|
||||||
|
|
||||||
|
if (ctx->pieces)
|
||||||
|
ctx->pieces = xrealloc (ctx->pieces,
|
||||||
|
(ctx->num_pieces
|
||||||
|
* sizeof (struct dwarf_expr_piece)));
|
||||||
|
else
|
||||||
|
ctx->pieces = xmalloc (ctx->num_pieces
|
||||||
|
* sizeof (struct dwarf_expr_piece));
|
||||||
|
|
||||||
|
p = &ctx->pieces[ctx->num_pieces - 1];
|
||||||
|
p->in_reg = in_reg;
|
||||||
|
p->value = value;
|
||||||
|
p->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
/* Evaluate the expression at ADDR (LEN bytes long) using the context
|
/* Evaluate the expression at ADDR (LEN bytes long) using the context
|
||||||
CTX. */
|
CTX. */
|
||||||
|
|
||||||
@ -230,6 +256,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||||||
unsigned char *op_end)
|
unsigned char *op_end)
|
||||||
{
|
{
|
||||||
ctx->in_reg = 0;
|
ctx->in_reg = 0;
|
||||||
|
ctx->initialized = 1; /* Default is initialized. */
|
||||||
|
|
||||||
while (op_ptr < op_end)
|
while (op_ptr < op_end)
|
||||||
{
|
{
|
||||||
@ -356,9 +383,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||||||
case DW_OP_reg29:
|
case DW_OP_reg29:
|
||||||
case DW_OP_reg30:
|
case DW_OP_reg30:
|
||||||
case DW_OP_reg31:
|
case DW_OP_reg31:
|
||||||
if (op_ptr != op_end && *op_ptr != DW_OP_piece)
|
if (op_ptr != op_end
|
||||||
error ("DWARF-2 expression error: DW_OP_reg operations must be "
|
&& *op_ptr != DW_OP_piece
|
||||||
"used either alone or in conjuction with DW_OP_piece.");
|
&& *op_ptr != DW_OP_bit_piece
|
||||||
|
&& *op_ptr != DW_OP_GNU_uninit)
|
||||||
|
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
|
||||||
|
"used either alone or in conjuction with DW_OP_piece."));
|
||||||
|
|
||||||
result = op - DW_OP_reg0;
|
result = op - DW_OP_reg0;
|
||||||
ctx->in_reg = 1;
|
ctx->in_reg = 1;
|
||||||
@ -661,6 +691,30 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
|||||||
case DW_OP_nop:
|
case DW_OP_nop:
|
||||||
goto no_push;
|
goto no_push;
|
||||||
|
|
||||||
|
case DW_OP_piece:
|
||||||
|
{
|
||||||
|
ULONGEST size;
|
||||||
|
CORE_ADDR addr_or_regnum;
|
||||||
|
|
||||||
|
/* Record the piece. */
|
||||||
|
op_ptr = read_uleb128 (op_ptr, op_end, &size);
|
||||||
|
addr_or_regnum = dwarf_expr_fetch (ctx, 0);
|
||||||
|
add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
|
||||||
|
|
||||||
|
/* Pop off the address/regnum, and clear the in_reg flag. */
|
||||||
|
dwarf_expr_pop (ctx);
|
||||||
|
ctx->in_reg = 0;
|
||||||
|
}
|
||||||
|
goto no_push;
|
||||||
|
|
||||||
|
case DW_OP_GNU_uninit:
|
||||||
|
if (op_ptr != op_end)
|
||||||
|
error (_("DWARF-2 expression error: DW_OP_GNU_unint must always "
|
||||||
|
"be the very last op."));
|
||||||
|
|
||||||
|
ctx->initialized = 0;
|
||||||
|
goto no_push;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error ("Unhandled dwarf expression opcode 0x%x", op);
|
error ("Unhandled dwarf expression opcode 0x%x", op);
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,51 @@ struct dwarf_expr_context
|
|||||||
/* Non-zero if the result is in a register. The register number
|
/* Non-zero if the result is in a register. The register number
|
||||||
will be on the expression stack. */
|
will be on the expression stack. */
|
||||||
int in_reg;
|
int in_reg;
|
||||||
|
/* Initialization status of variable: Non-zero if variable has been
|
||||||
|
initialized; zero otherwise. */
|
||||||
|
int initialized;
|
||||||
|
|
||||||
|
/* An array of pieces. PIECES points to its first element;
|
||||||
|
NUM_PIECES is its length.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
expecting to see a value left on the top of the stack (say, code
|
||||||
|
evaluating frame base expressions or CFA's specified with
|
||||||
|
DW_CFA_def_cfa_expression) will get an error if the expression
|
||||||
|
actually marks all the values it computes as pieces.
|
||||||
|
|
||||||
|
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.) */
|
||||||
|
int num_pieces;
|
||||||
|
struct dwarf_expr_piece *pieces;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A piece of an object, as recorded by DW_OP_piece or DW_OP_bit_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;
|
||||||
|
|
||||||
|
/* This piece's address or register number. */
|
||||||
|
CORE_ADDR value;
|
||||||
|
|
||||||
|
/* The length of the piece, in bytes. */
|
||||||
|
ULONGEST size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dwarf_expr_context *new_dwarf_expr_context (void);
|
struct dwarf_expr_context *new_dwarf_expr_context (void);
|
||||||
|
@ -206,6 +206,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
|||||||
struct objfile *objfile)
|
struct objfile *objfile)
|
||||||
{
|
{
|
||||||
CORE_ADDR result;
|
CORE_ADDR result;
|
||||||
|
struct gdbarch *arch = get_frame_arch (frame);
|
||||||
struct value *retval;
|
struct value *retval;
|
||||||
struct dwarf_expr_baton baton;
|
struct dwarf_expr_baton baton;
|
||||||
struct dwarf_expr_context *ctx;
|
struct dwarf_expr_context *ctx;
|
||||||
@ -230,7 +231,32 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
|||||||
dwarf_expr_eval (ctx, data, size);
|
dwarf_expr_eval (ctx, data, size);
|
||||||
result = dwarf_expr_fetch (ctx, 0);
|
result = dwarf_expr_fetch (ctx, 0);
|
||||||
|
|
||||||
if (ctx->in_reg)
|
if (ctx->num_pieces > 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long offset = 0;
|
||||||
|
bfd_byte *contents;
|
||||||
|
|
||||||
|
retval = allocate_value (SYMBOL_TYPE (var));
|
||||||
|
contents = VALUE_CONTENTS_RAW (retval);
|
||||||
|
for (i = 0; i < ctx->num_pieces; i++)
|
||||||
|
{
|
||||||
|
struct dwarf_expr_piece *p = &ctx->pieces[i];
|
||||||
|
if (p->in_reg)
|
||||||
|
{
|
||||||
|
bfd_byte regval[MAX_REGISTER_SIZE];
|
||||||
|
int gdb_regnum = DWARF2_REG_TO_REGNUM (p->value);
|
||||||
|
get_frame_register (frame, gdb_regnum, regval);
|
||||||
|
memcpy (contents + offset, regval, p->size);
|
||||||
|
}
|
||||||
|
else /* In memory? */
|
||||||
|
{
|
||||||
|
read_memory (p->value, contents + offset, p->size);
|
||||||
|
}
|
||||||
|
offset += p->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ctx->in_reg)
|
||||||
{
|
{
|
||||||
int regnum = DWARF2_REG_TO_REGNUM (result);
|
int regnum = DWARF2_REG_TO_REGNUM (result);
|
||||||
retval = value_from_register (SYMBOL_TYPE (var), regnum, frame);
|
retval = value_from_register (SYMBOL_TYPE (var), regnum, frame);
|
||||||
@ -245,6 +271,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
|||||||
VALUE_ADDRESS (retval) = result;
|
VALUE_ADDRESS (retval) = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_value_initialized (retval, ctx->initialized);
|
||||||
|
|
||||||
free_dwarf_expr_context (ctx);
|
free_dwarf_expr_context (ctx);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
@ -322,6 +350,17 @@ dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
|
|||||||
|
|
||||||
in_reg = ctx->in_reg;
|
in_reg = ctx->in_reg;
|
||||||
|
|
||||||
|
if (ctx->num_pieces > 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
in_reg = 1;
|
||||||
|
}
|
||||||
|
|
||||||
free_dwarf_expr_context (ctx);
|
free_dwarf_expr_context (ctx);
|
||||||
|
|
||||||
return baton.needs_frame || in_reg;
|
return baton.needs_frame || in_reg;
|
||||||
|
@ -7110,6 +7110,8 @@ dwarf_stack_op_name (unsigned op)
|
|||||||
/* GNU extensions. */
|
/* GNU extensions. */
|
||||||
case DW_OP_GNU_push_tls_address:
|
case DW_OP_GNU_push_tls_address:
|
||||||
return "DW_OP_GNU_push_tls_address";
|
return "DW_OP_GNU_push_tls_address";
|
||||||
|
case DW_OP_GNU_uninit:
|
||||||
|
return "DW_OP_GNU_uninit";
|
||||||
default:
|
default:
|
||||||
return "OP_<unknown>";
|
return "OP_<unknown>";
|
||||||
}
|
}
|
||||||
@ -7634,6 +7636,9 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
|
|||||||
dwarf2_complex_location_expr_complaint ();
|
dwarf2_complex_location_expr_complaint ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_OP_GNU_uninit:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
complaint (&symfile_complaints, "unsupported stack op: '%s'",
|
complaint (&symfile_complaints, "unsupported stack op: '%s'",
|
||||||
dwarf_stack_op_name (op));
|
dwarf_stack_op_name (op));
|
||||||
|
@ -165,6 +165,9 @@ struct value
|
|||||||
/* The BFD section associated with this value. */
|
/* The BFD section associated with this value. */
|
||||||
asection *bfd_section;
|
asection *bfd_section;
|
||||||
|
|
||||||
|
/* If value is a variable, is it initialized or not. */
|
||||||
|
int initialized;
|
||||||
|
|
||||||
/* Actual contents of the value. For use of this value; setting
|
/* Actual contents of the value. For use of this value; setting
|
||||||
it uses the stuff above. Not valid if lazy is nonzero.
|
it uses the stuff above. Not valid if lazy is nonzero.
|
||||||
Target byte-order. We force it to be aligned properly for any
|
Target byte-order. We force it to be aligned properly for any
|
||||||
|
@ -101,6 +101,7 @@ allocate_value (struct type *type)
|
|||||||
VALUE_EMBEDDED_OFFSET (val) = 0;
|
VALUE_EMBEDDED_OFFSET (val) = 0;
|
||||||
VALUE_POINTED_TO_OFFSET (val) = 0;
|
VALUE_POINTED_TO_OFFSET (val) = 0;
|
||||||
val->modifiable = 1;
|
val->modifiable = 1;
|
||||||
|
val->initialized = 1; /* Default to initialized. */
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1311,6 +1312,22 @@ using_struct_return (struct type *value_type, int gcc_p)
|
|||||||
== RETURN_VALUE_STRUCT_CONVENTION);
|
== RETURN_VALUE_STRUCT_CONVENTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the initialized field in a value struct. */
|
||||||
|
|
||||||
|
void
|
||||||
|
set_value_initialized (struct value *val, int status)
|
||||||
|
{
|
||||||
|
val->initialized = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the initialized field in a value struct. */
|
||||||
|
|
||||||
|
int
|
||||||
|
value_initialized (struct value *val)
|
||||||
|
{
|
||||||
|
return val->initialized;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_values (void)
|
_initialize_values (void)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user