diff options
Diffstat (limited to 'gdb/dwarf2/expr.c')
-rw-r--r-- | gdb/dwarf2/expr.c | 90 |
1 files changed, 73 insertions, 17 deletions
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 3a6165a..346bf7f 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -1,6 +1,6 @@ /* DWARF 2 Expression Evaluator. - Copyright (C) 2001-2024 Free Software Foundation, Inc. + Copyright (C) 2001-2025 Free Software Foundation, Inc. Contributed by Daniel Berlin (dan@dberlin.org) @@ -880,6 +880,34 @@ dwarf_expr_context::read_mem (gdb_byte *buf, CORE_ADDR addr, /* See expr.h. */ +value * +dwarf_expr_context::deref (CORE_ADDR addr, int size, struct type *type) +{ + gdb_byte *buf = (gdb_byte *) alloca (size); + this->read_mem (buf, addr, size); + + if (type == nullptr) + type = this->address_type (); + + /* If the size of the object read from memory is different + from the type length, we need to zero-extend it. */ + if (type->length () != size) + { + gdbarch *arch = this->m_per_objfile->objfile->arch (); + bfd_endian byte_order = gdbarch_byte_order (arch); + ULONGEST datum + = extract_unsigned_integer (buf, size, byte_order); + + buf = (gdb_byte *) alloca (type->length ()); + store_unsigned_integer (buf, type->length (), + byte_order, datum); + } + + return value_from_contents_and_address (type, buf, addr); +} + +/* See expr.h. */ + void dwarf_expr_context::push_dwarf_reg_entry_value (call_site_parameter_kind kind, call_site_parameter_u kind_u, @@ -1507,6 +1535,27 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, return 1; } +/* Return true if, for an expr evaluated in the context of FRAME, we can + assume that DW_OP_entry_value (expr) == expr. + + We can assume this right after executing a call, when stopped at the + start of the called function, in other words, when: + - FRAME is the innermost frame, and + - FRAME->pc is the first insn in a function. */ + +static bool +trivial_entry_value (frame_info_ptr frame) +{ + bool innermost_frame = frame_relative_level (frame) == 0; + + /* Get pc corresponding to frame. Use get_frame_address_in_block to make + sure we get a pc in the correct function in the case of tail calls. */ + CORE_ADDR pc = get_frame_address_in_block (frame); + bool at_first_insn = find_function_type (pc) != nullptr; + + return innermost_frame && at_first_insn; +} + /* The engine for the expression evaluator. Using the context in this object, evaluate the expression between OP_PTR and OP_END. */ @@ -1916,7 +1965,6 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, case DW_OP_GNU_deref_type: { int addr_size = (op == DW_OP_deref ? this->m_addr_size : *op_ptr++); - gdb_byte *buf = (gdb_byte *) alloca (addr_size); CORE_ADDR addr = fetch_address (0); struct type *type; @@ -1931,21 +1979,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, else type = address_type; - 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. */ - if (type->length () != addr_size) - { - ULONGEST datum = - extract_unsigned_integer (buf, addr_size, byte_order); - - buf = (gdb_byte *) alloca (type->length ()); - store_unsigned_integer (buf, type->length (), - byte_order, datum); - } - - result_val = value_from_contents_and_address (type, buf, addr); + result_val = this->deref (addr, addr_size, type); break; } @@ -2274,6 +2308,17 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, if (kind_u.dwarf_reg != -1) { op_ptr += len; + + if (trivial_entry_value (this->m_frame)) + { + /* We can assume that DW_OP_entry_value (expr) == expr. + Handle as DW_OP_regx. */ + result_val + = value_from_ulongest (address_type, kind_u.dwarf_reg); + this->m_location = DWARF_VALUE_REGISTER; + break; + } + this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG, kind_u, -1 /* deref_size */); @@ -2288,6 +2333,17 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, if (deref_size == -1) deref_size = this->m_addr_size; op_ptr += len; + + if (trivial_entry_value (this->m_frame)) + { + /* We can assume that DW_OP_entry_value (expr) == expr. + Handle as DW_OP_bregx;DW_OP_deref_size. */ + CORE_ADDR addr + = read_addr_from_reg (this->m_frame, kind_u.dwarf_reg); + result_val = this->deref (addr, deref_size); + break; + } + this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG, kind_u, deref_size); goto no_push; |