Code cleanup: Generalize call_site.parameter key.
	* dwarf2expr.c (execute_stack_op) <DW_OP_GNU_entry_value>: Remove
	variable dwarf_reg.  New variable kind_u.  Update parameters to
	push_dwarf_reg_entry_value.
	(ctx_no_push_dwarf_reg_entry_value): Update parameters.
	* dwarf2expr.h (enum call_site_parameter_kind)
	(union call_site_parameter_u): Forward declarations.
	(struct dwarf_expr_context_funcs): Update parameters and their
	description for push_dwarf_reg_entry_value.
	(ctx_no_push_dwarf_reg_entry_value): Update parameters.
	* dwarf2loc.c (call_site_parameter_matches): New function.
	(dwarf_expr_reg_to_entry_parameter): Update parameters and their
	description.  Use call_site_parameter_matches.
	(dwarf_expr_push_dwarf_reg_entry_value, value_of_dwarf_reg_entry):
	Update parameters and their description.
	(value_of_dwarf_block_entry): Remove variables dwarf_reg and fb_offset.
	New variable kind_u.  Adjust the caller for updated parameters.
	(needs_dwarf_reg_entry_value): Update parameters.
	* dwarf2read.c (read_call_site_scope): New variable loc.  Use it
	instead of attr.  Update for the changed fields of struct
	call_site_parameter.
	* gdbtypes.h: Include dwarf2expr.h.
	(enum call_site_parameter_kind): New.
	(struct call_site.parameter): New field kind.  Wrap dwarf_reg and
	fb_offset into new union u.
This commit is contained in:
Jan Kratochvil 2012-06-17 19:50:53 +00:00
parent e8c21678a4
commit 24c5c679cb
6 changed files with 144 additions and 73 deletions

View File

@ -1,3 +1,31 @@
2012-06-17 Jan Kratochvil <jan.kratochvil@redhat.com>
Code cleanup: Generalize call_site.parameter key.
* dwarf2expr.c (execute_stack_op) <DW_OP_GNU_entry_value>: Remove
variable dwarf_reg. New variable kind_u. Update parameters to
push_dwarf_reg_entry_value.
(ctx_no_push_dwarf_reg_entry_value): Update parameters.
* dwarf2expr.h (enum call_site_parameter_kind)
(union call_site_parameter_u): Forward declarations.
(struct dwarf_expr_context_funcs): Update parameters and their
description for push_dwarf_reg_entry_value.
(ctx_no_push_dwarf_reg_entry_value): Update parameters.
* dwarf2loc.c (call_site_parameter_matches): New function.
(dwarf_expr_reg_to_entry_parameter): Update parameters and their
description. Use call_site_parameter_matches.
(dwarf_expr_push_dwarf_reg_entry_value, value_of_dwarf_reg_entry):
Update parameters and their description.
(value_of_dwarf_block_entry): Remove variables dwarf_reg and fb_offset.
New variable kind_u. Adjust the caller for updated parameters.
(needs_dwarf_reg_entry_value): Update parameters.
* dwarf2read.c (read_call_site_scope): New variable loc. Use it
instead of attr. Update for the changed fields of struct
call_site_parameter.
* gdbtypes.h: Include dwarf2expr.h.
(enum call_site_parameter_kind): New.
(struct call_site.parameter): New field kind. Wrap dwarf_reg and
fb_offset into new union u.
2012-06-16 H.J. Lu <hongjiu.lu@intel.com>
* amd64-tdep.c (amd64_x32_analyze_stack_align): New function.

View File

