http://sourceware.org/ml/gdb-patches/2012-06/msg00458.html Subject: [patch 1/2] Generalize call_site.parameter key ("code cleanup") Hi, previously parameter could be identified either via DW_OP_reg or via DW_OP_fbreg (both in DW_AT_location). As [patch 2/2] adds new identification via DW_AT_abstract_origin generalize this two state deciding into more general enum. Thanks, Jan gdb/ 2012-06-14 Jan Kratochvil Code cleanup: Generalize call_site.parameter key. * dwarf2expr.c (execute_stack_op) : 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. Index: gdb-7.4.50.20120120/gdb/dwarf2expr.c =================================================================== --- gdb-7.4.50.20120120.orig/gdb/dwarf2expr.c 2012-06-14 08:55:44.000000000 +0200 +++ gdb-7.4.50.20120120/gdb/dwarf2expr.c 2012-06-14 08:59:51.223967311 +0200 @@ -1349,33 +1349,35 @@ execute_stack_op (struct dwarf_expr_cont case DW_OP_GNU_entry_value: { ULONGEST len; - int dwarf_reg; CORE_ADDR deref_size; + union call_site_parameter_u kind_u; op_ptr = 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; } @@ -1532,7 +1534,8 @@ ctx_no_get_base_type (struct dwarf_expr_ 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__, Index: gdb-7.4.50.20120120/gdb/dwarf2expr.h =================================================================== --- gdb-7.4.50.20120120.orig/gdb/dwarf2expr.h 2012-06-14 08:55:44.000000000 +0200 +++ gdb-7.4.50.20120120/gdb/dwarf2expr.h 2012-06-14 08:55:59.937479777 +0200 @@ -24,6 +24,8 @@ #define DWARF2EXPR_H struct dwarf_expr_context; +enum call_site_parameter_kind; +union call_site_parameter_u; /* Virtual method table for struct dwarf_expr_context below. */ @@ -63,14 +65,12 @@ struct dwarf_expr_context_funcs struct type *(*get_base_type) (struct dwarf_expr_context *ctx, size_t 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); /* Not yet implemented. */ @@ -276,7 +276,8 @@ CORE_ADDR ctx_no_get_tls_address (void * void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset); struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t 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); int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end); Index: gdb-7.4.50.20120120/gdb/dwarf2loc.c =================================================================== --- gdb-7.4.50.20120120.orig/gdb/dwarf2loc.c 2012-06-14 08:55:44.000000000 +0200 +++ gdb-7.4.50.20120120/gdb/dwarf2loc.c 2012-06-14 08:55:59.938479774 +0200 @@ -905,16 +905,34 @@ call_site_find_chain (struct gdbarch *gd 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); @@ -979,12 +997,7 @@ dwarf_expr_reg_to_entry_parameter (struc 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) @@ -1041,17 +1054,17 @@ dwarf_entry_parameter_to_value (struct c 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; @@ -1068,7 +1081,7 @@ dwarf_expr_push_dwarf_reg_entry_value (s 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; @@ -1238,17 +1251,17 @@ static const struct lval_funcs entry_dat 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); @@ -1258,7 +1271,7 @@ value_of_dwarf_reg_entry (struct type *t 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 */, @@ -1310,15 +1323,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; - - 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 */); + union call_site_parameter_u 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); + 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, &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 @@ -2391,7 +2405,8 @@ needs_frame_dwarf_call (struct dwarf_exp 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; Index: gdb-7.4.50.20120120/gdb/dwarf2read.c =================================================================== --- gdb-7.4.50.20120120.orig/gdb/dwarf2read.c 2012-06-14 08:55:46.000000000 +0200 +++ gdb-7.4.50.20120120/gdb/dwarf2read.c 2012-06-14 08:58:31.874143194 +0200 @@ -6368,6 +6368,7 @@ read_call_site_scope (struct die_info *d { struct dwarf2_locexpr_baton *dlbaton; struct call_site_parameter *parameter; + struct attribute *loc; if (child_die->tag != DW_TAG_GNU_call_site_parameter) { @@ -6381,8 +6382,8 @@ read_call_site_scope (struct die_info *d /* 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 " @@ -6390,19 +6391,26 @@ read_call_site_scope (struct die_info *d child_die->offset, 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], - ¶meter->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, 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], + ¶meter->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, objfile->name); + continue; + } } attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu); Index: gdb-7.4.50.20120120/gdb/gdbtypes.h =================================================================== --- gdb-7.4.50.20120120.orig/gdb/gdbtypes.h 2012-06-14 08:55:45.000000000 +0200 +++ gdb-7.4.50.20120120/gdb/gdbtypes.h 2012-06-14 08:55:59.943479763 +0200 @@ -23,6 +23,7 @@ #define GDBTYPES_H 1 #include "hashtab.h" +#include "dwarf2expr.h" /* Forward declarations for prototypes. */ struct field; @@ -1010,6 +1011,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. */ @@ -1043,15 +1055,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; - - /* 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; + ENUM_BITFIELD (call_site_parameter_kind) kind : 2; + + 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. */