From a03eab7536648e8dfcbde6d3e71cd8de41d86f3d Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Tue, 12 May 2020 12:05:24 -0400 Subject: Add dwarf2_per_objfile to dwarf_expr_context and dwarf2_frame_cache Evaluating DWARF expressions (such as location expressions) requires knowing about the current objfile. For example, it may call functions like dwarf2_fetch_die_loc_sect_off, which currently obtain the dwarf2_per_objfile object it needs from the dwarf2_per_cu_data object. However, since we are going to remove this dwarf2_per_cu_data::dwarf2_per_objfile link, these functions will need to obtain the current dwarf2_per_objfile by parmeter. If we go up the stack, we see that the DWARF expression contexts (dwarf_expr_context and the classes that derive from it) need to store the dwarf2_per_objfile, to be able to pass it to those functions that will need it. This patch adds a constructor to all these dwarf_expr_context variants, accepting a dwarf2_per_objfile parameter. This dwarf2_per_objfile generally comes from a symbol baton created earlier. For frame-related expressions, the dwarf2_per_objfile object must be passed through the dwarf2_frame_cache object. This lead to the dwarf2_frame_find_fde function returning (by parameter) a dwarf2_per_objfile object. I then realized that this made the existing "out_offset" parameter redundant. This offset is `objfile->text_section_offset ()`, so it can be recomputed from the dwarf2_per_objfile object at any time. I therefore opted to remove this output parameter, as well as the offset field of dwarf2_frame_cache. *Note*, there's one spot I'm particularly unsure about. In dwarf_evaluate_loc_desc::push_dwarf_reg_entry_value, we would save and overwrite the offset value in the context, along with a bunch of other state. This is because we might be about to evaluate something in a different CU that the current one. If the two CUs are in the same objfile, then the text_offset is the same, as it's a property of the objfile. However, if the two CUs are possibly in different objfiles, then it means the text_offsets are different. It would also mean we would need to save and restore the dwarf2_per_objfile in the context. Is that even possible? gdb/ChangeLog: * dwarf2/expr.h (struct dwarf_expr_context) : Add dwarf2_per_objfile parameter. : Remove. : New member. * dwarf2/expr.c (dwarf_expr_context::dwarf_expr_context): Add dwarf2_per_objfile parameter. Don't set offset, set per_objfile. (dwarf_expr_context::execute_stack_op): Use offset from objfile. * dwarf2/frame.c (dwarf2_frame_find_fde): Return (by parameter) a dwarf2_per_objfile object instead of an offset. (class dwarf_expr_executor) : Add constructor. (execute_stack_op): Add dwarf2_per_objfile parameter, pass it to dwarf2_expr_executor constructor. Don't set offset. (dwarf2_fetch_cfa_info): Update. (struct dwarf2_frame_cache) : Remove. : New field. (dwarf2_frame_cache): Update. (dwarf2_frame_prev_register): Update. * dwarf2/loc.c (class dwarf_evaluate_loc_desc) : Add constructor. (dwarf2_evaluate_loc_desc_full): Update. (dwarf2_locexpr_baton_eval): Update. (class symbol_needs_eval_context) : Add constructor. (dwarf2_loc_desc_get_symbol_read_needs): Update. --- gdb/dwarf2/expr.c | 11 +++++---- gdb/dwarf2/expr.h | 11 +++++---- gdb/dwarf2/frame.c | 67 +++++++++++++++++++++++++++++++----------------------- gdb/dwarf2/loc.c | 33 +++++++++++++++------------ 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 243f493..802b343 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -27,6 +27,7 @@ #include "dwarf2.h" #include "dwarf2/expr.h" #include "dwarf2/loc.h" +#include "dwarf2/read.h" #include "gdbsupport/underlying.h" #include "gdbarch.h" @@ -88,17 +89,17 @@ dwarf_expr_context::address_type () const /* Create a new context for the expression evaluator. */ -dwarf_expr_context::dwarf_expr_context () +dwarf_expr_context::dwarf_expr_context (dwarf2_per_objfile *per_objfile) : gdbarch (NULL), addr_size (0), ref_addr_size (0), - offset (0), recursion_depth (0), max_recursion_depth (0x100), location (DWARF_VALUE_MEMORY), len (0), data (NULL), - initialized (0) + initialized (0), + per_objfile (per_objfile) { } @@ -631,7 +632,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, index, not an address. We don't support things like branching between the address and the TLS op. */ if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address) - result += this->offset; + result += this->per_objfile->objfile->text_section_offset (); result_val = value_from_ulongest (address_type, result); break; @@ -639,7 +640,7 @@ 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->get_addr_index (uoffset); - result += this->offset; + result += this->per_objfile->objfile->text_section_offset (); result_val = value_from_ulongest (address_type, result); break; case DW_OP_GNU_const_index: diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h index 2f3d2ce..fd9c2bb 100644 --- a/gdb/dwarf2/expr.h +++ b/gdb/dwarf2/expr.h @@ -25,6 +25,8 @@ #include "leb128.h" #include "gdbtypes.h" +struct dwarf2_per_objfile; + /* The location of a value. */ enum dwarf_value_location { @@ -117,7 +119,7 @@ struct dwarf_stack_value its current state and its callbacks. */ struct dwarf_expr_context { - dwarf_expr_context (); + dwarf_expr_context (dwarf2_per_objfile *per_objfile); virtual ~dwarf_expr_context () = default; void push_address (CORE_ADDR value, bool in_stack_memory); @@ -139,10 +141,6 @@ struct dwarf_expr_context context and operations depending on DW_FORM_ref_addr are not allowed. */ int ref_addr_size; - /* Offset used to relocate DW_OP_addr, DW_OP_addrx, and - DW_OP_GNU_addr_index arguments. */ - CORE_ADDR offset; - /* 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. */ @@ -185,6 +183,9 @@ struct dwarf_expr_context two cases need to be handled separately.) */ std::vector pieces; + /* We evaluate the expression in the context of this objfile. */ + dwarf2_per_objfile *per_objfile; + /* 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; diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index f7276d4..5fe16a6 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -166,8 +166,8 @@ struct comp_unit auto_obstack obstack; }; -static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc, - CORE_ADDR *out_offset); +static struct dwarf2_fde *dwarf2_frame_find_fde + (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile); static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p); @@ -237,7 +237,11 @@ register %s (#%d) at %s"), class dwarf_expr_executor : public dwarf_expr_context { - public: +public: + + dwarf_expr_executor (dwarf2_per_objfile *per_objfile) + : dwarf_expr_context (per_objfile) + {} struct frame_info *this_frame; @@ -311,19 +315,18 @@ class dwarf_expr_executor : public dwarf_expr_context static CORE_ADDR execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, - CORE_ADDR offset, struct frame_info *this_frame, - CORE_ADDR initial, int initial_in_stack_memory) + struct frame_info *this_frame, CORE_ADDR initial, + int initial_in_stack_memory, dwarf2_per_objfile *per_objfile) { CORE_ADDR result; - dwarf_expr_executor ctx; + dwarf_expr_executor ctx (per_objfile); scoped_value_mark free_values; 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.push_address (initial, initial_in_stack_memory); ctx.eval (exp, len); @@ -883,14 +886,16 @@ dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc, const gdb_byte **cfa_end_out) { struct dwarf2_fde *fde; - CORE_ADDR text_offset; + dwarf2_per_objfile *per_objfile; CORE_ADDR pc1 = pc; /* Find the correct FDE. */ - fde = dwarf2_frame_find_fde (&pc1, &text_offset); + fde = dwarf2_frame_find_fde (&pc1, &per_objfile); if (fde == NULL) error (_("Could not compute CFA; needed to translate this expression")); + gdb_assert (per_objfile != nullptr); + dwarf2_frame_state fs (pc1, fde->cie); /* Check for "quirks" - known bugs in producers. */ @@ -898,14 +903,15 @@ dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc, /* First decode all the insns in the CIE. */ execute_cfa_program (fde, fde->cie->initial_instructions, - fde->cie->end, gdbarch, pc, &fs, text_offset); + fde->cie->end, gdbarch, pc, &fs, + per_objfile->objfile->text_section_offset ()); /* Save the initialized register set. */ fs.initial = fs.regs; /* Then decode the insns in the FDE up to our target PC. */ execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, pc, &fs, - text_offset); + per_objfile->objfile->text_section_offset ()); /* Calculate the CFA. */ switch (fs.regs.cfa_how) @@ -923,7 +929,7 @@ dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc, } case CFA_EXP: - *text_offset_out = text_offset; + *text_offset_out = per_objfile->objfile->text_section_offset (); *cfa_start_out = fs.regs.cfa_exp; *cfa_end_out = fs.regs.cfa_exp + fs.regs.cfa_exp_len; return 0; @@ -956,8 +962,8 @@ struct dwarf2_frame_cache /* Target address size in bytes. */ int addr_size; - /* The .text offset. */ - CORE_ADDR text_offset; + /* The dwarf2_per_objfile from which this frame description came. */ + dwarf2_per_objfile *per_objfile; /* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME sequence. If NULL then it is a normal case with no TAILCALL_FRAME @@ -1003,8 +1009,9 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) CORE_ADDR pc1 = get_frame_address_in_block (this_frame); /* Find the correct FDE. */ - fde = dwarf2_frame_find_fde (&pc1, &cache->text_offset); + fde = dwarf2_frame_find_fde (&pc1, &cache->per_objfile); gdb_assert (fde != NULL); + gdb_assert (cache->per_objfile != nullptr); /* Allocate and initialize the frame state. */ struct dwarf2_frame_state fs (pc1, fde->cie); @@ -1018,7 +1025,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) execute_cfa_program (fde, fde->cie->initial_instructions, fde->cie->end, gdbarch, get_frame_address_in_block (this_frame), &fs, - cache->text_offset); + cache->per_objfile->objfile->text_section_offset ()); /* Save the initialized register set. */ fs.initial = fs.regs; @@ -1034,8 +1041,9 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) && entry_pc < fde->initial_location + fde->address_range) { /* Decode the insns in the FDE up to the entry PC. */ - instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, - entry_pc, &fs, cache->text_offset); + instr = execute_cfa_program + (fde, fde->instructions, fde->end, gdbarch, entry_pc, &fs, + cache->per_objfile->objfile->text_section_offset ()); if (fs.regs.cfa_how == CFA_REG_OFFSET && (dwarf_reg_to_regnum (gdbarch, fs.regs.cfa_reg) @@ -1051,7 +1059,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) /* Then decode the insns in the FDE up to our target PC. */ execute_cfa_program (fde, instr, fde->end, gdbarch, get_frame_address_in_block (this_frame), &fs, - cache->text_offset); + cache->per_objfile->objfile->text_section_offset ()); try { @@ -1069,8 +1077,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) case CFA_EXP: cache->cfa = execute_stack_op (fs.regs.cfa_exp, fs.regs.cfa_exp_len, - cache->addr_size, cache->text_offset, - this_frame, 0, 0); + cache->addr_size, this_frame, 0, 0, + cache->per_objfile); break; default: @@ -1270,8 +1278,9 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp.start, cache->reg[regnum].loc.exp.len, - cache->addr_size, cache->text_offset, - this_frame, cache->cfa, 1); + cache->addr_size, + this_frame, cache->cfa, 1, + cache->per_objfile); return frame_unwind_got_memory (this_frame, regnum, addr); case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: @@ -1281,8 +1290,9 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_VAL_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp.start, cache->reg[regnum].loc.exp.len, - cache->addr_size, cache->text_offset, - this_frame, cache->cfa, 1); + cache->addr_size, + this_frame, cache->cfa, 1, + cache->per_objfile); return frame_unwind_got_constant (this_frame, regnum, addr); case DWARF2_FRAME_REG_UNSPECIFIED: @@ -1650,7 +1660,7 @@ set_comp_unit (struct objfile *objfile, struct comp_unit *unit) initial location associated with it into *PC. */ static struct dwarf2_fde * -dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset) +dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) { for (objfile *objfile : current_program_space->objfiles ()) { @@ -1682,8 +1692,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset) if (it != fde_table->end ()) { *pc = (*it)->initial_location + offset; - if (out_offset) - *out_offset = offset; + if (out_per_objfile != nullptr) + *out_per_objfile = get_dwarf2_per_objfile (objfile); + return *it; } } diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index e4a9ee9..7f979bf 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -617,7 +617,10 @@ sect_variable_value (struct dwarf_expr_context *ctx, sect_offset sect_off, class dwarf_evaluate_loc_desc : public dwarf_expr_context { - public: +public: + dwarf_evaluate_loc_desc (dwarf2_per_objfile *per_objfile) + : dwarf_expr_context (per_objfile) + {} struct frame_info *frame; struct dwarf2_per_cu_data *per_cu; @@ -733,8 +736,6 @@ class dwarf_evaluate_loc_desc : public dwarf_expr_context this->gdbarch = per_cu->objfile ()->arch (); scoped_restore save_addr_size = make_scoped_restore (&this->addr_size); this->addr_size = per_cu->addr_size (); - scoped_restore save_offset = make_scoped_restore (&this->offset); - this->offset = per_cu->text_offset (); this->eval (data_src, size); } @@ -2191,7 +2192,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, if (size == 0) return allocate_optimized_out_value (subobj_type); - dwarf_evaluate_loc_desc ctx; + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + dwarf_evaluate_loc_desc ctx (per_objfile); ctx.frame = frame; ctx.per_cu = per_cu; ctx.obj_address = 0; @@ -2201,7 +2203,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, ctx.gdbarch = objfile->arch (); ctx.addr_size = per_cu->addr_size (); ctx.ref_addr_size = per_cu->ref_addr_size (); - ctx.offset = per_cu->text_offset (); try { @@ -2398,6 +2399,10 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, struct evaluate_for_locexpr_baton : public dwarf_evaluate_loc_desc { + evaluate_for_locexpr_baton (dwarf2_per_objfile *per_objfile) + : dwarf_evaluate_loc_desc (per_objfile) + {} + /* The data that was passed in. */ gdb::array_view data_view; @@ -2443,12 +2448,11 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, CORE_ADDR *valp, bool push_initial_value) { - struct objfile *objfile; - if (dlbaton == NULL || dlbaton->size == 0) return 0; - evaluate_for_locexpr_baton ctx; + dwarf2_per_objfile *per_objfile = dlbaton->per_objfile; + evaluate_for_locexpr_baton ctx (per_objfile); ctx.frame = frame; ctx.per_cu = dlbaton->per_cu; @@ -2460,12 +2464,9 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, ctx.data_view = addr_stack->valaddr; } - objfile = dlbaton->per_objfile->objfile; - - ctx.gdbarch = objfile->arch (); + ctx.gdbarch = per_objfile->objfile->arch (); ctx.addr_size = dlbaton->per_cu->addr_size (); ctx.ref_addr_size = dlbaton->per_cu->ref_addr_size (); - ctx.offset = dlbaton->per_cu->text_offset (); if (push_initial_value) ctx.push_address (ctx.obj_address, false); @@ -2675,7 +2676,10 @@ dwarf2_compile_property_to_c (string_file *stream, class symbol_needs_eval_context : public dwarf_expr_context { - public: +public: + symbol_needs_eval_context (dwarf2_per_objfile *per_objfile) + : dwarf_expr_context (per_objfile) + {} enum symbol_needs_kind needs; struct dwarf2_per_cu_data *per_cu; @@ -2792,14 +2796,13 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size, scoped_value_mark free_values; - symbol_needs_eval_context ctx; + symbol_needs_eval_context ctx (get_dwarf2_per_objfile (objfile)); ctx.needs = SYMBOL_NEEDS_NONE; ctx.per_cu = per_cu; ctx.gdbarch = objfile->arch (); ctx.addr_size = per_cu->addr_size (); ctx.ref_addr_size = per_cu->ref_addr_size (); - ctx.offset = per_cu->text_offset (); ctx.eval (data, size); -- cgit v1.1