@ -1355,33 +1355,35 @@ execute_stack_op (struct dwarf_expr_context *ctx,
case DW_OP_GNU_entry_value:
{
uint64_t len;
int dwarf_reg;
CORE_ADDR deref_size;
union call_site_parameter_u kind_u;
op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
if (op_ptr + len > op_end)
error (_("DW_OP_GNU_entry_value: too few bytes available."));
dwarf_reg = dwarf_block_to_dwarf_reg (op_ptr, op_ptr + len);
if (dwarf_reg != -1)
kind_u.dwarf_reg = dwarf_block_to_dwarf_reg (op_ptr, op_ptr + len);
if (kind_u.dwarf_reg != -1)
{
op_ptr += len;
ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
0 /* unused */,
ctx->funcs->push_dwarf_reg_entry_value (ctx,
CALL_SITE_PARAMETER_DWARF_REG,
kind_u,
-1 /* deref_size */);
goto no_push;
}
dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr, op_ptr + len,
&deref_size);
if (dwarf_reg != -1)
kind_u.dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr,
op_ptr + len,
&deref_size);
if (kind_u.dwarf_reg != -1)
{
if (deref_size == -1)
deref_size = ctx->addr_size;
op_ptr += len;
ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
0 /* unused */,
deref_size);
ctx->funcs->push_dwarf_reg_entry_value (ctx,
CALL_SITE_PARAMETER_DWARF_REG,
kind_u, deref_size);
goto no_push;
}
@ -1533,7 +1535,8 @@ ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset die)
void
ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
int deref_size)
{
internal_error (__FILE__, __LINE__,

View File

@ -26,6 +26,8 @@
#include "leb128.h"
struct dwarf_expr_context;
enum call_site_parameter_kind;
union call_site_parameter_u;
/* Offset relative to the start of its containing CU (compilation unit). */
typedef struct
@ -77,14 +79,12 @@ struct dwarf_expr_context_funcs
struct type *(*get_base_type) (struct dwarf_expr_context *ctx, cu_offset die);
/* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
DWARF_REG/FB_OFFSET at the caller of specified BATON. If DWARF register
number DWARF_REG specifying the push_dwarf_reg_entry_value parameter is
not -1 FB_OFFSET is ignored. Otherwise FB_OFFSET specifies stack
parameter offset against caller's stack pointer (which equals the callee's
frame base). If DEREF_SIZE is not -1 then use
DW_AT_GNU_call_site_data_value instead of DW_AT_GNU_call_site_value. */
parameter matching KIND and KIND_U at the caller of specified BATON.
If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
DW_AT_GNU_call_site_value. */
void (*push_dwarf_reg_entry_value) (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
int deref_size);
/* Return the address indexed by DW_OP_GNU_addr_index.
@ -289,7 +289,8 @@ void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset);
struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx,
cu_offset die);
void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
int deref_size);
CORE_ADDR ctx_no_get_addr_index (void *baton, unsigned int index);

View File

@ -948,16 +948,34 @@ call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
return retval;
}
/* Fetch call_site_parameter from caller matching the parameters. FRAME is for
callee. See DWARF_REG and FB_OFFSET description at struct
dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
/* Return 1 if KIND and KIND_U match PARAMETER. Return 0 otherwise. */
static int
call_site_parameter_matches (struct call_site_parameter *parameter,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u)
{
if (kind == parameter->kind)
switch (kind)
{
case CALL_SITE_PARAMETER_DWARF_REG:
return kind_u.dwarf_reg == parameter->u.dwarf_reg;
case CALL_SITE_PARAMETER_FB_OFFSET:
return kind_u.fb_offset == parameter->u.fb_offset;
}
return 0;
}
/* Fetch call_site_parameter from caller matching KIND and KIND_U.
FRAME is for callee.
Function always returns non-NULL, it throws NO_ENTRY_VALUE_ERROR
otherwise. */
static struct call_site_parameter *
dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
CORE_ADDR fb_offset,
dwarf_expr_reg_to_entry_parameter (struct frame_info *frame,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
struct dwarf2_per_cu_data **per_cu_return)
{
CORE_ADDR func_addr = get_frame_func (frame);
@ -1020,12 +1038,7 @@ dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
for (iparams = 0; iparams < call_site->parameter_count; iparams++)
{
parameter = &call_site->parameter[iparams];
if (parameter->dwarf_reg == -1 && dwarf_reg == -1)
{
if (parameter->fb_offset == fb_offset)
break;
}
else if (parameter->dwarf_reg == dwarf_reg)
if (call_site_parameter_matches (parameter, kind, kind_u))
break;
}
if (iparams == call_site->parameter_count)
@ -1082,17 +1095,17 @@ dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
}
/* Execute call_site_parameter's DWARF block matching DEREF_SIZE for caller of
the CTX's frame. CTX must be of dwarf_expr_ctx_funcs kind. See DWARF_REG
and FB_OFFSET description at struct
dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
/* Execute DWARF block of call_site_parameter which matches KIND and KIND_U.
Choose DEREF_SIZE value of that parameter. Search caller of the CTX's
frame. CTX must be of dwarf_expr_ctx_funcs kind.
The CTX caller can be from a different CU - per_cu_dwarf_call implementation
can be more simple as it does not support cross-CU DWARF executions. */
static void
dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
int deref_size)
{
struct dwarf_expr_baton *debaton;
@ -1109,7 +1122,7 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
frame = debaton->frame;
caller_frame = get_prev_frame (frame);
parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
&caller_per_cu);
data_src = deref_size == -1 ? parameter->value : parameter->data_value;
size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
@ -1206,17 +1219,17 @@ static const struct lval_funcs entry_data_value_funcs =
entry_data_value_free_closure
};
/* Read parameter of TYPE at (callee) FRAME's function entry. DWARF_REG and
FB_OFFSET are used to match DW_AT_location at the caller's
DW_TAG_GNU_call_site_parameter. See DWARF_REG and FB_OFFSET description at
struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
/* Read parameter of TYPE at (callee) FRAME's function entry. KIND and KIND_U
are used to match DW_AT_location at the caller's
DW_TAG_GNU_call_site_parameter.
Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if it
cannot resolve the parameter for any reason. */
static struct value *
value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
int dwarf_reg, CORE_ADDR fb_offset)
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u)
{
struct type *checked_type = check_typedef (type);
struct type *target_type = TYPE_TARGET_TYPE (checked_type);
@ -1226,7 +1239,7 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
struct dwarf2_per_cu_data *caller_per_cu;
CORE_ADDR addr;
parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
&caller_per_cu);
outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */,
@ -1278,15 +1291,16 @@ static struct value *
value_of_dwarf_block_entry (struct type *type, struct frame_info *frame,
const gdb_byte *block, size_t block_len)
{
int dwarf_reg;
CORE_ADDR fb_offset;
union call_site_parameter_u kind_u;
dwarf_reg = dwarf_block_to_dwarf_reg (block, block + block_len);
if (dwarf_reg != -1)
return value_of_dwarf_reg_entry (type, frame, dwarf_reg, 0 /* unused */);
kind_u.dwarf_reg = dwarf_block_to_dwarf_reg (block, block + block_len);
if (kind_u.dwarf_reg != -1)
return value_of_dwarf_reg_entry (type, frame, CALL_SITE_PARAMETER_DWARF_REG,
kind_u);
if (dwarf_block_to_fb_offset (block, block + block_len, &fb_offset))
return value_of_dwarf_reg_entry (type, frame, -1, fb_offset);
if (dwarf_block_to_fb_offset (block, block + block_len, &kind_u.fb_offset))
return value_of_dwarf_reg_entry (type, frame, CALL_SITE_PARAMETER_FB_OFFSET,
kind_u);
/* This can normally happen - throw NO_ENTRY_VALUE_ERROR to get the message
suppressed during normal operation. The expression can be arbitrary if
@ -2377,7 +2391,8 @@ needs_frame_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
static void
needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset, int deref_size)
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u, int deref_size)
{
struct needs_frame_baton *nf_baton = ctx->baton;

View File

@ -7812,6 +7812,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
child_die = sibling_die (child_die))
{
struct call_site_parameter *parameter;
struct attribute *loc;
if (child_die->tag != DW_TAG_GNU_call_site_parameter)
{
@ -7825,8 +7826,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
/* DW_AT_location specifies the register number. Value of the data
assumed for the register is contained in DW_AT_GNU_call_site_value. */
attr = dwarf2_attr (child_die, DW_AT_location, cu);
if (!attr || !attr_form_is_block (attr))
loc = dwarf2_attr (child_die, DW_AT_location, cu);
if (loc == NULL || !attr_form_is_block (loc))
{
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_location for "
@ -7834,19 +7835,26 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
child_die->offset.sect_off, objfile->name);
continue;
}
parameter->dwarf_reg = dwarf_block_to_dwarf_reg (DW_BLOCK (attr)->data,
&DW_BLOCK (attr)->data[DW_BLOCK (attr)->size]);
if (parameter->dwarf_reg == -1
&& !dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (attr)->data,
&DW_BLOCK (attr)->data[DW_BLOCK (attr)->size],
&parameter->fb_offset))
else
{
complaint (&symfile_complaints,
_("Only single DW_OP_reg or DW_OP_fbreg is supported "
"for DW_FORM_block* DW_AT_location for "
"DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
child_die->offset.sect_off, objfile->name);
continue;
parameter->u.dwarf_reg = dwarf_block_to_dwarf_reg
(DW_BLOCK (loc)->data, &DW_BLOCK (loc)->data[DW_BLOCK (loc)->size]);
if (parameter->u.dwarf_reg != -1)
parameter->kind = CALL_SITE_PARAMETER_DWARF_REG;
else if (dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (loc)->data,
&DW_BLOCK (loc)->data[DW_BLOCK (loc)->size],
&parameter->u.fb_offset))
parameter->kind = CALL_SITE_PARAMETER_FB_OFFSET;
else
{
complaint (&symfile_complaints,
_("Only single DW_OP_reg or DW_OP_fbreg is supported "
"for DW_FORM_block* DW_AT_location is supported for "
"DW_TAG_GNU_call_site child DIE 0x%x "
"[in module %s]"),
child_die->offset.sect_off, objfile->name);
continue;
}
}
attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);

