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) |
{ |