/* Frame unwinder for frames with DWARF Call Frame Information.
- Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Mark Kettenis.
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "dwarf2expr.h"
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;
/* Encoding of addresses. */
- unsigned char encoding;
+ gdb_byte encoding;
/* True if a 'z' augmentation existed. */
unsigned char saw_z_augmentation;
CORE_ADDR address_range;
/* Instruction sequence. */
- unsigned char *instructions;
- unsigned char *end;
+ gdb_byte *instructions;
+ gdb_byte *end;
struct dwarf2_fde *next;
};
LONGEST cfa_offset;
ULONGEST cfa_reg;
- unsigned char *cfa_exp;
+ gdb_byte *cfa_exp;
enum {
CFA_UNSET,
CFA_REG_OFFSET,
struct frame_info *next_frame = (struct frame_info *) baton;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
int regnum;
- char *buf;
+ gdb_byte *buf;
regnum = DWARF2_REG_TO_REGNUM (reg);
- buf = (char *) alloca (register_size (gdbarch, regnum));
+ buf = alloca (register_size (gdbarch, regnum));
frame_unwind_register (next_frame, regnum, buf);
return extract_typed_address (buf, builtin_type_void_data_ptr);
}
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"));
}
static CORE_ADDR
-execute_stack_op (unsigned char *exp, ULONGEST len,
+execute_stack_op (gdb_byte *exp, ULONGEST len,
struct frame_info *next_frame, CORE_ADDR initial)
{
struct dwarf_expr_context *ctx;
\f
static void
-execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
+execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end,
struct frame_info *next_frame,
struct dwarf2_frame_state *fs)
{
while (insn_ptr < insn_end && fs->pc <= pc)
{
- unsigned char insn = *insn_ptr++;
+ gdb_byte insn = *insn_ptr++;
ULONGEST utmp, reg;
LONGEST offset;
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];
+ 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"),
+ REGISTER_NAME(DWARF2_REG_TO_REGNUM(reg)),
+ DWARF2_REG_TO_REGNUM(reg), paddr (fs->pc));
}
else
{
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);
+ fs->cfa_offset = utmp;
/* cfa_how deliberately not set. */
break;
struct dwarf2_frame_ops
{
/* Pre-initialize the register state REG for register REGNUM. */
- void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *);
+ void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *,
+ struct frame_info *);
/* Check whether the frame preceding NEXT_FRAME will be a signal
trampoline. */
static void
dwarf2_frame_default_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg)
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *next_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
void
dwarf2_frame_set_init_reg (struct gdbarch *gdbarch,
void (*init_reg) (struct gdbarch *, int,
- struct dwarf2_frame_state_reg *))
+ struct dwarf2_frame_state_reg *,
+ struct frame_info *))
{
struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
static void
dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg)
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *next_frame)
{
struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
- ops->init_reg (gdbarch, regnum, reg);
+ ops->init_reg (gdbarch, regnum, reg, next_frame);
}
/* Set the architecture-specific signal trampoline recognition
int regnum;
for (regnum = 0; regnum < num_regs; regnum++)
- dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum]);
+ dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum], next_frame);
}
/* Go through the DWARF2 CFI generated table and save its register
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)
+ int *realnump, gdb_byte *valuep)
{
struct gdbarch *gdbarch = get_frame_arch (next_frame);
struct dwarf2_frame_cache *cache =
}
break;
+ case DWARF2_FRAME_REG_CFA_OFFSET:
+ *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 + cache->reg[regnum].loc.offset);
+ }
+ break;
+
case DWARF2_FRAME_REG_RA_OFFSET:
*optimizedp = 0;
*lvalp = not_lval;
struct dwarf2_cie *cie;
/* Pointer to the .debug_frame section loaded into memory. */
- char *dwarf_frame_buffer;
+ gdb_byte *dwarf_frame_buffer;
/* Length of the loaded .debug_frame section. */
unsigned long dwarf_frame_size;
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;
}
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;
}
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;
}
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
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)
}
static unsigned int
-size_of_encoded_value (unsigned char encoding)
+size_of_encoded_value (gdb_byte encoding)
{
if (encoding == DW_EH_PE_omit)
return 0;
}
static CORE_ADDR
-read_encoded_value (struct comp_unit *unit, unsigned char encoding,
- unsigned char *buf, unsigned int *bytes_read_ptr)
+read_encoded_value (struct comp_unit *unit, gdb_byte encoding,
+ gdb_byte *buf, unsigned int *bytes_read_ptr)
{
int ptr_len = size_of_encoded_value (DW_EH_PE_absptr);
ptrdiff_t offset;
break;
case DW_EH_PE_pcrel:
base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
- base += ((char *) buf - unit->dwarf_frame_buffer);
+ base += (buf - unit->dwarf_frame_buffer);
break;
case DW_EH_PE_datarel:
base = unit->dbase;
break;
case DW_EH_PE_aligned:
base = 0;
- offset = (char *) buf - unit->dwarf_frame_buffer;
+ offset = buf - unit->dwarf_frame_buffer;
if ((offset % ptr_len) != 0)
{
*bytes_read_ptr = ptr_len - (offset % ptr_len);
case DW_EH_PE_uleb128:
{
ULONGEST value;
- unsigned char *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+ 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_sleb128:
{
LONGEST value;
- char *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
+ gdb_byte *end_buf = buf + (sizeof (value) + 1) * 8 / 7;
*bytes_read_ptr += read_sleb128 (buf, end_buf, &value) - buf;
return base + value;
}
#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;
+ 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);
buf += 1;
/* Interpret the interesting bits of the augmentation. */
- augmentation = buf;
- buf = augmentation + strlen (augmentation) + 1;
+ augmentation = (char *) buf;
+ buf += (strlen (augmentation) + 1);
/* The GCC 2.x "eh" augmentation has a pointer immediately
following the augmentation string, so it must be handled
else if (*augmentation == 'P')
{
/* Skip. Avoid indirection since we throw away the result. */
- unsigned char encoding = (*buf++) & ~DW_EH_PE_indirect;
+ gdb_byte encoding = (*buf++) & ~DW_EH_PE_indirect;
read_encoded_value (unit, encoding, buf, &bytes_read);
buf += bytes_read;
augmentation++;
}
/* 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;
extern asection *dwarf_eh_frame_section;
/* Imported from dwarf2read.c. */
-extern char *dwarf2_read_section (struct objfile *objfile, 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;
+ gdb_byte *frame_ptr;
/* Build a minimal decoding of the DWARF2 compilation unit. */
unit.abfd = objfile->obfd;