X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2-frame.c;h=ce11d89ed42932a8a3ce7b59815399a59109bb28;hb=4e99ad6974d2233414bccf6989139dead4132704;hp=fa65f25a875df5fda8a716c20d0788a83c9ff8fa;hpb=cbdfc7c029fe3dfed60580245332f53271842eba;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index fa65f25a87..ce11d89ed4 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -1,6 +1,7 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -8,7 +9,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,9 +18,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "dwarf2expr.h" @@ -32,6 +31,7 @@ #include "symtab.h" #include "objfiles.h" #include "regcache.h" +#include "value.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -39,12 +39,17 @@ #include "complaints.h" #include "dwarf2-frame.h" +struct comp_unit; + /* Call Frame Information (CFI). */ /* Common Information Entry (CIE). */ struct dwarf2_cie { + /* Computation Unit for this CIE. */ + struct comp_unit *unit; + /* Offset into the .debug_frame section where this CIE was found. Used to identify this CIE. */ ULONGEST cie_pointer; @@ -60,15 +65,27 @@ struct dwarf2_cie ULONGEST return_address_register; /* Instruction sequence to initialize a register set. */ - unsigned char *initial_instructions; - unsigned char *end; + gdb_byte *initial_instructions; + gdb_byte *end; + + /* Saved augmentation, in case it's needed later. */ + char *augmentation; /* Encoding of addresses. */ - unsigned char encoding; + gdb_byte encoding; + + /* Target address size in bytes. */ + int addr_size; /* True if a 'z' augmentation existed. */ unsigned char saw_z_augmentation; + /* True if an 'S' augmentation existed. */ + unsigned char signal_frame; + + /* The version recorded in the CIE. */ + unsigned char version; + struct dwarf2_cie *next; }; @@ -86,55 +103,65 @@ struct dwarf2_fde CORE_ADDR address_range; /* Instruction sequence. */ - unsigned char *instructions; - unsigned char *end; + gdb_byte *instructions; + gdb_byte *end; + + /* True if this FDE is read from a .eh_frame instead of a .debug_frame + section. */ + unsigned char eh_frame_p; struct dwarf2_fde *next; }; +/* A minimal decoding of DWARF2 compilation units. We only decode + what's needed to get to the call frame information. */ + +struct comp_unit +{ + /* Keep the bfd convenient. */ + bfd *abfd; + + struct objfile *objfile; + + /* Linked list of CIEs for this object. */ + struct dwarf2_cie *cie; + + /* Pointer to the .debug_frame section loaded into memory. */ + gdb_byte *dwarf_frame_buffer; + + /* Length of the loaded .debug_frame section. */ + unsigned long dwarf_frame_size; + + /* Pointer to the .debug_frame section. */ + asection *dwarf_frame_section; + + /* Base for DW_EH_PE_datarel encodings. */ + bfd_vma dbase; + + /* Base for DW_EH_PE_textrel encodings. */ + bfd_vma tbase; +}; + static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc); + +static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, + int eh_frame_p); + +static CORE_ADDR read_encoded_value (struct comp_unit *unit, gdb_byte encoding, + int ptr_len, gdb_byte *buf, + unsigned int *bytes_read_ptr, + CORE_ADDR func_base); /* Structure describing a frame state. */ -enum dwarf2_reg_rule -{ - /* Make certain that 0 maps onto the correct enum value - the - corresponding structure is being initialized using memset zero. - This indicates that CFI didn't provide any information at all - about a register - leaving how to obtain it's value totally - unspecified. */ - REG_UNSPECIFIED = 0, - /* The term "undefined" comes from the DWARF2 CFI spec which this - code is moddeling - it indicates that the register's value is - "undefined". */ - /* NOTE: cagney/2003-09-08: GCC uses the less formal term "unsaved" - - it's definition is a combination of REG_UNDEFINED and - REG_UNSPECIFIED - the failure to differentiate the two helps - explain a few problems with the CFI GCC outputs. */ - REG_UNDEFINED, - REG_SAVED_OFFSET, - REG_SAVED_REG, - REG_SAVED_EXP, - REG_SAME_VALUE -}; - struct dwarf2_frame_state { /* Each register save state can be described in terms of a CFA slot, another register, or a location expression. */ struct dwarf2_frame_state_reg_info { - struct dwarf2_frame_state_reg - { - union { - LONGEST offset; - ULONGEST reg; - unsigned char *exp; - } loc; - ULONGEST exp_len; - enum dwarf2_reg_rule how; - } *reg; + struct dwarf2_frame_state_reg *reg; int num_regs; /* Used to implement DW_CFA_remember_state. */ @@ -143,7 +170,7 @@ struct dwarf2_frame_state LONGEST cfa_offset; ULONGEST cfa_reg; - unsigned char *cfa_exp; + gdb_byte *cfa_exp; enum { CFA_UNSET, CFA_REG_OFFSET, @@ -161,13 +188,23 @@ struct dwarf2_frame_state LONGEST data_align; ULONGEST code_align; ULONGEST retaddr_column; + + /* Flags for known producer quirks. */ + + /* The ARM compilers, in DWARF2 mode, assume that DW_CFA_def_cfa + and DW_CFA_def_cfa_offset takes a factored offset. */ + int armcc_cfa_offsets_sf; + + /* The ARM compilers, in DWARF2 or DWARF3 mode, may assume that + the CFA is defined as REG - OFFSET rather than REG + OFFSET. */ + int armcc_cfa_offsets_reversed; }; /* Store the length the expression for the CFA in the `cfa_reg' field, which is unused in that case. */ #define cfa_exp_len cfa_reg -/* Assert that the register set RS is large enough to store NUM_REGS +/* Assert that the register set RS is large enough to store gdbarch_num_regs columns. If necessary, enlarge the register set. */ static void @@ -193,7 +230,7 @@ dwarf2_frame_state_alloc_regs (struct dwarf2_frame_state_reg_info *rs, static struct dwarf2_frame_state_reg * dwarf2_frame_state_copy_regs (struct dwarf2_frame_state_reg_info *rs) { - size_t size = rs->num_regs * sizeof (struct dwarf2_frame_state_reg_info); + size_t size = rs->num_regs * sizeof (struct dwarf2_frame_state_reg); struct dwarf2_frame_state_reg *reg; reg = (struct dwarf2_frame_state_reg *) xmalloc (size); @@ -236,46 +273,85 @@ dwarf2_frame_state_free (void *p) static CORE_ADDR read_reg (void *baton, int reg) { - struct frame_info *next_frame = (struct frame_info *) baton; + struct frame_info *this_frame = (struct frame_info *) baton; + struct gdbarch *gdbarch = get_frame_arch (this_frame); int regnum; - char *buf; + gdb_byte *buf; - regnum = DWARF2_REG_TO_REGNUM (reg); + regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); - buf = (char *) alloca (register_size (current_gdbarch, regnum)); - frame_unwind_register (next_frame, regnum, buf); - return extract_typed_address (buf, builtin_type_void_data_ptr); + 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); } static void -read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len) +read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) { read_memory (addr, buf, len); } static void -no_get_frame_base (void *baton, unsigned char **start, size_t *length) +no_get_frame_base (void *baton, gdb_byte **start, size_t *length) { internal_error (__FILE__, __LINE__, - "Support for DW_OP_fbreg is unimplemented"); + _("Support for DW_OP_fbreg is unimplemented")); } static CORE_ADDR no_get_tls_address (void *baton, CORE_ADDR offset) { internal_error (__FILE__, __LINE__, - "Support for DW_OP_GNU_push_tls_address is unimplemented"); + _("Support for DW_OP_GNU_push_tls_address is unimplemented")); +} + +/* Execute the required actions for both the DW_CFA_restore and +DW_CFA_restore_extended instructions. */ +static void +dwarf2_restore_rule (struct gdbarch *gdbarch, ULONGEST reg_num, + struct dwarf2_frame_state *fs, int eh_frame_p) +{ + ULONGEST reg; + + gdb_assert (fs->initial.reg); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg_num, eh_frame_p); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + + /* Check if this register was explicitly initialized in the + CIE initial instructions. If not, default the rule to + UNSPECIFIED. */ + if (reg < fs->initial.num_regs) + fs->regs.reg[reg] = fs->initial.reg[reg]; + else + fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNSPECIFIED; + + if (fs->regs.reg[reg].how == DWARF2_FRAME_REG_UNSPECIFIED) + complaint (&symfile_complaints, _("\ +incomplete CFI data; DW_CFA_restore unspecified\n\ +register %s (#%d) at 0x%s"), + gdbarch_register_name + (gdbarch, gdbarch_dwarf2_reg_to_regnum (gdbarch, reg)), + gdbarch_dwarf2_reg_to_regnum (gdbarch, reg), + paddr (fs->pc)); } static CORE_ADDR -execute_stack_op (unsigned char *exp, ULONGEST len, - struct frame_info *next_frame, CORE_ADDR initial) +execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, + struct frame_info *this_frame, CORE_ADDR initial) { struct dwarf_expr_context *ctx; CORE_ADDR result; ctx = new_dwarf_expr_context (); - ctx->baton = next_frame; + ctx->gdbarch = get_frame_arch (this_frame); + ctx->addr_size = addr_size; + ctx->baton = this_frame; ctx->read_reg = read_reg; ctx->read_mem = read_mem; ctx->get_frame_base = no_get_frame_base; @@ -286,7 +362,7 @@ execute_stack_op (unsigned char *exp, ULONGEST len, result = dwarf_expr_fetch (ctx, 0); if (ctx->in_reg) - result = read_reg (next_frame, result); + result = read_reg (this_frame, result); free_dwarf_expr_context (ctx); @@ -295,16 +371,18 @@ execute_stack_op (unsigned char *exp, ULONGEST len, static void -execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, - struct frame_info *next_frame, +execute_cfa_program (struct dwarf2_fde *fde, gdb_byte *insn_ptr, + gdb_byte *insn_end, struct frame_info *this_frame, struct dwarf2_frame_state *fs) { - CORE_ADDR pc = frame_pc_unwind (next_frame); + int eh_frame_p = fde->eh_frame_p; + CORE_ADDR pc = get_frame_pc (this_frame); int bytes_read; + struct gdbarch *gdbarch = get_frame_arch (this_frame); while (insn_ptr < insn_end && fs->pc <= pc) { - unsigned char insn = *insn_ptr++; + gdb_byte insn = *insn_ptr++; ULONGEST utmp, reg; LONGEST offset; @@ -313,25 +391,29 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, else if ((insn & 0xc0) == DW_CFA_offset) { reg = insn & 0x3f; + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); insn_ptr = 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 = REG_SAVED_OFFSET; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } else if ((insn & 0xc0) == DW_CFA_restore) { - gdb_assert (fs->initial.reg); reg = insn & 0x3f; - dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg] = fs->initial.reg[reg]; + dwarf2_restore_rule (gdbarch, reg, fs, eh_frame_p); } else { switch (insn) { case DW_CFA_set_loc: - fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read); + fs->pc = read_encoded_value (fde->cie->unit, fde->cie->encoding, + fde->cie->addr_size, insn_ptr, + &bytes_read, fde->initial_location); + /* Apply the objfile offset for relocatable objects. */ + fs->pc += ANOFFSET (fde->cie->unit->objfile->section_offsets, + SECT_OFF_TEXT (fde->cie->unit->objfile)); insn_ptr += bytes_read; break; @@ -353,37 +435,40 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, case DW_CFA_offset_extended: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); insn_ptr = 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 = REG_SAVED_OFFSET; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; case DW_CFA_restore_extended: - gdb_assert (fs->initial.reg); insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); - dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg] = fs->initial.reg[reg]; + dwarf2_restore_rule (gdbarch, reg, fs, eh_frame_p); break; case DW_CFA_undefined: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_UNDEFINED; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNDEFINED; break; case DW_CFA_same_value: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAME_VALUE; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAME_VALUE; break; case DW_CFA_register: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + utmp = dwarf2_frame_adjust_regnum (gdbarch, utmp, eh_frame_p); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAVED_REG; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG; fs->regs.reg[reg].loc.reg = utmp; break; @@ -402,31 +487,51 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, { struct dwarf2_frame_state_reg_info *old_rs = fs->regs.prev; - gdb_assert (old_rs); - - xfree (fs->regs.reg); - fs->regs = *old_rs; - xfree (old_rs); + if (old_rs == NULL) + { + complaint (&symfile_complaints, _("\ +bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc)); + } + else + { + xfree (fs->regs.reg); + fs->regs = *old_rs; + xfree (old_rs); + } } break; case DW_CFA_def_cfa: insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg); insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + + if (fs->armcc_cfa_offsets_sf) + utmp *= fs->data_align; + fs->cfa_offset = utmp; fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_register: insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg); + fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg, + eh_frame_p); fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_offset: - insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_offset); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + + if (fs->armcc_cfa_offsets_sf) + utmp *= fs->data_align; + + fs->cfa_offset = utmp; /* cfa_how deliberately not set. */ break; + case DW_CFA_nop: + break; + case DW_CFA_def_cfa_expression: insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_exp_len); fs->cfa_exp = insn_ptr; @@ -436,15 +541,90 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, case DW_CFA_expression: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); fs->regs.reg[reg].loc.exp = insn_ptr; fs->regs.reg[reg].exp_len = utmp; - fs->regs.reg[reg].how = REG_SAVED_EXP; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_EXP; insn_ptr += utmp; break; - case DW_CFA_nop: + case DW_CFA_offset_extended_sf: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); + insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); + offset *= 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; + break; + + case DW_CFA_val_offset: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + offset = utmp * fs->data_align; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_val_offset_sf: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); + offset *= fs->data_align; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_val_expression: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + fs->regs.reg[reg].loc.exp = insn_ptr; + fs->regs.reg[reg].exp_len = utmp; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP; + insn_ptr += utmp; + break; + + case DW_CFA_def_cfa_sf: + insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg); + fs->cfa_reg = dwarf2_frame_adjust_regnum (gdbarch, fs->cfa_reg, + eh_frame_p); + insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); + fs->cfa_offset = offset * fs->data_align; + fs->cfa_how = CFA_REG_OFFSET; + break; + + case DW_CFA_def_cfa_offset_sf: + insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); + fs->cfa_offset = offset * fs->data_align; + /* cfa_how deliberately not set. */ + break; + + case DW_CFA_GNU_window_save: + /* This is SPARC-specific code, and contains hard-coded + constants for the register numbering scheme used by + GCC. Rather than having a architecture-specific + operation that's only ever used by a single + architecture, we provide the implementation here. + Incidentally that's what GCC does too in its + unwinder. */ + { + int size = register_size (gdbarch, 0); + dwarf2_frame_state_alloc_regs (&fs->regs, 32); + for (reg = 8; reg < 16; reg++) + { + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG; + fs->regs.reg[reg].loc.reg = reg + 16; + } + for (reg = 16; reg < 32; reg++) + { + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = (reg - 16) * size; + } + } break; case DW_CFA_GNU_args_size: @@ -452,8 +632,18 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); break; + case DW_CFA_GNU_negative_offset_extended: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + reg = dwarf2_frame_adjust_regnum (gdbarch, reg, eh_frame_p); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &offset); + offset *= 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; + break; + default: - internal_error (__FILE__, __LINE__, "Unknown CFI encountered."); + internal_error (__FILE__, __LINE__, _("Unknown CFI encountered.")); } } } @@ -462,22 +652,228 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, dwarf2_frame_state_free_regs (fs->regs.prev); fs->regs.prev = NULL; } + + +/* Architecture-specific operations. */ + +/* Per-architecture data key. */ +static struct gdbarch_data *dwarf2_frame_data; + +struct dwarf2_frame_ops +{ + /* Pre-initialize the register state REG for register REGNUM. */ + void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *, + struct frame_info *); + + /* Check whether the THIS_FRAME is a signal trampoline. */ + int (*signal_frame_p) (struct gdbarch *, struct frame_info *); + + /* Convert .eh_frame register number to DWARF register number, or + adjust .debug_frame register number. */ + int (*adjust_regnum) (struct gdbarch *, int, int); +}; + +/* Default architecture-specific register state initialization + function. */ + +static void +dwarf2_frame_default_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg, + struct frame_info *this_frame) +{ + /* If we have a register that acts as a program counter, mark it as + a destination for the return address. If we have a register that + serves as the stack pointer, arrange for it to be filled with the + call frame address (CFA). The other registers are marked as + unspecified. + + We copy the return address to the program counter, since many + parts in GDB assume that it is possible to get the return address + by unwinding the program counter register. However, on ISA's + with a dedicated return address register, the CFI usually only + contains information to unwind that return address register. + + The reason we're treating the stack pointer special here is + because in many cases GCC doesn't emit CFI for the stack pointer + and implicitly assumes that it is equal to the CFA. This makes + some sense since the DWARF specification (version 3, draft 8, + p. 102) says that: + + "Typically, the CFA is defined to be the value of the stack + pointer at the call site in the previous frame (which may be + different from its value on entry to the current frame)." + + However, this isn't true for all platforms supported by GCC + (e.g. IBM S/390 and zSeries). Those architectures should provide + their own architecture-specific initialization function. */ + + if (regnum == gdbarch_pc_regnum (gdbarch)) + reg->how = DWARF2_FRAME_REG_RA; + else if (regnum == gdbarch_sp_regnum (gdbarch)) + reg->how = DWARF2_FRAME_REG_CFA; +} + +/* Return a default for the architecture-specific operations. */ + +static void * +dwarf2_frame_init (struct obstack *obstack) +{ + struct dwarf2_frame_ops *ops; + + ops = OBSTACK_ZALLOC (obstack, struct dwarf2_frame_ops); + ops->init_reg = dwarf2_frame_default_init_reg; + return ops; +} + +/* Set the architecture-specific register state initialization + function for GDBARCH to INIT_REG. */ + +void +dwarf2_frame_set_init_reg (struct gdbarch *gdbarch, + void (*init_reg) (struct gdbarch *, int, + struct dwarf2_frame_state_reg *, + struct frame_info *)) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + ops->init_reg = init_reg; +} + +/* Pre-initialize the register state REG for register REGNUM. */ + +static void +dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg, + struct frame_info *this_frame) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + ops->init_reg (gdbarch, regnum, reg, this_frame); +} + +/* Set the architecture-specific signal trampoline recognition + function for GDBARCH to SIGNAL_FRAME_P. */ + +void +dwarf2_frame_set_signal_frame_p (struct gdbarch *gdbarch, + int (*signal_frame_p) (struct gdbarch *, + struct frame_info *)) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + ops->signal_frame_p = signal_frame_p; +} + +/* Query the architecture-specific signal frame recognizer for + THIS_FRAME. */ + +static int +dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch, + struct frame_info *this_frame) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + if (ops->signal_frame_p == NULL) + return 0; + return ops->signal_frame_p (gdbarch, this_frame); +} + +/* Set the architecture-specific adjustment of .eh_frame and .debug_frame + register numbers. */ + +void +dwarf2_frame_set_adjust_regnum (struct gdbarch *gdbarch, + int (*adjust_regnum) (struct gdbarch *, + int, int)) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + ops->adjust_regnum = adjust_regnum; +} + +/* Translate a .eh_frame register to DWARF register, or adjust a .debug_frame + register. */ + +static int +dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p) +{ + struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data); + + if (ops->adjust_regnum == NULL) + return regnum; + return ops->adjust_regnum (gdbarch, regnum, eh_frame_p); +} + +static void +dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs, + struct dwarf2_fde *fde) +{ + static const char *arm_idents[] = { + "ARM C Compiler, ADS", + "Thumb C Compiler, ADS", + "ARM C++ Compiler, ADS", + "Thumb C++ Compiler, ADS", + "ARM/Thumb C/C++ Compiler, RVCT" + }; + int i; + + struct symtab *s; + + s = find_pc_symtab (fs->pc); + if (s == NULL || s->producer == NULL) + return; + + for (i = 0; i < ARRAY_SIZE (arm_idents); i++) + if (strncmp (s->producer, arm_idents[i], strlen (arm_idents[i])) == 0) + { + if (fde->cie->version == 1) + fs->armcc_cfa_offsets_sf = 1; + + if (fde->cie->version == 1) + fs->armcc_cfa_offsets_reversed = 1; + + /* The reversed offset problem is present in some compilers + using DWARF3, but it was eventually fixed. Check the ARM + defined augmentations, which are in the format "armcc" followed + by a list of one-character options. The "+" option means + this problem is fixed (no quirk needed). If the armcc + augmentation is missing, the quirk is needed. */ + if (fde->cie->version == 3 + && (strncmp (fde->cie->augmentation, "armcc", 5) != 0 + || strchr (fde->cie->augmentation + 5, '+') == NULL)) + fs->armcc_cfa_offsets_reversed = 1; + + return; + } +} + struct dwarf2_frame_cache { /* DWARF Call Frame Address. */ CORE_ADDR cfa; + /* Set if the return address column was marked as undefined. */ + int undefined_retaddr; + /* Saved registers, indexed by GDB register number, not by DWARF register number. */ struct dwarf2_frame_state_reg *reg; + + /* Return address register. */ + struct dwarf2_frame_state_reg retaddr_reg; + + /* Target address size in bytes. */ + int addr_size; }; static struct dwarf2_frame_cache * -dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) +dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) { struct cleanup *old_chain; - const int num_regs = NUM_REGS + NUM_PSEUDO_REGS; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + const int num_regs = gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch); struct dwarf2_frame_cache *cache; struct dwarf2_frame_state *fs; struct dwarf2_fde *fde; @@ -496,23 +892,20 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) /* Unwind the PC. - Note that if NEXT_FRAME is never supposed to return (i.e. a call + Note that if the next frame is never supposed to return (i.e. a call to abort), the compiler might optimize away the instruction at - NEXT_FRAME's return address. As a result the return address will + its return address. As a result the return address will point at some random instruction, and the CFI for that - instruction is probably wortless to us. GCC's unwinder solves + instruction is probably worthless to us. GCC's unwinder solves this problem by substracting 1 from the return address to get an address in the middle of a presumed call instruction (or the instruction in the associated delay slot). This should only be done for "normal" frames and not for resume-type frames (signal - handlers, sentinel frames, dummy frames). - - frame_unwind_address_in_block does just this. - - It's not clear how reliable the method is though - there is the - potential for the register state pre-call being different to that - on return. */ - fs->pc = frame_unwind_address_in_block (next_frame); + handlers, sentinel frames, dummy frames). The function + get_frame_address_in_block does just this. It's not clear how + reliable the method is though; there is the potential for the + register state pre-call being different to that on return. */ + fs->pc = get_frame_address_in_block (this_frame); /* Find the correct FDE. */ fde = dwarf2_frame_find_fde (&fs->pc); @@ -522,114 +915,143 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) fs->data_align = fde->cie->data_alignment_factor; fs->code_align = fde->cie->code_alignment_factor; fs->retaddr_column = fde->cie->return_address_register; + cache->addr_size = fde->cie->addr_size; + + /* Check for "quirks" - known bugs in producers. */ + dwarf2_frame_find_quirks (fs, fde); /* First decode all the insns in the CIE. */ - execute_cfa_program (fde->cie->initial_instructions, - fde->cie->end, next_frame, fs); + execute_cfa_program (fde, fde->cie->initial_instructions, + fde->cie->end, this_frame, fs); /* Save the initialized register set. */ fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde->instructions, fde->end, next_frame, fs); + execute_cfa_program (fde, fde->instructions, fde->end, this_frame, fs); - /* Caclulate the CFA. */ + /* Calculate the CFA. */ switch (fs->cfa_how) { case CFA_REG_OFFSET: - cache->cfa = read_reg (next_frame, fs->cfa_reg); - cache->cfa += fs->cfa_offset; + cache->cfa = read_reg (this_frame, fs->cfa_reg); + if (fs->armcc_cfa_offsets_reversed) + cache->cfa -= fs->cfa_offset; + else + cache->cfa += fs->cfa_offset; break; case CFA_EXP: cache->cfa = - execute_stack_op (fs->cfa_exp, fs->cfa_exp_len, next_frame, 0); + execute_stack_op (fs->cfa_exp, fs->cfa_exp_len, + cache->addr_size, this_frame, 0); break; default: - internal_error (__FILE__, __LINE__, "Unknown CFA rule."); + internal_error (__FILE__, __LINE__, _("Unknown CFA rule.")); } - /* Initialize things so that all registers are marked as - unspecified. */ + /* Initialize the register state. */ { int regnum; + for (regnum = 0; regnum < num_regs; regnum++) - cache->reg[regnum].how = REG_UNSPECIFIED; + dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum], this_frame); } /* Go through the DWARF2 CFI generated table and save its register - location information in the cache. */ + location information in the cache. Note that we don't skip the + return address column; it's perfectly all right for it to + correspond to a real register. If it doesn't correspond to a + real register, or if we shouldn't treat it as such, + gdbarch_dwarf2_reg_to_regnum should be defined to return a number outside + the range [0, gdbarch_num_regs). */ { int column; /* CFI speak for "register number". */ + for (column = 0; column < fs->regs.num_regs; column++) { - int regnum; - - /* Skip the return address column. */ - if (column == fs->retaddr_column) - /* NOTE: cagney/2003-06-07: Is this right? What if - RETADDR_COLUMN corresponds to a real register (and, - worse, that isn't the PC_REGNUM)? I'm guessing that the - PC_REGNUM further down is trying to handle this. That - can't be right though - PC_REGNUM may not be valid (it - can be -ve). I think, instead when RETADDR_COLUM isn't a - real register, it should map itself onto frame_pc_unwind. */ - continue; - /* Use the GDB register number as the destination index. */ - regnum = DWARF2_REG_TO_REGNUM (column); + int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, column); /* If there's no corresponding GDB register, ignore it. */ if (regnum < 0 || regnum >= num_regs) continue; /* NOTE: cagney/2003-09-05: CFI should specify the disposition - of all debug info registers. If it doesn't complain (but - not too loudly). It turns out that GCC, assumes that an + of all debug info registers. If it doesn't, complain (but + not too loudly). It turns out that GCC assumes that an unspecified register implies "same value" when CFI (draft 7) specifies nothing at all. Such a register could equally be interpreted as "undefined". Also note that this check - isn't sufficient - it only checks that all registers in the - range [0 .. max column] are specified - and won't detect + isn't sufficient; it only checks that all registers in the + range [0 .. max column] are specified, and won't detect problems when a debug info register falls outside of the - table. Need a way of iterating through all the valid + table. We need a way of iterating through all the valid DWARF2 register numbers. */ - if (fs->regs.reg[column].how == REG_UNSPECIFIED) - complaint (&symfile_complaints, - "Incomplete CFI data; unspecified registers at 0x%s", - paddr (fs->pc)); + if (fs->regs.reg[column].how == DWARF2_FRAME_REG_UNSPECIFIED) + { + if (cache->reg[regnum].how == DWARF2_FRAME_REG_UNSPECIFIED) + complaint (&symfile_complaints, _("\ +incomplete CFI data; unspecified registers (e.g., %s) at 0x%s"), + gdbarch_register_name (gdbarch, regnum), + paddr_nz (fs->pc)); + } + else + cache->reg[regnum] = fs->regs.reg[column]; + } + } + + /* Eliminate any DWARF2_FRAME_REG_RA rules, and save the information + we need for evaluating DWARF2_FRAME_REG_RA_OFFSET rules. */ + { + int regnum; - cache->reg[regnum] = fs->regs.reg[column]; + for (regnum = 0; regnum < num_regs; regnum++) + { + if (cache->reg[regnum].how == DWARF2_FRAME_REG_RA + || cache->reg[regnum].how == DWARF2_FRAME_REG_RA_OFFSET) + { + struct dwarf2_frame_state_reg *retaddr_reg = + &fs->regs.reg[fs->retaddr_column]; + + /* It seems rather bizarre to specify an "empty" column as + the return adress column. However, this is exactly + what GCC does on some targets. It turns out that GCC + assumes that the return address can be found in the + register corresponding to the return address column. + Incidentally, that's how we should treat a return + address column specifying "same value" too. */ + if (fs->retaddr_column < fs->regs.num_regs + && retaddr_reg->how != DWARF2_FRAME_REG_UNSPECIFIED + && retaddr_reg->how != DWARF2_FRAME_REG_SAME_VALUE) + { + if (cache->reg[regnum].how == DWARF2_FRAME_REG_RA) + cache->reg[regnum] = *retaddr_reg; + else + cache->retaddr_reg = *retaddr_reg; + } + else + { + if (cache->reg[regnum].how == DWARF2_FRAME_REG_RA) + { + cache->reg[regnum].loc.reg = fs->retaddr_column; + cache->reg[regnum].how = DWARF2_FRAME_REG_SAVED_REG; + } + else + { + cache->retaddr_reg.loc.reg = fs->retaddr_column; + cache->retaddr_reg.how = DWARF2_FRAME_REG_SAVED_REG; + } + } + } } } - /* Store the location of the return addess. If the return address - column (adjusted) is not the same as gdb's PC_REGNUM, then this - implies a copy from the ra column register. */ if (fs->retaddr_column < fs->regs.num_regs - && fs->regs.reg[fs->retaddr_column].how != REG_UNDEFINED) - { - /* See comment above about a possibly -ve PC_REGNUM. If this - assertion fails, it's a problem with this code and not the - architecture. */ - gdb_assert (PC_REGNUM >= 0); - cache->reg[PC_REGNUM] = fs->regs.reg[fs->retaddr_column]; - } - else - { - int reg = DWARF2_REG_TO_REGNUM (fs->retaddr_column); - if (reg != PC_REGNUM) - { - /* See comment above about PC_REGNUM being -ve. If this - assertion fails, it's a problem with this code and not - the architecture. */ - gdb_assert (PC_REGNUM >= 0); - cache->reg[PC_REGNUM].loc.reg = reg; - cache->reg[PC_REGNUM].how = REG_SAVED_REG; - } - } + && fs->regs.reg[fs->retaddr_column].how == DWARF2_FRAME_REG_UNDEFINED) + cache->undefined_retaddr = 1; do_cleanups (old_chain); @@ -638,112 +1060,61 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) } static void -dwarf2_frame_this_id (struct frame_info *next_frame, void **this_cache, +dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) { struct dwarf2_frame_cache *cache = - dwarf2_frame_cache (next_frame, this_cache); + dwarf2_frame_cache (this_frame, this_cache); + + if (cache->undefined_retaddr) + return; - (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame)); + (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame)); } -static void -dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *valuep) +static struct value * +dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, + int regnum) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); struct dwarf2_frame_cache *cache = - dwarf2_frame_cache (next_frame, this_cache); + dwarf2_frame_cache (this_frame, this_cache); + CORE_ADDR addr; + int realnum; switch (cache->reg[regnum].how) { - case REG_UNDEFINED: + case DWARF2_FRAME_REG_UNDEFINED: /* If CFI explicitly specified that the value isn't defined, - mark it as optimized away - the value isn't available. */ - *optimizedp = 1; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (regnum == SP_REGNUM) - { - /* GCC defines the CFA as the value of the stack pointer - just before the call instruction is executed. Do other - compilers use the same definition? */ - /* DWARF V3 Draft 7 p102: Typically, the CFA is defined to - be the value of the stack pointer at the call site in the - previous frame (which may be different from its value on - entry to the current frame). */ - /* DWARF V3 Draft 7 p103: The first column of the rules - defines the rule which computes the CFA value; it may be - either a register and a signed offset that are added - together or a DWARF expression that is evaluated. */ - /* FIXME: cagney/2003-07-07: I don't understand this. The - CFI info should have provided unwind information for the - SP register and then pointed ->cfa_reg at it, not the - reverse. Assuming that SP_REGNUM is !-ve, there is a - very real posibility that CFA is an offset from some - other register, having nothing to do with the unwound SP - value. */ - /* FIXME: cagney/2003-09-05: I think I understand. GDB was - lumping the two states "unspecified" and "undefined" - together. Here SP_REGNUM was "unspecified", GCC assuming - that in such a case CFA would be used. This branch of - the if statement should be deleted - the problem of - SP_REGNUM is now handed by the case REG_UNSPECIFIED - below. */ - *optimizedp = 0; - if (valuep) - { - /* Store the value. */ - store_typed_address (valuep, builtin_type_void_data_ptr, - cache->cfa); - } - } - else if (valuep) - { - /* In some cases, for example %eflags on the i386, we have - to provide a sane value, even though this register wasn't - saved. Assume we can get it from NEXT_FRAME. */ - frame_unwind_register (next_frame, regnum, valuep); - } - break; - - case REG_SAVED_OFFSET: - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = cache->cfa + cache->reg[regnum].loc.offset; - *realnump = -1; - if (valuep) - { - /* Read the value in from memory. */ - read_memory (*addrp, valuep, - register_size (current_gdbarch, regnum)); - } - break; - - case REG_SAVED_REG: - regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg); - frame_register_unwind (next_frame, regnum, - optimizedp, lvalp, addrp, realnump, valuep); - break; - - case REG_SAVED_EXP: - *optimizedp = 0; - *lvalp = lval_memory; - *addrp = execute_stack_op (cache->reg[regnum].loc.exp, - cache->reg[regnum].exp_len, - next_frame, cache->cfa); - *realnump = -1; - if (valuep) - { - /* Read the value in from memory. */ - read_memory (*addrp, valuep, - register_size (current_gdbarch, regnum)); - } - break; - - case REG_UNSPECIFIED: + mark it as optimized away; the value isn't available. */ + return frame_unwind_got_optimized (this_frame, regnum); + + case DWARF2_FRAME_REG_SAVED_OFFSET: + addr = cache->cfa + cache->reg[regnum].loc.offset; + return frame_unwind_got_memory (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_SAVED_REG: + realnum + = gdbarch_dwarf2_reg_to_regnum (gdbarch, cache->reg[regnum].loc.reg); + return frame_unwind_got_register (this_frame, regnum, realnum); + + case DWARF2_FRAME_REG_SAVED_EXP: + addr = execute_stack_op (cache->reg[regnum].loc.exp, + cache->reg[regnum].exp_len, + cache->addr_size, this_frame, cache->cfa); + return frame_unwind_got_memory (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: + addr = cache->cfa + cache->reg[regnum].loc.offset; + return frame_unwind_got_constant (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_SAVED_VAL_EXP: + addr = execute_stack_op (cache->reg[regnum].loc.exp, + cache->reg[regnum].exp_len, + cache->addr_size, this_frame, cache->cfa); + return frame_unwind_got_constant (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_UNSPECIFIED: /* GCC, in its infinite wisdom decided to not provide unwind information for registers that are "same value". Since DWARF2 (3 draft 7) doesn't define such behavior, said @@ -751,78 +1122,86 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, "undefined"). Code above issues a complaint about this. Here just fudge the books, assume GCC, and that the value is more inner on the stack. */ - if (SP_REGNUM >= 0 && regnum == SP_REGNUM) - { - /* Can things get worse? Yep! One of the registers GCC - forgot to provide unwind information for was the stack - pointer. Outch! GCC appears to assumes that the CFA - address can be used - after all it points to the inner - most address of the previous frame before the function - call and that's always the same as the stack pointer on - return, right? Wrong. See GCC's i386 STDCALL option for - an ABI that has a different entry and return stack - pointer. */ - /* DWARF V3 Draft 7 p102: Typically, the CFA is defined to - be the value of the stack pointer at the call site in the - previous frame (which may be different from its value on - entry to the current frame). */ - /* DWARF V3 Draft 7 p103: The first column of the rules - defines the rule which computes the CFA value; it may be - either a register and a signed offset that are added - together or a DWARF expression that is evaluated. */ - /* NOTE: cagney/2003-09-05: Should issue a complain. - Unfortunately it turns out that DWARF2 CFI has a problem. - Since CFI specifies the location at which a register was - saved (not its value) it isn't possible to specify - something like "unwound(REG) == REG + constant" using CFI - as will almost always occure with the stack pointer. I - guess CFI should be point SP at CFA. Ref: danielj, - "Describing unsaved stack pointers", posted to dwarf2 - list 2003-08-15. */ - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (valuep) - /* Store the value. */ - store_typed_address (valuep, builtin_type_void_data_ptr, - cache->cfa); - } - else - /* Assume that the register can be found in the next inner - most frame. */ - frame_register_unwind (next_frame, regnum, - optimizedp, lvalp, addrp, realnump, valuep); - break; + return frame_unwind_got_register (this_frame, regnum, regnum); - case REG_SAME_VALUE: - frame_register_unwind (next_frame, regnum, - optimizedp, lvalp, addrp, realnump, valuep); - break; + case DWARF2_FRAME_REG_SAME_VALUE: + return frame_unwind_got_register (this_frame, regnum, regnum); + + case DWARF2_FRAME_REG_CFA: + return frame_unwind_got_address (this_frame, regnum, cache->cfa); + + case DWARF2_FRAME_REG_CFA_OFFSET: + addr = cache->cfa + cache->reg[regnum].loc.offset; + return frame_unwind_got_address (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_RA_OFFSET: + addr = cache->reg[regnum].loc.offset; + regnum = gdbarch_dwarf2_reg_to_regnum + (gdbarch, cache->retaddr_reg.loc.reg); + addr += get_frame_register_unsigned (this_frame, regnum); + return frame_unwind_got_address (this_frame, regnum, addr); + + case DWARF2_FRAME_REG_FN: + return cache->reg[regnum].loc.fn (this_frame, this_cache, regnum); default: - internal_error (__FILE__, __LINE__, "Unknown register rule."); + internal_error (__FILE__, __LINE__, _("Unknown register rule.")); } } +static int +dwarf2_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, void **this_cache) +{ + /* Grab an address that is guarenteed to reside somewhere within the + function. get_frame_pc(), with a no-return next function, can + end up returning something past the end of this function's body. + If the frame we're sniffing for is a signal frame whose start + address is placed on the stack by the OS, its FDE must + extend one byte before its start address or we could potentially + select the FDE of the previous function. */ + CORE_ADDR block_addr = get_frame_address_in_block (this_frame); + struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); + if (!fde) + return 0; + + /* On some targets, signal trampolines may have unwind information. + We need to recognize them so that we set the frame type + correctly. */ + + if (fde->cie->signal_frame + || dwarf2_frame_signal_frame_p (get_frame_arch (this_frame), + this_frame)) + return self->type == SIGTRAMP_FRAME; + + return self->type != SIGTRAMP_FRAME; +} + static const struct frame_unwind dwarf2_frame_unwind = { NORMAL_FRAME, dwarf2_frame_this_id, - dwarf2_frame_prev_register + dwarf2_frame_prev_register, + NULL, + dwarf2_frame_sniffer }; -const struct frame_unwind * -dwarf2_frame_sniffer (struct frame_info *next_frame) +static const struct frame_unwind dwarf2_signal_frame_unwind = { - /* Grab an address that is guarenteed to reside somewhere within the - function. frame_pc_unwind(), for a no-return next function, can - end up returning something past the end of this function's body. */ - CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame); - if (dwarf2_frame_find_fde (&block_addr)) - return &dwarf2_frame_unwind; + SIGTRAMP_FRAME, + dwarf2_frame_this_id, + dwarf2_frame_prev_register, + NULL, + dwarf2_frame_sniffer +}; - return NULL; +/* Append the DWARF-2 frame unwinders to GDBARCH's list. */ + +void +dwarf2_append_unwinders (struct gdbarch *gdbarch) +{ + frame_unwind_append_unwinder (gdbarch, &dwarf2_frame_unwind); + frame_unwind_append_unwinder (gdbarch, &dwarf2_signal_frame_unwind); } @@ -833,10 +1212,10 @@ dwarf2_frame_sniffer (struct frame_info *next_frame) response to the "info frame" command. */ static CORE_ADDR -dwarf2_frame_base_address (struct frame_info *next_frame, void **this_cache) +dwarf2_frame_base_address (struct frame_info *this_frame, void **this_cache) { struct dwarf2_frame_cache *cache = - dwarf2_frame_cache (next_frame, this_cache); + dwarf2_frame_cache (this_frame, this_cache); return cache->cfa; } @@ -850,74 +1229,42 @@ static const struct frame_base dwarf2_frame_base = }; const struct frame_base * -dwarf2_frame_base_sniffer (struct frame_info *next_frame) +dwarf2_frame_base_sniffer (struct frame_info *this_frame) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - if (dwarf2_frame_find_fde (&pc)) + CORE_ADDR block_addr = get_frame_address_in_block (this_frame); + if (dwarf2_frame_find_fde (&block_addr)) return &dwarf2_frame_base; return NULL; } -/* A minimal decoding of DWARF2 compilation units. We only decode - what's needed to get to the call frame information. */ - -struct comp_unit -{ - /* Keep the bfd convenient. */ - bfd *abfd; - - struct objfile *objfile; - - /* Linked list of CIEs for this object. */ - struct dwarf2_cie *cie; - - /* Address size for this unit - from unit header. */ - unsigned char addr_size; - - /* Pointer to the .debug_frame section loaded into memory. */ - char *dwarf_frame_buffer; - - /* Length of the loaded .debug_frame section. */ - unsigned long dwarf_frame_size; - - /* Pointer to the .debug_frame section. */ - asection *dwarf_frame_section; - - /* Base for DW_EH_PE_datarel encodings. */ - bfd_vma dbase; - - /* Base for DW_EH_PE_textrel encodings. */ - bfd_vma tbase; -}; - -const struct objfile_data *dwarf2_frame_data; +const struct objfile_data *dwarf2_frame_objfile_data; static unsigned int -read_1_byte (bfd *bfd, char *buf) +read_1_byte (bfd *abfd, gdb_byte *buf) { - return bfd_get_8 (abfd, (bfd_byte *) buf); + return bfd_get_8 (abfd, buf); } static unsigned int -read_4_bytes (bfd *abfd, char *buf) +read_4_bytes (bfd *abfd, gdb_byte *buf) { - return bfd_get_32 (abfd, (bfd_byte *) buf); + return bfd_get_32 (abfd, buf); } static ULONGEST -read_8_bytes (bfd *abfd, char *buf) +read_8_bytes (bfd *abfd, gdb_byte *buf) { - return bfd_get_64 (abfd, (bfd_byte *) buf); + return bfd_get_64 (abfd, buf); } static ULONGEST -read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) { ULONGEST result; unsigned int num_read; int shift; - unsigned char byte; + gdb_byte byte; result = 0; shift = 0; @@ -939,12 +1286,12 @@ read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) } static LONGEST -read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) { LONGEST result; int shift; unsigned int num_read; - unsigned char byte; + gdb_byte byte; result = 0; shift = 0; @@ -960,8 +1307,8 @@ read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) } while (byte & 0x80); - if ((shift < 32) && (byte & 0x40)) - result |= -(1 << shift); + if (shift < 8 * sizeof (result) && (byte & 0x40)) + result |= -(((LONGEST)1) << shift); *bytes_read_ptr = num_read; @@ -969,14 +1316,14 @@ read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) } static ULONGEST -read_initial_length (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) +read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) { LONGEST result; - result = bfd_get_32 (abfd, (bfd_byte *) buf); + result = bfd_get_32 (abfd, buf); if (result == 0xffffffff) { - result = bfd_get_64 (abfd, (bfd_byte *) buf + 4); + result = bfd_get_64 (abfd, buf + 4); *bytes_read_ptr = 12; } else @@ -1002,7 +1349,7 @@ read_initial_length (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) position in the FDE, ...). Bit 7, indicates that the address should be dereferenced. */ -static unsigned char +static gdb_byte encoding_for_size (unsigned int size) { switch (size) @@ -1014,36 +1361,15 @@ encoding_for_size (unsigned int size) case 8: return DW_EH_PE_udata8; default: - internal_error (__FILE__, __LINE__, "Unsupported address size"); - } -} - -static unsigned int -size_of_encoded_value (unsigned char encoding) -{ - if (encoding == DW_EH_PE_omit) - return 0; - - switch (encoding & 0x07) - { - case DW_EH_PE_absptr: - return TYPE_LENGTH (builtin_type_void_data_ptr); - case DW_EH_PE_udata2: - return 2; - case DW_EH_PE_udata4: - return 4; - case DW_EH_PE_udata8: - return 8; - default: - internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding"); + internal_error (__FILE__, __LINE__, _("Unsupported address size")); } } static CORE_ADDR -read_encoded_value (struct comp_unit *unit, unsigned char encoding, - char *buf, unsigned int *bytes_read_ptr) +read_encoded_value (struct comp_unit *unit, gdb_byte encoding, + int ptr_len, gdb_byte *buf, unsigned int *bytes_read_ptr, + CORE_ADDR func_base) { - int ptr_len = size_of_encoded_value (DW_EH_PE_absptr); ptrdiff_t offset; CORE_ADDR base; @@ -1051,7 +1377,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, FDE's. */ if (encoding & DW_EH_PE_indirect) internal_error (__FILE__, __LINE__, - "Unsupported encoding: DW_EH_PE_indirect"); + _("Unsupported encoding: DW_EH_PE_indirect")); *bytes_read_ptr = 0; @@ -1061,7 +1387,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, base = 0; break; case DW_EH_PE_pcrel: - base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section); + base = bfd_get_section_vma (unit->abfd, unit->dwarf_frame_section); base += (buf - unit->dwarf_frame_buffer); break; case DW_EH_PE_datarel: @@ -1070,6 +1396,9 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, case DW_EH_PE_textrel: base = unit->tbase; break; + case DW_EH_PE_funcrel: + base = func_base; + break; case DW_EH_PE_aligned: base = 0; offset = buf - unit->dwarf_frame_buffer; @@ -1080,14 +1409,25 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, } break; default: - internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding"); + internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding")); } - if ((encoding & 0x0f) == 0x00) - encoding |= encoding_for_size (ptr_len); + if ((encoding & 0x07) == 0x00) + { + encoding |= encoding_for_size (ptr_len); + if (bfd_get_sign_extend_vma (unit->abfd)) + encoding |= DW_EH_PE_signed; + } switch (encoding & 0x0f) { + case DW_EH_PE_uleb128: + { + ULONGEST value; + gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7; + *bytes_read_ptr += read_uleb128 (buf, end_buf, &value) - buf; + return base + value; + } case DW_EH_PE_udata2: *bytes_read_ptr += 2; return (base + bfd_get_16 (unit->abfd, (bfd_byte *) buf)); @@ -1097,6 +1437,13 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, case DW_EH_PE_udata8: *bytes_read_ptr += 8; return (base + bfd_get_64 (unit->abfd, (bfd_byte *) buf)); + case DW_EH_PE_sleb128: + { + LONGEST value; + gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7; + *bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf; + return base + value; + } case DW_EH_PE_sdata2: *bytes_read_ptr += 2; return (base + bfd_get_signed_16 (unit->abfd, (bfd_byte *) buf)); @@ -1107,7 +1454,7 @@ read_encoded_value (struct comp_unit *unit, unsigned char encoding, *bytes_read_ptr += 8; return (base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf)); default: - internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding"); + internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding")); } } @@ -1136,6 +1483,7 @@ add_cie (struct comp_unit *unit, struct dwarf2_cie *cie) { cie->next = unit->cie; unit->cie = cie; + cie->unit = unit; } /* Find the FDE for *PC. Return a pointer to the FDE, and store the @@ -1151,7 +1499,7 @@ dwarf2_frame_find_fde (CORE_ADDR *pc) struct dwarf2_fde *fde; CORE_ADDR offset; - fde = objfile_data (objfile, dwarf2_frame_data); + fde = objfile_data (objfile, dwarf2_frame_objfile_data); if (fde == NULL) continue; @@ -1177,8 +1525,8 @@ dwarf2_frame_find_fde (CORE_ADDR *pc) static void add_fde (struct comp_unit *unit, struct dwarf2_fde *fde) { - fde->next = objfile_data (unit->objfile, dwarf2_frame_data); - set_objfile_data (unit->objfile, dwarf2_frame_data, fde); + fde->next = objfile_data (unit->objfile, dwarf2_frame_objfile_data); + set_objfile_data (unit->objfile, dwarf2_frame_objfile_data, fde); } #ifdef CC_HAS_LONG_LONG @@ -1187,21 +1535,21 @@ add_fde (struct comp_unit *unit, struct dwarf2_fde *fde) #define DW64_CIE_ID ~0 #endif -static char *decode_frame_entry (struct comp_unit *unit, char *start, - int eh_frame_p); +static gdb_byte *decode_frame_entry (struct comp_unit *unit, gdb_byte *start, + int eh_frame_p); /* Decode the next CIE or FDE. Return NULL if invalid input, otherwise the next byte to be processed. */ -static char * -decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) +static gdb_byte * +decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) { - char *buf; + struct gdbarch *gdbarch = get_objfile_arch (unit->objfile); + gdb_byte *buf, *end; LONGEST length; unsigned int bytes_read; int dwarf64_p; ULONGEST cie_id; ULONGEST cie_pointer; - char *end; buf = start; length = read_initial_length (unit->abfd, buf, &bytes_read); @@ -1242,6 +1590,7 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) /* This is a CIE. */ struct dwarf2_cie *cie; char *augmentation; + unsigned int cie_version; /* Record the offset into the .debug_frame section of this CIE. */ cie_pointer = start - unit->dwarf_frame_buffer; @@ -1251,24 +1600,41 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) return end; cie = (struct dwarf2_cie *) - obstack_alloc (&unit->objfile->psymbol_obstack, + obstack_alloc (&unit->objfile->objfile_obstack, sizeof (struct dwarf2_cie)); cie->initial_instructions = NULL; cie->cie_pointer = cie_pointer; /* The encoding for FDE's in a normal .debug_frame section - depends on the target address size as specified in the - Compilation Unit Header. */ - cie->encoding = encoding_for_size (unit->addr_size); + depends on the target address size. */ + cie->encoding = DW_EH_PE_absptr; + + /* The target address size. For .eh_frame FDEs this is considered + equal to the size of a target pointer. For .dwarf_frame FDEs, + this is supposed to be the target address size from the associated + CU header. FIXME: We do not have a good way to determine the + latter. Always use the target pointer size for now. */ + cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + + /* We'll determine the final value later, but we need to + initialize it conservatively. */ + cie->signal_frame = 0; /* Check version number. */ - if (read_1_byte (unit->abfd, buf) != DW_CIE_VERSION) + cie_version = read_1_byte (unit->abfd, buf); + if (cie_version != 1 && cie_version != 3) return NULL; + cie->version = cie_version; buf += 1; /* Interpret the interesting bits of the augmentation. */ - augmentation = buf; - buf = augmentation + strlen (augmentation) + 1; + cie->augmentation = augmentation = (char *) buf; + buf += (strlen (augmentation) + 1); + + /* Ignore armcc augmentations. We only use them for quirks, + and that doesn't happen until later. */ + if (strncmp (augmentation, "armcc", 5) == 0) + augmentation += strlen (augmentation); /* The GCC 2.x "eh" augmentation has a pointer immediately following the augmentation string, so it must be handled @@ -1276,7 +1642,7 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) if (augmentation[0] == 'e' && augmentation[1] == 'h') { /* Skip. */ - buf += TYPE_LENGTH (builtin_type_void_data_ptr); + buf += gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; augmentation += 2; } @@ -1288,8 +1654,20 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) read_signed_leb128 (unit->abfd, buf, &bytes_read); buf += bytes_read; - cie->return_address_register = read_1_byte (unit->abfd, buf); - buf += 1; + if (cie_version == 1) + { + cie->return_address_register = read_1_byte (unit->abfd, buf); + bytes_read = 1; + } + else + cie->return_address_register = read_unsigned_leb128 (unit->abfd, buf, + &bytes_read); + cie->return_address_register + = dwarf2_frame_adjust_regnum (gdbarch, + cie->return_address_register, + eh_frame_p); + + buf += bytes_read; cie->saw_z_augmentation = (*augmentation == 'z'); if (cie->saw_z_augmentation) @@ -1324,20 +1702,31 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) /* "P" indicates a personality routine in the CIE augmentation. */ else if (*augmentation == 'P') { - /* Skip. */ - buf += size_of_encoded_value (*buf++); + /* Skip. Avoid indirection since we throw away the result. */ + gdb_byte encoding = (*buf++) & ~DW_EH_PE_indirect; + read_encoded_value (unit, encoding, cie->addr_size, + buf, &bytes_read, 0); + buf += bytes_read; augmentation++; } - /* Otherwise we have an unknown augmentation. - Bail out unless we saw a 'z' prefix. */ - else + /* "S" indicates a signal frame, such that the return + address must not be decremented to locate the call frame + info for the previous frame; it might even be the first + instruction of a function, so decrementing it would take + us to a different function. */ + else if (*augmentation == 'S') { - if (cie->initial_instructions == NULL) - return end; + cie->signal_frame = 1; + augmentation++; + } - /* Skip unknown augmentations. */ - buf = cie->initial_instructions; + /* Otherwise we have an unknown augmentation. Assume that either + there is no augmentation data, or we saw a 'z' prefix. */ + else + { + if (cie->initial_instructions) + buf = cie->initial_instructions; break; } } @@ -1367,7 +1756,7 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) return NULL; fde = (struct dwarf2_fde *) - obstack_alloc (&unit->objfile->psymbol_obstack, + obstack_alloc (&unit->objfile->objfile_obstack, sizeof (struct dwarf2_fde)); fde->cie = find_cie (unit, cie_pointer); if (fde->cie == NULL) @@ -1380,11 +1769,13 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) gdb_assert (fde->cie != NULL); fde->initial_location = - read_encoded_value (unit, fde->cie->encoding, buf, &bytes_read); + read_encoded_value (unit, fde->cie->encoding, fde->cie->addr_size, + buf, &bytes_read, 0); buf += bytes_read; fde->address_range = - read_encoded_value (unit, fde->cie->encoding & 0x0f, buf, &bytes_read); + read_encoded_value (unit, fde->cie->encoding & 0x0f, + fde->cie->addr_size, buf, &bytes_read, 0); buf += bytes_read; /* A 'z' augmentation in the CIE implies the presence of an @@ -1404,6 +1795,8 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) fde->instructions = buf; fde->end = end; + fde->eh_frame_p = eh_frame_p; + add_fde (unit, fde); } @@ -1411,11 +1804,11 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p) } /* Read a CIE or FDE in BUF and decode it. */ -static char * -decode_frame_entry (struct comp_unit *unit, char *start, int eh_frame_p) +static gdb_byte * +decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) { enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE; - char *ret; + gdb_byte *ret; const char *msg; ptrdiff_t start_offset; @@ -1479,21 +1872,21 @@ decode_frame_entry (struct comp_unit *unit, char *start, int eh_frame_p) case ALIGN4: complaint (&symfile_complaints, - "Corrupt data in %s:%s; align 4 workaround apparently succeeded", + _("Corrupt data in %s:%s; align 4 workaround apparently succeeded"), unit->dwarf_frame_section->owner->filename, unit->dwarf_frame_section->name); break; case ALIGN8: complaint (&symfile_complaints, - "Corrupt data in %s:%s; align 8 workaround apparently succeeded", + _("Corrupt data in %s:%s; align 8 workaround apparently succeeded"), unit->dwarf_frame_section->owner->filename, unit->dwarf_frame_section->name); break; default: complaint (&symfile_complaints, - "Corrupt data in %s:%s", + _("Corrupt data in %s:%s"), unit->dwarf_frame_section->owner->filename, unit->dwarf_frame_section->name); break; @@ -1501,83 +1894,75 @@ decode_frame_entry (struct comp_unit *unit, char *start, int eh_frame_p) return ret; } - /* FIXME: kettenis/20030504: This still needs to be integrated with dwarf2read.c in a better way. */ /* Imported from dwarf2read.c. */ -extern file_ptr dwarf_frame_offset; -extern unsigned int dwarf_frame_size; extern asection *dwarf_frame_section; -extern file_ptr dwarf_eh_frame_offset; -extern unsigned int dwarf_eh_frame_size; extern asection *dwarf_eh_frame_section; /* Imported from dwarf2read.c. */ -extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset, - unsigned int size, asection *sectp); +extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp); void dwarf2_build_frame_info (struct objfile *objfile) { - struct comp_unit unit; - char *frame_ptr; + struct comp_unit *unit; + gdb_byte *frame_ptr; /* Build a minimal decoding of the DWARF2 compilation unit. */ - unit.abfd = objfile->obfd; - unit.objfile = objfile; - unit.addr_size = objfile->obfd->arch_info->bits_per_address / 8; - unit.dbase = 0; - unit.tbase = 0; + unit = (struct comp_unit *) obstack_alloc (&objfile->objfile_obstack, + sizeof (struct comp_unit)); + unit->abfd = objfile->obfd; + unit->objfile = objfile; + unit->dbase = 0; + unit->tbase = 0; /* First add the information from the .eh_frame section. That way, the FDEs from that section are searched last. */ - if (dwarf_eh_frame_offset) + if (dwarf_eh_frame_section) { asection *got, *txt; - unit.cie = NULL; - unit.dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_offset, - dwarf_eh_frame_size, - dwarf_eh_frame_section); + unit->cie = NULL; + unit->dwarf_frame_buffer = dwarf2_read_section (objfile, + dwarf_eh_frame_section); - unit.dwarf_frame_size = dwarf_eh_frame_size; - unit.dwarf_frame_section = dwarf_eh_frame_section; + unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); + unit->dwarf_frame_section = dwarf_eh_frame_section; /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the DW_EH_PE_datarel encoding. */ - got = bfd_get_section_by_name (unit.abfd, ".got"); + got = bfd_get_section_by_name (unit->abfd, ".got"); if (got) - unit.dbase = got->vma; + unit->dbase = got->vma; - /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 so far. */ - txt = bfd_get_section_by_name (unit.abfd, ".text"); + /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 + so far. */ + txt = bfd_get_section_by_name (unit->abfd, ".text"); if (txt) - unit.tbase = txt->vma; + unit->tbase = txt->vma; - frame_ptr = unit.dwarf_frame_buffer; - while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size) - frame_ptr = decode_frame_entry (&unit, frame_ptr, 1); + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 1); } - if (dwarf_frame_offset) + if (dwarf_frame_section) { - unit.cie = NULL; - unit.dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_offset, - dwarf_frame_size, - dwarf_frame_section); - unit.dwarf_frame_size = dwarf_frame_size; - unit.dwarf_frame_section = dwarf_frame_section; - - frame_ptr = unit.dwarf_frame_buffer; - while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size) - frame_ptr = decode_frame_entry (&unit, frame_ptr, 0); + unit->cie = NULL; + unit->dwarf_frame_buffer = dwarf2_read_section (objfile, + dwarf_frame_section); + unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); + unit->dwarf_frame_section = dwarf_frame_section; + + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 0); } } @@ -1587,5 +1972,6 @@ void _initialize_dwarf2_frame (void); void _initialize_dwarf2_frame (void) { - dwarf2_frame_data = register_objfile_data (); + dwarf2_frame_data = gdbarch_data_register_pre_init (dwarf2_frame_init); + dwarf2_frame_objfile_data = register_objfile_data (); }