| Index: gdb/dwarf2-frame.c
|
| diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
|
| index 986aaea2335e59f3fded32c487e337495c4cc014..c4f87715c1779853c5aba0c0e31ea11d66085d3c 100644
|
| --- a/gdb/dwarf2-frame.c
|
| +++ b/gdb/dwarf2-frame.c
|
| @@ -1,6 +1,6 @@
|
| /* Frame unwinder for frames with DWARF Call Frame Information.
|
|
|
| - Copyright (C) 2003-2005, 2007-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2003-2013 Free Software Foundation, Inc.
|
|
|
| Contributed by Mark Kettenis.
|
|
|
| @@ -33,7 +33,7 @@
|
| #include "value.h"
|
|
|
| #include "gdb_assert.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
|
|
| #include "complaints.h"
|
| #include "dwarf2-frame.h"
|
| @@ -141,7 +141,7 @@ struct comp_unit
|
| struct objfile *objfile;
|
|
|
| /* Pointer to the .debug_frame section loaded into memory. */
|
| - gdb_byte *dwarf_frame_buffer;
|
| + const gdb_byte *dwarf_frame_buffer;
|
|
|
| /* Length of the loaded .debug_frame section. */
|
| bfd_size_type dwarf_frame_size;
|
| @@ -286,7 +286,7 @@ dwarf2_frame_state_free (void *p)
|
| /* Helper functions for execute_stack_op. */
|
|
|
| static CORE_ADDR
|
| -read_reg (void *baton, int reg)
|
| +read_addr_from_reg (void *baton, int reg)
|
| {
|
| struct frame_info *this_frame = (struct frame_info *) baton;
|
| struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
| @@ -298,12 +298,19 @@ read_reg (void *baton, int reg)
|
| buf = alloca (register_size (gdbarch, regnum));
|
| get_frame_register (this_frame, regnum, buf);
|
|
|
| - /* Convert the register to an integer. This returns a LONGEST
|
| - rather than a CORE_ADDR, but unpack_pointer does the same thing
|
| - under the covers, and this makes more sense for non-pointer
|
| - registers. Maybe read_reg and the associated interfaces should
|
| - deal with "struct value" instead of CORE_ADDR. */
|
| - return unpack_long (register_type (gdbarch, regnum), buf);
|
| + return unpack_pointer (register_type (gdbarch, regnum), buf);
|
| +}
|
| +
|
| +/* 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 = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg);
|
| +
|
| + return value_from_register (type, regnum, this_frame);
|
| }
|
|
|
| static void
|
| @@ -346,7 +353,8 @@ register %s (#%d) at %s"),
|
|
|
| static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs =
|
| {
|
| - read_reg,
|
| + read_addr_from_reg,
|
| + get_reg_value,
|
| read_mem,
|
| ctx_no_get_frame_base,
|
| ctx_no_get_frame_cfa,
|
| @@ -384,7 +392,8 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
|
| if (ctx->location == DWARF_VALUE_MEMORY)
|
| result = dwarf_expr_fetch_address (ctx, 0);
|
| else if (ctx->location == DWARF_VALUE_REGISTER)
|
| - result = read_reg (this_frame, value_as_long (dwarf_expr_fetch (ctx, 0)));
|
| + result = read_addr_from_reg (this_frame,
|
| + value_as_long (dwarf_expr_fetch (ctx, 0)));
|
| else
|
| {
|
| /* This is actually invalid DWARF, but if we ever do run across
|
| @@ -410,7 +419,7 @@ execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
|
| CORE_ADDR pc, struct dwarf2_frame_state *fs)
|
| {
|
| int eh_frame_p = fde->eh_frame_p;
|
| - int bytes_read;
|
| + unsigned int bytes_read;
|
| enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
| while (insn_ptr < insn_end && fs->pc <= pc)
|
| @@ -672,8 +681,8 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
|
| case DW_CFA_GNU_negative_offset_extended:
|
| insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, ®);
|
| reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p);
|
| - insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &offset);
|
| - offset *= fs->data_align;
|
| + insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
|
| + offset = utmp * fs->data_align;
|
| dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
| fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
|
| fs->regs.reg[reg].loc.offset = -offset;
|
| @@ -888,8 +897,6 @@ dwarf2_compile_cfa_to_ax (struct agent_expr *expr, struct axs_value *loc,
|
| CORE_ADDR pc,
|
| struct dwarf2_per_cu_data *data)
|
| {
|
| - const int num_regs = gdbarch_num_regs (gdbarch)
|
| - + gdbarch_num_pseudo_regs (gdbarch);
|
| struct dwarf2_fde *fde;
|
| CORE_ADDR text_offset;
|
| struct dwarf2_frame_state fs;
|
| @@ -986,12 +993,22 @@ struct dwarf2_frame_cache
|
| /* The .text offset. */
|
| CORE_ADDR text_offset;
|
|
|
| + /* True if we already checked whether this frame is the bottom frame
|
| + of a virtual tail call frame chain. */
|
| + int checked_tailcall_bottom;
|
| +
|
| /* 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
|
| involved. Non-bottom frames of a virtual tail call frames chain use
|
| dwarf2_tailcall_frame_unwind unwinder so this field does not apply for
|
| them. */
|
| void *tailcall_cache;
|
| +
|
| + /* The number of bytes to subtract from TAILCALL_FRAME frames frame
|
| + base to get the SP, to simulate the return address pushed on the
|
| + stack. */
|
| + LONGEST entry_cfa_sp_offset;
|
| + int entry_cfa_sp_offset_p;
|
| };
|
|
|
| /* A cleanup that sets a pointer to NULL. */
|
| @@ -1016,8 +1033,6 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
|
| struct dwarf2_fde *fde;
|
| volatile struct gdb_exception ex;
|
| CORE_ADDR entry_pc;
|
| - LONGEST entry_cfa_sp_offset;
|
| - int entry_cfa_sp_offset_p = 0;
|
| const gdb_byte *instr;
|
|
|
| if (*this_cache)
|
| @@ -1065,7 +1080,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
|
|
|
| /* First decode all the insns in the CIE. */
|
| execute_cfa_program (fde, fde->cie->initial_instructions,
|
| - fde->cie->end, gdbarch, get_frame_pc (this_frame), fs);
|
| + fde->cie->end, gdbarch,
|
| + get_frame_address_in_block (this_frame), fs);
|
|
|
| /* Save the initialized register set. */
|
| fs->initial = fs->regs;
|
| @@ -1081,8 +1097,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
|
| && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg)
|
| == gdbarch_sp_regnum (gdbarch)))
|
| {
|
| - entry_cfa_sp_offset = fs->regs.cfa_offset;
|
| - entry_cfa_sp_offset_p = 1;
|
| + cache->entry_cfa_sp_offset = fs->regs.cfa_offset;
|
| + cache->entry_cfa_sp_offset_p = 1;
|
| }
|
| }
|
| else
|
| @@ -1090,7 +1106,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_pc (this_frame), fs);
|
| + get_frame_address_in_block (this_frame), fs);
|
|
|
| TRY_CATCH (ex, RETURN_MASK_ERROR)
|
| {
|
| @@ -1098,7 +1114,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
|
| switch (fs->regs.cfa_how)
|
| {
|
| case CFA_REG_OFFSET:
|
| - cache->cfa = read_reg (this_frame, fs->regs.cfa_reg);
|
| + cache->cfa = read_addr_from_reg (this_frame, fs->regs.cfa_reg);
|
| if (fs->armcc_cfa_offsets_reversed)
|
| cache->cfa -= fs->regs.cfa_offset;
|
| else
|
| @@ -1231,13 +1247,6 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"),
|
| cache->undefined_retaddr = 1;
|
|
|
| do_cleanups (old_chain);
|
| -
|
| - /* Try to find a virtual tail call frames chain with bottom (callee) frame
|
| - starting at THIS_FRAME. */
|
| - dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
|
| - (entry_cfa_sp_offset_p
|
| - ? &entry_cfa_sp_offset : NULL));
|
| -
|
| discard_cleanups (reset_cache_cleanup);
|
| return cache;
|
| }
|
| @@ -1284,6 +1293,16 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
|
| CORE_ADDR addr;
|
| int realnum;
|
|
|
| + /* Check whether THIS_FRAME is the bottom frame of a virtual tail
|
| + call frame chain. */
|
| + if (!cache->checked_tailcall_bottom)
|
| + {
|
| + cache->checked_tailcall_bottom = 1;
|
| + dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
|
| + (cache->entry_cfa_sp_offset_p
|
| + ? &cache->entry_cfa_sp_offset : NULL));
|
| + }
|
| +
|
| /* Non-bottom frames of a virtual tail call frames chain use
|
| dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
|
| them. If dwarf2_tailcall_prev_register_first does not have specific value
|
| @@ -1410,10 +1429,6 @@ dwarf2_frame_sniffer (const struct frame_unwind *self,
|
| if (self->type != NORMAL_FRAME)
|
| return 0;
|
|
|
| - /* Preinitializa the cache so that TAILCALL_FRAME can find the record by
|
| - dwarf2_tailcall_sniffer_first. */
|
| - dwarf2_frame_cache (this_frame, this_cache);
|
| -
|
| return 1;
|
| }
|
|
|
| @@ -1804,11 +1819,7 @@ add_fde (struct dwarf2_fde_table *fde_table, struct dwarf2_fde *fde)
|
| fde_table->entries[fde_table->num_entries - 1] = fde;
|
| }
|
|
|
| -#ifdef CC_HAS_LONG_LONG
|
| #define DW64_CIE_ID 0xffffffffffffffffULL
|
| -#else
|
| -#define DW64_CIE_ID ~0
|
| -#endif
|
|
|
| /* Defines the type of eh_frames that are expected to be decoded: CIE, FDE
|
| or any of them. */
|
| @@ -2311,7 +2322,7 @@ dwarf2_build_frame_info (struct objfile *objfile)
|
| if (e.reason < 0)
|
| {
|
| warning (_("skipping .eh_frame info of %s: %s"),
|
| - objfile->name, e.message);
|
| + objfile_name (objfile), e.message);
|
|
|
| if (fde_table.num_entries != 0)
|
| {
|
| @@ -2351,7 +2362,7 @@ dwarf2_build_frame_info (struct objfile *objfile)
|
| if (e.reason < 0)
|
| {
|
| warning (_("skipping .debug_frame info of %s: %s"),
|
| - objfile->name, e.message);
|
| + objfile_name (objfile), e.message);
|
|
|
| if (fde_table.num_entries != 0)
|
| {
|
|
|