View File

@ -23,6 +23,7 @@
#define GDBTYPES_H 1
#include "hashtab.h"
#include "dwarf2expr.h"
/* Forward declarations for prototypes. */
struct field;
@ -915,6 +916,17 @@ struct func_type
struct call_site *tail_call_list;
};
/* struct call_site_parameter can be referenced in callees by several ways. */
enum call_site_parameter_kind
{
/* Use field call_site_parameter.u.dwarf_reg. */
CALL_SITE_PARAMETER_DWARF_REG,
/* Use field call_site_parameter.u.fb_offset. */
CALL_SITE_PARAMETER_FB_OFFSET
};
/* A place where a function gets called from, represented by
DW_TAG_GNU_call_site. It can be looked up from symtab->call_site_htab. */
@ -948,15 +960,19 @@ struct call_site
/* Describe DW_TAG_GNU_call_site's DW_TAG_formal_parameter. */
struct call_site_parameter
{
/* DW_TAG_formal_parameter's DW_AT_location's DW_OP_regX as DWARF
register number, for register passed parameters. If -1 then use
fb_offset. */
int dwarf_reg;
ENUM_BITFIELD (call_site_parameter_kind) kind : 2;
/* Offset from the callee's frame base, for stack passed parameters.
This equals offset from the caller's stack pointer. Valid only if
DWARF_REGNUM is -1. */
CORE_ADDR fb_offset;
union call_site_parameter_u
{
/* DW_TAG_formal_parameter's DW_AT_location's DW_OP_regX as DWARF
register number, for register passed parameters. */
int dwarf_reg;
/* Offset from the callee's frame base, for stack passed parameters.
This equals offset from the caller's stack pointer. */
CORE_ADDR fb_offset;
}
u;
/* DW_TAG_formal_parameter's DW_AT_GNU_call_site_value. It is never
NULL. */