From patchwork Thu Oct 20 21:48:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 16708 Received: (qmail 19180 invoked by alias); 20 Oct 2016 21:48:43 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 19168 invoked by uid 89); 20 Oct 2016 21:48:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.2 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=8888, relocate, thread-local, threadlocal X-HELO: gproxy7-pub.mail.unifiedlayer.com Received: from gproxy7-pub.mail.unifiedlayer.com (HELO gproxy7-pub.mail.unifiedlayer.com) (70.40.196.235) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with SMTP; Thu, 20 Oct 2016 21:48:32 +0000 Received: (qmail 4558 invoked by uid 0); 20 Oct 2016 21:48:31 -0000 Received: from unknown (HELO cmgw2) (10.0.90.83) by gproxy7.mail.unifiedlayer.com with SMTP; 20 Oct 2016 21:48:31 -0000 Received: from box522.bluehost.com ([74.220.219.122]) by cmgw2 with id xxoS1t0072f2jeq01xoVi6; Thu, 20 Oct 2016 15:48:29 -0600 X-Authority-Analysis: v=2.1 cv=PIacp5aC c=1 sm=1 tr=0 a=GsOEXm/OWkKvwdLVJsfwcA==:117 a=GsOEXm/OWkKvwdLVJsfwcA==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=CH0kA5CcgfcA:10 a=zstS-IiYAAAA:8 a=mDV3o1hIAAAA:8 a=B67RFlONWphQwijflygA:9 a=kQVoA1isWHRXyOeg:21 a=eGwu1w8Zhwn_5D7Z:21 a=oJ3tNzY9LdNFhhDZ:21 a=4G6NA9xxw8l3yy4pmD5M:22 a=_FVE-zBwftR9WsbkzFJk:22 Received: from 174-16-143-211.hlrn.qwest.net ([174.16.143.211]:55884 helo=bapiya) by box522.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.86_1) (envelope-from ) id 1bxLCN-0005B4-A4; Thu, 20 Oct 2016 15:48:27 -0600 From: Tom Tromey To: Tom Tromey Cc: Pedro Alves , gdb-patches@sourceware.org Subject: Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods References: <1476393012-29987-1-git-send-email-tom@tromey.com> <1476393012-29987-17-git-send-email-tom@tromey.com> <94f5892b-e4d2-f903-36e2-513e37f3947b@redhat.com> <878ttmid6e.fsf@tromey.com> Date: Thu, 20 Oct 2016 15:48:24 -0600 In-Reply-To: <878ttmid6e.fsf@tromey.com> (Tom Tromey's message of "Mon, 17 Oct 2016 20:49:45 -0600") Message-ID: <87a8dyhetz.fsf@tromey.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux) MIME-Version: 1.0 X-BWhitelist: no X-Exim-ID: 1bxLCN-0005B4-A4 X-Source-Sender: 174-16-143-211.hlrn.qwest.net (bapiya) [174.16.143.211]:55884 X-Source-Auth: tom+tromey.com X-Email-Count: 8 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTIyLmJsdWVob3N0LmNvbQ== Pedro> Should we remove the parens throughout? Tom> I made this change. Here's the updated version of this patch. It also fixes some "CTX" comments. Tom diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 296c2fe..b2a9844 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,58 @@ 2016-10-20 Tom Tromey + * dwarf2loc.c (struct dwarf_expr_context_funcs): Don't declare. + (dwarf_expr_read_addr_from_reg, dwarf_expr_get_reg_value) + (dwarf_expr_read_mem, dwarf_expr_frame_base): Rename; turn into + methods. + (get_frame_pc_for_per_cu_dwarf_call): New function. + (dwarf_expr_frame_cfa, dwarf_expr_frame_pc) + (dwarf_expr_tls_address): Rename; turn into methods. + (per_cu_dwarf_call): Remove arguments. Use + get_frame_pc_for_per_cu_dwarf_call. + (dwarf_evaluate_loc_desc): New class. + (dwarf_expr_dwarf_call, dwarf_expr_context) + (dwarf_expr_push_dwarf_reg_entry_value) + (dwarf_expr_get_addr_index, dwarf_expr_get_obj_addr): Rename; turn + into methods. + (dwarf_expr_ctx_funcs): Remove. + (dwarf2_evaluate_loc_desc_full): Update. + (dwarf2_locexpr_baton_eval): Update. + (symbol_needs_eval_context): New class. + (symbol_needs_read_addr_from_reg, symbol_needs_get_reg_value) + (symbol_needs_read_mem, symbol_needs_frame_base) + (symbol_needs_frame_cfa, symbol_needs_tls_address) + (symbol_needs_dwarf_call, needs_dwarf_reg_entry_value): Rename; + turn into methods. + (needs_get_addr_index, needs_get_obj_addr): Remove; turn into + methods. + (symbol_needs_ctx_funcs): Remove. + (dwarf2_loc_desc_get_symbol_read_needs): Update. + * dwarf2expr.h (struct dwarf_expr_context_funcs): Remove; turn + contents into methods. + (struct dwarf_expr_context) : Remove. + : Declare new methods. + (ctx_no_get_frame_base, ctx_no_get_frame_cfa) + (ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call) + (ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value) + (ctx_no_get_addr_index): Don't declare. + * dwarf2expr.c (get_base_type): Use impl_get_base_type. + (execute_stack_op): Update. + (ctx_no_get_frame_base, ctx_no_get_frame_cfa) + (ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call) + (ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value) + (ctx_no_get_addr_index): Remove; now methods on + dwarf_expr_context. + * dwarf2-frame.c (read_addr_from_reg): Take a frame_info, not a + baton. + (class dwarf_expr_executor): New class. + (get_reg_value, read_mem): Rename, turn into methods. + (execute_stack_op): Use dwarf_expr_executor. + +2016-10-20 Tom Tromey + * dwarf2loc.c (per_cu_dwarf_call) (dwarf_expr_push_dwarf_reg_entry_value) (dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval) diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index c93c362..c9962e1 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -288,33 +288,14 @@ dwarf2_frame_state_free (void *p) /* Helper functions for execute_stack_op. */ static CORE_ADDR -read_addr_from_reg (void *baton, int reg) +read_addr_from_reg (struct frame_info *this_frame, int reg) { - struct frame_info *this_frame = (struct frame_info *) baton; struct gdbarch *gdbarch = get_frame_arch (this_frame); int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg); return address_from_register (regnum, this_frame); } -/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback. */ - -static struct value * -get_reg_value (void *baton, struct type *type, int reg) -{ - struct frame_info *this_frame = (struct frame_info *) baton; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg); - - return value_from_register (type, regnum, this_frame); -} - -static void -read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) -{ - read_memory (addr, buf, len); -} - /* Execute the required actions for both the DW_CFA_restore and DW_CFA_restore_extended instructions. */ static void @@ -347,21 +328,29 @@ register %s (#%d) at %s"), } } -/* Virtual method table for execute_stack_op below. */ - -static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs = +class dwarf_expr_executor : public dwarf_expr_context { - read_addr_from_reg, - get_reg_value, - read_mem, - ctx_no_get_frame_base, - ctx_no_get_frame_cfa, - ctx_no_get_frame_pc, - ctx_no_get_tls_address, - ctx_no_dwarf_call, - ctx_no_get_base_type, - ctx_no_push_dwarf_reg_entry_value, - ctx_no_get_addr_index + public: + + struct frame_info *this_frame; + + CORE_ADDR read_addr_from_reg (int reg) OVERRIDE + { + return ::read_addr_from_reg (this_frame, reg); + } + + struct value *get_reg_value (struct type *type, int reg) OVERRIDE + { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg); + + return value_from_register (type, regnum, this_frame); + } + + void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE + { + read_memory (addr, buf, len); + } }; static CORE_ADDR @@ -372,15 +361,14 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, CORE_ADDR result; struct cleanup *old_chain; - dwarf_expr_context ctx; + dwarf_expr_executor ctx; old_chain = make_cleanup_value_free_to_mark (value_mark ()); + ctx.this_frame = this_frame; ctx.gdbarch = get_frame_arch (this_frame); ctx.addr_size = addr_size; ctx.ref_addr_size = -1; ctx.offset = offset; - ctx.baton = this_frame; - ctx.funcs = &dwarf2_frame_ctx_funcs; ctx.push_address (initial, initial_in_stack_memory); ctx.eval (exp, len); @@ -388,8 +376,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, if (ctx.location == DWARF_VALUE_MEMORY) result = ctx.fetch_address (0); else if (ctx.location == DWARF_VALUE_REGISTER) - result = read_addr_from_reg (this_frame, - value_as_long (ctx.fetch (0))); + result = ctx.read_addr_from_reg (value_as_long (ctx.fetch (0))); else { /* This is actually invalid DWARF, but if we ever do run across diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 1aa6afc..a01d6d8 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -414,20 +414,11 @@ base_types_equal_p (struct type *t1, struct type *t2) struct type * dwarf_expr_context::get_base_type (cu_offset die, int size) { - struct type *result; - - if (this->funcs->get_base_type) - { - result = this->funcs->get_base_type (this, die); - if (result == NULL) - error (_("Could not find type for DW_OP_GNU_const_type")); - if (size != 0 && TYPE_LENGTH (result) != size) - error (_("DW_OP_GNU_const_type has different sizes for type and data")); - } - else - /* Anything will do. */ - result = builtin_type (this->gdbarch)->builtin_int; - + struct type *result = this->impl_get_base_type (die); + if (result == NULL) + error (_("Could not find type for DW_OP_GNU_const_type")); + if (size != 0 && TYPE_LENGTH (result) != size) + error (_("DW_OP_GNU_const_type has different sizes for type and data")); return result; } @@ -698,13 +689,13 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, case DW_OP_GNU_addr_index: op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); - result = (this->funcs->get_addr_index) (this->baton, uoffset); + result = this->get_addr_index (uoffset); result += this->offset; result_val = value_from_ulongest (address_type, result); break; case DW_OP_GNU_const_index: op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); - result = (this->funcs->get_addr_index) (this->baton, uoffset); + result = this->get_addr_index (uoffset); result_val = value_from_ulongest (address_type, result); break; @@ -888,8 +879,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, case DW_OP_breg31: { op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - result = (this->funcs->read_addr_from_reg) (this->baton, - op - DW_OP_breg0); + result = this->read_addr_from_reg (op - DW_OP_breg0); result += offset; result_val = value_from_ulongest (address_type, result); } @@ -898,7 +888,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, { op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - result = (this->funcs->read_addr_from_reg) (this->baton, reg); + result = this->read_addr_from_reg (reg); result += offset; result_val = value_from_ulongest (address_type, result); } @@ -918,14 +908,12 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, /* FIXME: cagney/2003-03-26: This code should be using get_frame_base_address(), and then implement a dwarf2 specific this_base method. */ - (this->funcs->get_frame_base) (this->baton, &datastart, &datalen); + this->get_frame_base (&datastart, &datalen); eval (datastart, datalen); if (this->location == DWARF_VALUE_MEMORY) result = fetch_address (0); else if (this->location == DWARF_VALUE_REGISTER) - result = (this->funcs->read_addr_from_reg) - (this->baton, - value_as_long (fetch (0))); + result = this->read_addr_from_reg (value_as_long (fetch (0))); else error (_("Not implemented: computing frame " "base using explicit value operator")); @@ -1011,7 +999,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, else type = address_type; - (this->funcs->read_mem) (this->baton, buf, addr, addr_size); + this->read_mem (buf, addr, addr_size); /* If the size of the object read from memory is different from the type length, we need to zero-extend it. */ @@ -1220,7 +1208,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, break; case DW_OP_call_frame_cfa: - result = (this->funcs->get_frame_cfa) (this->baton); + result = this->get_frame_cfa (); result_val = value_from_ulongest (address_type, result); in_stack_memory = 1; break; @@ -1237,7 +1225,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, returned. */ result = value_as_long (fetch (0)); pop (); - result = (this->funcs->get_tls_address) (this->baton, result); + result = this->get_tls_address (result); result_val = value_from_ulongest (address_type, result); break; @@ -1313,7 +1301,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order); op_ptr += 2; - this->funcs->dwarf_call (this, offset); + this->dwarf_call (offset); } goto no_push; @@ -1323,7 +1311,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order); op_ptr += 4; - this->funcs->dwarf_call (this, offset); + this->dwarf_call (offset); } goto no_push; @@ -1341,10 +1329,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, if (kind_u.dwarf_reg != -1) { op_ptr += len; - this->funcs->push_dwarf_reg_entry_value (this, - CALL_SITE_PARAMETER_DWARF_REG, - kind_u, - -1 /* deref_size */); + this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG, + kind_u, + -1 /* deref_size */); goto no_push; } @@ -1356,9 +1343,8 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, if (deref_size == -1) deref_size = this->addr_size; op_ptr += len; - this->funcs->push_dwarf_reg_entry_value (this, - CALL_SITE_PARAMETER_DWARF_REG, - kind_u, deref_size); + this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG, + kind_u, deref_size); goto no_push; } @@ -1374,10 +1360,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order); op_ptr += 4; - this->funcs->push_dwarf_reg_entry_value (this, - CALL_SITE_PARAMETER_PARAM_OFFSET, - kind_u, - -1 /* deref_size */); + this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_PARAM_OFFSET, + kind_u, + -1 /* deref_size */); } goto no_push; @@ -1409,7 +1394,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, type_die.cu_off = uoffset; type = get_base_type (type_die, 0); - result_val = this->funcs->get_reg_value (this->baton, type, reg); + result_val = this->get_reg_value (type, reg); } break; @@ -1448,7 +1433,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, case DW_OP_push_object_address: /* Return the address of the object we are currently observing. */ - result = (this->funcs->get_object_address) (this->baton); + result = this->get_object_address (); result_val = value_from_ulongest (address_type, result); break; @@ -1474,75 +1459,6 @@ abort_expression: gdb_assert (this->recursion_depth >= 0); } -/* Stub dwarf_expr_context_funcs.get_frame_base implementation. */ - -void -ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length) -{ - error (_("%s is invalid in this context"), "DW_OP_fbreg"); -} - -/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation. */ - -CORE_ADDR -ctx_no_get_frame_cfa (void *baton) -{ - error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa"); -} - -/* Stub dwarf_expr_context_funcs.get_frame_pc implementation. */ - -CORE_ADDR -ctx_no_get_frame_pc (void *baton) -{ - error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer"); -} - -/* Stub dwarf_expr_context_funcs.get_tls_address implementation. */ - -CORE_ADDR -ctx_no_get_tls_address (void *baton, CORE_ADDR offset) -{ - error (_("%s is invalid in this context"), "DW_OP_form_tls_address"); -} - -/* Stub dwarf_expr_context_funcs.dwarf_call implementation. */ - -void -ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset) -{ - error (_("%s is invalid in this context"), "DW_OP_call*"); -} - -/* Stub dwarf_expr_context_funcs.get_base_type implementation. */ - -struct type * -ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset die) -{ - error (_("Support for typed DWARF is not supported in this context")); -} - -/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value - implementation. */ - -void -ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, - enum call_site_parameter_kind kind, - union call_site_parameter_u kind_u, - int deref_size) -{ - internal_error (__FILE__, __LINE__, - _("Support for DW_OP_GNU_entry_value is unimplemented")); -} - -/* Stub dwarf_expr_context_funcs.get_addr_index implementation. */ - -CORE_ADDR -ctx_no_get_addr_index (void *baton, unsigned int index) -{ - error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index"); -} - /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_dwarf2expr; diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 4706bb3..63bdc6e 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -25,69 +25,6 @@ #include "leb128.h" #include "gdbtypes.h" -struct dwarf_expr_context; - -/* Virtual method table for struct dwarf_expr_context below. */ - -struct dwarf_expr_context_funcs -{ - /* Return the value of register number REGNUM (a DWARF register number), - read as an address. */ - CORE_ADDR (*read_addr_from_reg) (void *baton, int regnum); - - /* Return a value of type TYPE, stored in register number REGNUM - of the frame associated to the given BATON. - - REGNUM is a DWARF register number. */ - struct value *(*get_reg_value) (void *baton, struct type *type, int regnum); - - /* Read LENGTH bytes at ADDR into BUF. */ - void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length); - - /* Return the location expression for the frame base attribute, in - START and LENGTH. The result must be live until the current - expression evaluation is complete. */ - void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length); - - /* Return the CFA for the frame. */ - CORE_ADDR (*get_frame_cfa) (void *baton); - - /* Return the PC for the frame. */ - CORE_ADDR (*get_frame_pc) (void *baton); - - /* Return the thread-local storage address for - DW_OP_GNU_push_tls_address or DW_OP_form_tls_address. */ - CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); - - /* Execute DW_AT_location expression for the DWARF expression subroutine in - the DIE at DIE_OFFSET in the CU from CTX. Do not touch STACK while it - being passed to and returned from the called DWARF subroutine. */ - void (*dwarf_call) (struct dwarf_expr_context *ctx, cu_offset die_offset); - - /* Return the base type given by the indicated DIE. This can throw - an exception if the DIE is invalid or does not represent a base - type. If can also be NULL in the special case where the - callbacks are not performing evaluation, and thus it is - meaningful to substitute a stub type of the correct size. */ - 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 - 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, - 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. - This can throw an exception if the index is out of range. */ - CORE_ADDR (*get_addr_index) (void *baton, unsigned int index); - - /* Return the `object address' for DW_OP_push_object_address. */ - CORE_ADDR (*get_object_address) (void *baton); -}; - /* The location of a value. */ enum dwarf_value_location { @@ -159,13 +96,6 @@ struct dwarf_expr_context /* Offset used to relocate DW_OP_addr and DW_OP_GNU_addr_index arguments. */ CORE_ADDR offset; - /* An opaque argument provided by the caller, which will be passed - to all of the callback functions. */ - void *baton; - - /* Callback functions. */ - const struct dwarf_expr_context_funcs *funcs; - /* The current depth of dwarf expression recursion, via DW_OP_call*, DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum depth we'll tolerate before raising an error. */ @@ -210,6 +140,93 @@ struct dwarf_expr_context int num_pieces; struct dwarf_expr_piece *pieces; + /* Return the value of register number REGNUM (a DWARF register number), + read as an address. */ + virtual CORE_ADDR read_addr_from_reg (int regnum) = 0; + + /* Return a value of type TYPE, stored in register number REGNUM + of the frame associated to the given BATON. + + REGNUM is a DWARF register number. */ + virtual struct value *get_reg_value (struct type *type, int regnum) = 0; + + /* Read LENGTH bytes at ADDR into BUF. */ + virtual void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t length) = 0; + + /* Return the location expression for the frame base attribute, in + START and LENGTH. The result must be live until the current + expression evaluation is complete. */ + virtual void get_frame_base (const gdb_byte **start, size_t *length) + { + error (_("%s is invalid in this context"), "DW_OP_fbreg"); + } + + /* Return the CFA for the frame. */ + virtual CORE_ADDR get_frame_cfa () + { + error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa"); + } + + /* Return the PC for the frame. */ + virtual CORE_ADDR get_frame_pc () + { + error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer"); + } + + /* Return the thread-local storage address for + DW_OP_GNU_push_tls_address or DW_OP_form_tls_address. */ + virtual CORE_ADDR get_tls_address (CORE_ADDR offset) + { + error (_("%s is invalid in this context"), "DW_OP_form_tls_address"); + } + + /* Execute DW_AT_location expression for the DWARF expression + subroutine in the DIE at DIE_OFFSET in the CU. Do not touch + STACK while it being passed to and returned from the called DWARF + subroutine. */ + virtual void dwarf_call (cu_offset die_offset) + { + error (_("%s is invalid in this context"), "DW_OP_call*"); + } + + /* Return the base type given by the indicated DIE. This can throw + an exception if the DIE is invalid or does not represent a base + type. If can also be NULL in the special case where the + callbacks are not performing evaluation, and thus it is + meaningful to substitute a stub type of the correct size. */ + virtual struct type *impl_get_base_type (cu_offset die) + { + /* Anything will do. */ + return builtin_type (this->gdbarch)->builtin_int; + } + + /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's + 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. */ + virtual void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, + union call_site_parameter_u kind_u, + int deref_size) + { + internal_error (__FILE__, __LINE__, + _("Support for DW_OP_GNU_entry_value is unimplemented")); + } + + /* Return the address indexed by DW_OP_GNU_addr_index. + This can throw an exception if the index is out of range. */ + virtual CORE_ADDR get_addr_index (unsigned int index) + { + error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index"); + } + + /* Return the `object address' for DW_OP_push_object_address. */ + virtual CORE_ADDR get_object_address () + { + internal_error (__FILE__, __LINE__, + _("Support for DW_OP_push_object_address " + "is unimplemented")); + } + private: struct type *address_type () const; @@ -273,22 +290,6 @@ struct dwarf_expr_piece void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *, const char *); -/* Stub dwarf_expr_context_funcs implementations. */ - -void ctx_no_get_frame_base (void *baton, const gdb_byte **start, - size_t *length); -CORE_ADDR ctx_no_get_frame_cfa (void *baton); -CORE_ADDR ctx_no_get_frame_pc (void *baton); -CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset); -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, - 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); - int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end); int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 1f946df..6f25314 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -43,8 +43,6 @@ extern int dwarf_always_disassemble; -extern const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs; - static struct value *dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, const gdb_byte *data, @@ -52,6 +50,12 @@ static struct value *dwarf2_evaluate_loc_desc_full (struct type *type, struct dwarf2_per_cu_data *per_cu, LONGEST byte_offset); +static struct call_site_parameter *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); + /* Until these have formal names, we define these here. ref: http://gcc.gnu.org/wiki/DebugFission Each entry in .debug_loc.dwo begins with a byte that describes the entry, @@ -311,71 +315,6 @@ struct dwarf_expr_baton CORE_ADDR obj_address; }; -/* Helper functions for dwarf2_evaluate_loc_desc. */ - -/* Using the frame specified in BATON, return the value of register - REGNUM, treated as a pointer. */ -static CORE_ADDR -dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - struct gdbarch *gdbarch = get_frame_arch (debaton->frame); - int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); - - return address_from_register (regnum, debaton->frame); -} - -/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback. */ - -static struct value * -dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - struct gdbarch *gdbarch = get_frame_arch (debaton->frame); - int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); - - return value_from_register (type, regnum, debaton->frame); -} - -/* Read memory at ADDR (length LEN) into BUF. */ - -static void -dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) -{ - read_memory (addr, buf, len); -} - -/* Using the frame specified in BATON, find the location expression - describing the frame base. Return a pointer to it in START and - its length in LENGTH. */ -static void -dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length) -{ - /* FIXME: cagney/2003-03-26: This code should be using - get_frame_base_address(), and then implement a dwarf2 specific - this_base method. */ - struct symbol *framefunc; - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - const struct block *bl = get_frame_block (debaton->frame, NULL); - - if (bl == NULL) - error (_("frame address is not available.")); - - /* Use block_linkage_function, which returns a real (not inlined) - function, instead of get_frame_function, which may return an - inlined function. */ - framefunc = block_linkage_function (bl); - - /* If we found a frame-relative symbol then it was certainly within - some function associated with a frame. If we can't find the frame, - something has gone wrong. */ - gdb_assert (framefunc != NULL); - - func_get_frame_base_dwarf_block (framefunc, - get_frame_address_in_block (debaton->frame), - start, length); -} - /* Implement find_frame_base_location method for LOC_BLOCK functions using DWARF expression for its DW_AT_frame_base. */ @@ -511,52 +450,23 @@ func_get_frame_base_dwarf_block (struct symbol *framefunc, CORE_ADDR pc, SYMBOL_NATURAL_NAME (framefunc)); } -/* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for - the frame in BATON. */ - -static CORE_ADDR -dwarf_expr_frame_cfa (void *baton) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - - return dwarf2_frame_cfa (debaton->frame); -} - -/* Helper function for dwarf2_evaluate_loc_desc. Computes the PC for - the frame in BATON. */ - -static CORE_ADDR -dwarf_expr_frame_pc (void *baton) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - - return get_frame_address_in_block (debaton->frame); -} - -/* Using the objfile specified in BATON, find the address for the - current thread's thread-local storage with offset OFFSET. */ static CORE_ADDR -dwarf_expr_tls_address (void *baton, CORE_ADDR offset) +get_frame_pc_for_per_cu_dwarf_call (void *baton) { - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu); + dwarf_expr_context *ctx = (dwarf_expr_context *) baton; - return target_translate_tls_address (objfile, offset); + return ctx->get_frame_pc (); } -/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in - current CU (as is PER_CU). State of the CTX is not affected by the - call and return. */ - static void per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset, - struct dwarf2_per_cu_data *per_cu, - CORE_ADDR (*get_frame_pc) (void *baton), - void *baton) + struct dwarf2_per_cu_data *per_cu) { struct dwarf2_locexpr_baton block; - block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu, get_frame_pc, baton); + block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu, + get_frame_pc_for_per_cu_dwarf_call, + ctx); /* DW_OP_call_ref is currently not supported. */ gdb_assert (block.per_cu == per_cu); @@ -564,27 +474,173 @@ per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset, ctx->eval (block.data, block.size); } -/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc. */ - -static void -dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset) +class dwarf_evaluate_loc_desc : public dwarf_expr_context { - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton; + public: - per_cu_dwarf_call (ctx, die_offset, debaton->per_cu, - ctx->funcs->get_frame_pc, ctx->baton); -} + struct frame_info *frame; + struct dwarf2_per_cu_data *per_cu; + CORE_ADDR obj_address; -/* Callback function for dwarf2_evaluate_loc_desc. */ + /* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for + the frame in BATON. */ -static struct type * -dwarf_expr_get_base_type (struct dwarf_expr_context *ctx, - cu_offset die_offset) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton; + CORE_ADDR get_frame_cfa () OVERRIDE + { + return dwarf2_frame_cfa (frame); + } - return dwarf2_get_die_type (die_offset, debaton->per_cu); -} + /* Helper function for dwarf2_evaluate_loc_desc. Computes the PC for + the frame in BATON. */ + + CORE_ADDR get_frame_pc () OVERRIDE + { + return get_frame_address_in_block (frame); + } + + /* Using the objfile specified in BATON, find the address for the + current thread's thread-local storage with offset OFFSET. */ + CORE_ADDR get_tls_address (CORE_ADDR offset) OVERRIDE + { + struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); + + return target_translate_tls_address (objfile, offset); + } + + /* Helper interface of per_cu_dwarf_call for + dwarf2_evaluate_loc_desc. */ + + void dwarf_call (cu_offset die_offset) OVERRIDE + { + per_cu_dwarf_call (this, die_offset, per_cu); + } + + /* Callback function for dwarf2_evaluate_loc_desc. */ + struct type *impl_get_base_type (cu_offset die_offset) OVERRIDE + { + return dwarf2_get_die_type (die_offset, per_cu); + } + + /* Callback function for dwarf2_evaluate_loc_desc. + Fetch the address indexed by DW_OP_GNU_addr_index. */ + + CORE_ADDR get_addr_index (unsigned int index) OVERRIDE + { + return dwarf2_read_addr_index (per_cu, index); + } + + /* Callback function for get_object_address. Return the address of the VLA + object. */ + + CORE_ADDR get_object_address () OVERRIDE + { + if (obj_address == 0) + error (_("Location address is not set.")); + return obj_address; + } + + /* Execute DWARF block of call_site_parameter which matches KIND and + KIND_U. Choose DEREF_SIZE value of that parameter. Search + caller of this objects's frame. + + The 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. */ + + void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, + union call_site_parameter_u kind_u, + int deref_size) OVERRIDE + { + struct frame_info *caller_frame; + struct dwarf2_per_cu_data *caller_per_cu; + struct dwarf_expr_baton baton_local; + struct call_site_parameter *parameter; + const gdb_byte *data_src; + size_t size; + + caller_frame = get_prev_frame (frame); + + 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; + + /* DEREF_SIZE size is not verified here. */ + if (data_src == NULL) + throw_error (NO_ENTRY_VALUE_ERROR, + _("Cannot resolve DW_AT_GNU_call_site_data_value")); + + baton_local.frame = caller_frame; + baton_local.per_cu = caller_per_cu; + baton_local.obj_address = 0; + + scoped_restore save_arch = make_scoped_restore (&this->gdbarch); + this->gdbarch + = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu)); + scoped_restore save_addr_size = make_scoped_restore (&this->addr_size); + this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu); + scoped_restore save_offset = make_scoped_restore (&this->offset); + this->offset = dwarf2_per_cu_text_offset (baton_local.per_cu); + + this->eval (data_src, size); + } + + /* Using the frame specified in BATON, find the location expression + describing the frame base. Return a pointer to it in START and + its length in LENGTH. */ + void get_frame_base (const gdb_byte **start, size_t * length) OVERRIDE + { + /* FIXME: cagney/2003-03-26: This code should be using + get_frame_base_address(), and then implement a dwarf2 specific + this_base method. */ + struct symbol *framefunc; + const struct block *bl = get_frame_block (frame, NULL); + + if (bl == NULL) + error (_("frame address is not available.")); + + /* Use block_linkage_function, which returns a real (not inlined) + function, instead of get_frame_function, which may return an + inlined function. */ + framefunc = block_linkage_function (bl); + + /* If we found a frame-relative symbol then it was certainly within + some function associated with a frame. If we can't find the frame, + something has gone wrong. */ + gdb_assert (framefunc != NULL); + + func_get_frame_base_dwarf_block (framefunc, + get_frame_address_in_block (frame), + start, length); + } + + /* Read memory at ADDR (length LEN) into BUF. */ + + void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE + { + read_memory (addr, buf, len); + } + + /* Using the frame specified in BATON, return the value of register + REGNUM, treated as a pointer. */ + CORE_ADDR read_addr_from_reg (int dwarf_regnum) OVERRIDE + { + struct gdbarch *gdbarch = get_frame_arch (frame); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); + + return address_from_register (regnum, frame); + } + + /* Implement "get_reg_value" callback. */ + + struct value *get_reg_value (struct type *type, int dwarf_regnum) OVERRIDE + { + struct gdbarch *gdbarch = get_frame_arch (frame); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); + + return value_from_register (type, regnum, frame); + } +}; /* See dwarf2loc.h. */ @@ -1250,91 +1306,6 @@ dwarf_entry_parameter_to_value (struct call_site_parameter *parameter, return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu); } -/* 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, - enum call_site_parameter_kind kind, - union call_site_parameter_u kind_u, - int deref_size) -{ - struct dwarf_expr_baton *debaton; - struct frame_info *frame, *caller_frame; - struct dwarf2_per_cu_data *caller_per_cu; - struct dwarf_expr_baton baton_local; - struct dwarf_expr_context saved_ctx; - struct call_site_parameter *parameter; - const gdb_byte *data_src; - size_t size; - - gdb_assert (ctx->funcs == &dwarf_expr_ctx_funcs); - debaton = (struct dwarf_expr_baton *) ctx->baton; - frame = debaton->frame; - caller_frame = get_prev_frame (frame); - - 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; - - /* DEREF_SIZE size is not verified here. */ - if (data_src == NULL) - throw_error (NO_ENTRY_VALUE_ERROR, - _("Cannot resolve DW_AT_GNU_call_site_data_value")); - - baton_local.frame = caller_frame; - baton_local.per_cu = caller_per_cu; - baton_local.obj_address = 0; - - saved_ctx.gdbarch = ctx->gdbarch; - saved_ctx.addr_size = ctx->addr_size; - saved_ctx.offset = ctx->offset; - saved_ctx.baton = ctx->baton; - ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu)); - ctx->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu); - ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu); - ctx->baton = &baton_local; - - ctx->eval (data_src, size); - - ctx->gdbarch = saved_ctx.gdbarch; - ctx->addr_size = saved_ctx.addr_size; - ctx->offset = saved_ctx.offset; - ctx->baton = saved_ctx.baton; -} - -/* Callback function for dwarf2_evaluate_loc_desc. - Fetch the address indexed by DW_OP_GNU_addr_index. */ - -static CORE_ADDR -dwarf_expr_get_addr_index (void *baton, unsigned int index) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - - return dwarf2_read_addr_index (debaton->per_cu, index); -} - -/* Callback function for get_object_address. Return the address of the VLA - object. */ - -static CORE_ADDR -dwarf_expr_get_obj_addr (void *baton) -{ - struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; - - gdb_assert (debaton != NULL); - - if (debaton->obj_address == 0) - error (_("Location address is not set.")); - - return debaton->obj_address; -} - /* VALUE must be of type lval_computed with entry_data_value_funcs. Perform the indirect method on it, that is use its stored target value, the sole purpose of entry_data_value_funcs.. */ @@ -2263,24 +2234,6 @@ static const struct lval_funcs pieced_value_funcs = { free_pieced_value_closure }; -/* Virtual method table for dwarf2_evaluate_loc_desc_full below. */ - -const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs = -{ - dwarf_expr_read_addr_from_reg, - dwarf_expr_get_reg_value, - dwarf_expr_read_mem, - dwarf_expr_frame_base, - dwarf_expr_frame_cfa, - dwarf_expr_frame_pc, - dwarf_expr_tls_address, - dwarf_expr_dwarf_call, - dwarf_expr_get_base_type, - dwarf_expr_push_dwarf_reg_entry_value, - dwarf_expr_get_addr_index, - dwarf_expr_get_obj_addr -}; - /* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable of TYPE in the context of FRAME. BYTE_OFFSET is applied after the contents are @@ -2293,7 +2246,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, LONGEST byte_offset) { struct value *retval; - struct dwarf_expr_baton baton; struct cleanup *value_chain; struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); @@ -2303,19 +2255,17 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, if (size == 0) return allocate_optimized_out_value (type); - baton.frame = frame; - baton.per_cu = per_cu; - baton.obj_address = 0; + dwarf_evaluate_loc_desc ctx; + ctx.frame = frame; + ctx.per_cu = per_cu; + ctx.obj_address = 0; - dwarf_expr_context ctx; value_chain = make_cleanup_value_free_to_mark (value_mark ()); ctx.gdbarch = get_objfile_arch (objfile); ctx.addr_size = dwarf2_per_cu_addr_size (per_cu); ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); ctx.offset = dwarf2_per_cu_text_offset (per_cu); - ctx.baton = &baton; - ctx.funcs = &dwarf_expr_ctx_funcs; TRY { @@ -2537,18 +2487,17 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, CORE_ADDR addr, CORE_ADDR *valp) { - struct dwarf_expr_baton baton; struct objfile *objfile; struct cleanup *cleanup; if (dlbaton == NULL || dlbaton->size == 0) return 0; - dwarf_expr_context ctx; + dwarf_evaluate_loc_desc ctx; - baton.frame = frame; - baton.per_cu = dlbaton->per_cu; - baton.obj_address = addr; + ctx.frame = frame; + ctx.per_cu = dlbaton->per_cu; + ctx.obj_address = addr; objfile = dwarf2_per_cu_objfile (dlbaton->per_cu); @@ -2556,8 +2505,6 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, ctx.addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu); ctx.offset = dwarf2_per_cu_text_offset (dlbaton->per_cu); - ctx.funcs = &dwarf_expr_ctx_funcs; - ctx.baton = &baton; ctx.eval (dlbaton->data, dlbaton->size); @@ -2568,7 +2515,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, case DWARF_VALUE_STACK: *valp = ctx.fetch_address (0); if (ctx.location == DWARF_VALUE_REGISTER) - *valp = dwarf_expr_read_addr_from_reg (&baton, *valp); + *valp = ctx.read_addr_from_reg (*valp); return 1; case DWARF_VALUE_LITERAL: *valp = extract_signed_integer (ctx.data, ctx.len, @@ -2713,140 +2660,97 @@ dwarf2_compile_property_to_c (struct ui_file *stream, /* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs. */ -struct symbol_needs_baton +class symbol_needs_eval_context : public dwarf_expr_context { + public: + enum symbol_needs_kind needs; struct dwarf2_per_cu_data *per_cu; -}; - -/* Reads from registers do require a frame. */ -static CORE_ADDR -symbol_needs_read_addr_from_reg (void *baton, int regnum) -{ - struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton; - - nf_baton->needs = SYMBOL_NEEDS_FRAME; - return 1; -} - -/* struct dwarf_expr_context_funcs' "get_reg_value" callback: - Reads from registers do require a frame. */ - -static struct value * -symbol_needs_get_reg_value (void *baton, struct type *type, int regnum) -{ - struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton; - - nf_baton->needs = SYMBOL_NEEDS_FRAME; - return value_zero (type, not_lval); -} - -/* Reads from memory do not require a frame. */ -static void -symbol_needs_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) -{ - memset (buf, 0, len); -} - -/* Frame-relative accesses do require a frame. */ -static void -symbol_needs_frame_base (void *baton, const gdb_byte **start, size_t * length) -{ - static gdb_byte lit0 = DW_OP_lit0; - struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton; - - *start = &lit0; - *length = 1; - nf_baton->needs = SYMBOL_NEEDS_FRAME; -} - -/* CFA accesses require a frame. */ - -static CORE_ADDR -symbol_needs_frame_cfa (void *baton) -{ - struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton; - - nf_baton->needs = SYMBOL_NEEDS_FRAME; - return 1; -} - -/* Thread-local accesses require registers, but not a frame. */ -static CORE_ADDR -symbol_needs_tls_address (void *baton, CORE_ADDR offset) -{ - struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton; - - if (nf_baton->needs <= SYMBOL_NEEDS_REGISTERS) - nf_baton->needs = SYMBOL_NEEDS_REGISTERS; - return 1; -} - -/* Helper interface of per_cu_dwarf_call for - dwarf2_loc_desc_get_symbol_read_needs. */ - -static void -symbol_needs_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset) -{ - struct symbol_needs_baton *nf_baton = - (struct symbol_needs_baton *) ctx->baton; - - per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu, - ctx->funcs->get_frame_pc, ctx->baton); -} - -/* DW_OP_GNU_entry_value accesses require a caller, therefore a frame. */ - -static void -needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, - enum call_site_parameter_kind kind, - union call_site_parameter_u kind_u, int deref_size) -{ - struct symbol_needs_baton *nf_baton = - (struct symbol_needs_baton *) ctx->baton; - - nf_baton->needs = SYMBOL_NEEDS_FRAME; - - /* The expression may require some stub values on DWARF stack. */ - ctx->push_address (0, 0); -} - -/* DW_OP_GNU_addr_index doesn't require a frame. */ + /* Reads from registers do require a frame. */ + CORE_ADDR read_addr_from_reg (int regnum) OVERRIDE + { + needs = SYMBOL_NEEDS_FRAME; + return 1; + } + + /* "get_reg_value" callback: Reads from registers do require a + frame. */ + + struct value *get_reg_value (struct type *type, int regnum) OVERRIDE + { + needs = SYMBOL_NEEDS_FRAME; + return value_zero (type, not_lval); + } + + /* Reads from memory do not require a frame. */ + void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE + { + memset (buf, 0, len); + } + + /* Frame-relative accesses do require a frame. */ + void get_frame_base (const gdb_byte **start, size_t *length) OVERRIDE + { + static gdb_byte lit0 = DW_OP_lit0; + + *start = &lit0; + *length = 1; + + needs = SYMBOL_NEEDS_FRAME; + } + + /* CFA accesses require a frame. */ + CORE_ADDR get_frame_cfa () OVERRIDE + { + needs = SYMBOL_NEEDS_FRAME; + return 1; + } + + /* Thread-local accesses require registers, but not a frame. */ + CORE_ADDR get_tls_address (CORE_ADDR offset) OVERRIDE + { + if (needs <= SYMBOL_NEEDS_REGISTERS) + needs = SYMBOL_NEEDS_REGISTERS; + return 1; + } + + /* Helper interface of per_cu_dwarf_call for + dwarf2_loc_desc_get_symbol_read_needs. */ + + void dwarf_call (cu_offset die_offset) OVERRIDE + { + per_cu_dwarf_call (this, die_offset, per_cu); + } + + /* DW_OP_GNU_entry_value accesses require a caller, therefore a + frame. */ + + void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, + union call_site_parameter_u kind_u, + int deref_size) OVERRIDE + { + needs = SYMBOL_NEEDS_FRAME; -static CORE_ADDR -needs_get_addr_index (void *baton, unsigned int index) -{ - /* Nothing to do. */ - return 1; -} + /* The expression may require some stub values on DWARF stack. */ + push_address (0, 0); + } -/* DW_OP_push_object_address has a frame already passed through. */ + /* DW_OP_GNU_addr_index doesn't require a frame. */ -static CORE_ADDR -needs_get_obj_addr (void *baton) -{ - /* Nothing to do. */ - return 1; -} + CORE_ADDR get_addr_index (unsigned int index) OVERRIDE + { + /* Nothing to do. */ + return 1; + } -/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs - below. */ + /* DW_OP_push_object_address has a frame already passed through. */ -static const struct dwarf_expr_context_funcs symbol_needs_ctx_funcs = -{ - symbol_needs_read_addr_from_reg, - symbol_needs_get_reg_value, - symbol_needs_read_mem, - symbol_needs_frame_base, - symbol_needs_frame_cfa, - symbol_needs_frame_cfa, /* get_frame_pc */ - symbol_needs_tls_address, - symbol_needs_dwarf_call, - NULL, /* get_base_type */ - needs_dwarf_reg_entry_value, - needs_get_addr_index, - needs_get_obj_addr + CORE_ADDR get_object_address () OVERRIDE + { + /* Nothing to do. */ + return 1; + } }; /* Compute the correct symbol_needs_kind value for the location @@ -2856,23 +2760,21 @@ static enum symbol_needs_kind dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size, struct dwarf2_per_cu_data *per_cu) { - struct symbol_needs_baton baton; int in_reg; struct cleanup *old_chain; struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); - baton.needs = SYMBOL_NEEDS_NONE; - baton.per_cu = per_cu; + symbol_needs_eval_context ctx; + + ctx.needs = SYMBOL_NEEDS_NONE; + ctx.per_cu = per_cu; - dwarf_expr_context ctx; old_chain = make_cleanup_value_free_to_mark (value_mark ()); ctx.gdbarch = get_objfile_arch (objfile); ctx.addr_size = dwarf2_per_cu_addr_size (per_cu); ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); ctx.offset = dwarf2_per_cu_text_offset (per_cu); - ctx.baton = &baton; - ctx.funcs = &symbol_needs_ctx_funcs; ctx.eval (data, size); @@ -2892,8 +2794,8 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size, do_cleanups (old_chain); if (in_reg) - baton.needs = SYMBOL_NEEDS_FRAME; - return baton.needs; + ctx.needs = SYMBOL_NEEDS_FRAME; + return ctx.needs; } /* A helper function that throws an unimplemented error mentioning a