Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include "gdbcore.h"
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "inferior.h"
#include "regcache.h"
#include "dwarf2cfi.h"
+#include "gdb_assert.h"
/* Common Information Entry - holds information that is shared among many
Frame Descriptors. */
int array_size;
};
-struct context_reg
-{
- union
- {
- unsigned int reg;
- long offset;
- CORE_ADDR addr;
- }
- loc;
- enum
- {
- REG_CTX_UNSAVED,
- REG_CTX_SAVED_OFFSET,
- REG_CTX_SAVED_REG,
- REG_CTX_SAVED_ADDR,
- REG_CTX_VALUE,
- }
- how;
-};
-
-/* This is the register and unwind state for a particular frame. */
-struct context
-{
- struct context_reg *reg;
-
- CORE_ADDR cfa;
- CORE_ADDR ra;
- void *lsda;
- int args_size;
-};
-
struct frame_state_reg
{
union
struct objfile *objfile;
};
-enum ptr_encoding {
+enum ptr_encoding
+{
PE_absptr = DW_EH_PE_absptr,
PE_pcrel = DW_EH_PE_pcrel,
PE_textrel = DW_EH_PE_textrel,
static struct cie_unit *cie_unit_alloc (void);
static void fde_chunks_need_space ();
-static struct context *context_alloc ();
-static struct frame_state *frame_state_alloc ();
static void unwind_tmp_obstack_init ();
static void unwind_tmp_obstack_free ();
-static void context_cpy (struct context *dst, struct context *src);
-
-static unsigned int read_1u (bfd * abfd, char **p);
-static int read_1s (bfd * abfd, char **p);
-static unsigned int read_2u (bfd * abfd, char **p);
-static int read_2s (bfd * abfd, char **p);
-static unsigned int read_4u (bfd * abfd, char **p);
-static int read_4s (bfd * abfd, char **p);
-static ULONGEST read_8u (bfd * abfd, char **p);
-static LONGEST read_8s (bfd * abfd, char **p);
-
-static ULONGEST read_uleb128 (bfd * abfd, char **p);
-static LONGEST read_sleb128 (bfd * abfd, char **p);
-static CORE_ADDR read_pointer (bfd * abfd, char **p);
-static CORE_ADDR read_encoded_pointer (bfd * abfd, char **p,
+
+static unsigned int read_1u (bfd *abfd, char **p);
+static int read_1s (bfd *abfd, char **p);
+static unsigned int read_2u (bfd *abfd, char **p);
+static int read_2s (bfd *abfd, char **p);
+static unsigned int read_4u (bfd *abfd, char **p);
+static int read_4s (bfd *abfd, char **p);
+static ULONGEST read_8u (bfd *abfd, char **p);
+static LONGEST read_8s (bfd *abfd, char **p);
+
+static ULONGEST read_uleb128 (bfd *abfd, char **p);
+static LONGEST read_sleb128 (bfd *abfd, char **p);
+static CORE_ADDR read_pointer (bfd *abfd, char **p);
+static CORE_ADDR read_encoded_pointer (bfd *abfd, char **p,
unsigned char encoding);
static enum ptr_encoding pointer_encoding (unsigned char encoding);
-static LONGEST read_initial_length (bfd * abfd, char *buf, int *bytes_read);
-static ULONGEST read_length (bfd * abfd, char *buf, int *bytes_read,
+static LONGEST read_initial_length (bfd *abfd, char *buf, int *bytes_read);
+static ULONGEST read_length (bfd *abfd, char *buf, int *bytes_read,
int dwarf64);
static int is_cie (ULONGEST cie_id, int dwarf64);
}
static void
-fde_chunks_need_space ()
+fde_chunks_need_space (void)
{
if (fde_chunks.elems < fde_chunks.array_size)
return;
}
/* Alocate a new `struct context' on temporary obstack. */
-static struct context *
-context_alloc ()
+struct context *
+context_alloc (void)
{
struct context *context;
}
/* Alocate a new `struct frame_state' on temporary obstack. */
-static struct frame_state *
-frame_state_alloc ()
+struct frame_state *
+frame_state_alloc (void)
{
struct frame_state *fs;
}
static void
-unwind_tmp_obstack_init ()
+unwind_tmp_obstack_init (void)
{
obstack_init (&unwind_tmp_obstack);
}
static void
-unwind_tmp_obstack_free ()
+unwind_tmp_obstack_free (void)
{
obstack_free (&unwind_tmp_obstack, NULL);
unwind_tmp_obstack_init ();
}
-static void
+void
context_cpy (struct context *dst, struct context *src)
{
int regs_size = sizeof (struct context_reg) * NUM_REGS;
struct context_reg *dreg;
- /* Structure dst contains a pointer to an array of
- * registers of a given frame as well as src does. This
- * array was already allocated before dst was passed to
- * context_cpy but the pointer to it was overriden by
- * '*dst = *src' and the array was lost. This led to the
- * situation, that we've had a copy of src placed in dst,
- * but both of them pointed to the same regs array and
- * thus we've sometimes blindly rewritten it. Now we save
- * the pointer before copying src to dst, return it back
- * after that and copy the registers into their new place
- * finally. --- mludvig@suse.cz */
+ /* Since `struct context' contains a pointer to an array with
+ register values, make sure we end up with a copy of that array,
+ and not with a copy of the pointer to that array. */
dreg = dst->reg;
*dst = *src;
dst->reg = dreg;
-
memcpy (dst->reg, src->reg, regs_size);
}
static unsigned int
-read_1u (bfd * abfd, char **p)
+read_1u (bfd *abfd, char **p)
{
unsigned ret;
}
static int
-read_1s (bfd * abfd, char **p)
+read_1s (bfd *abfd, char **p)
{
int ret;
}
static unsigned int
-read_2u (bfd * abfd, char **p)
+read_2u (bfd *abfd, char **p)
{
unsigned ret;
}
static int
-read_2s (bfd * abfd, char **p)
+read_2s (bfd *abfd, char **p)
{
int ret;
}
static unsigned int
-read_4u (bfd * abfd, char **p)
+read_4u (bfd *abfd, char **p)
{
unsigned int ret;
}
static int
-read_4s (bfd * abfd, char **p)
+read_4s (bfd *abfd, char **p)
{
int ret;
}
static ULONGEST
-read_8u (bfd * abfd, char **p)
+read_8u (bfd *abfd, char **p)
{
ULONGEST ret;
}
static LONGEST
-read_8s (bfd * abfd, char **p)
+read_8s (bfd *abfd, char **p)
{
LONGEST ret;
}
static ULONGEST
-read_uleb128 (bfd * abfd, char **p)
+read_uleb128 (bfd *abfd, char **p)
{
ULONGEST ret;
int i, shift;
}
static LONGEST
-read_sleb128 (bfd * abfd, char **p)
+read_sleb128 (bfd *abfd, char **p)
{
LONGEST ret;
int i, shift, size, num_read;
}
static CORE_ADDR
-read_pointer (bfd * abfd, char **p)
+read_pointer (bfd *abfd, char **p)
{
switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
{
}
}
-/* This functions only reads appropriate amount of data from *p
- * and returns the resulting value. Calling function must handle
- * different encoding possibilities itself! */
+/* Read the appropriate amount of data from *P and return the
+ resulting value based on ENCODING, which the calling function must
+ provide. */
static CORE_ADDR
-read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding)
+read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding)
{
CORE_ADDR ret;
return ret;
}
-/* Variable 'encoding' carries 3 different flags:
- * - encoding & 0x0f : size of the address (handled in read_encoded_pointer())
- * - encoding & 0x70 : type (absolute, relative, ...)
- * - encoding & 0x80 : indirect flag (DW_EH_PE_indirect == 0x80). */
+/* The variable 'encoding' carries three different flags:
+ - encoding & 0x0f : size of the address (handled in read_encoded_pointer())
+ - encoding & 0x70 : type (absolute, relative, ...)
+ - encoding & 0x80 : indirect flag (DW_EH_PE_indirect == 0x80). */
enum ptr_encoding
pointer_encoding (unsigned char encoding)
{
if (encoding & DW_EH_PE_indirect)
warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect");
-
+
switch (encoding & 0x70)
{
case DW_EH_PE_absptr:
ret = encoding & 0x70;
break;
default:
- internal_error (__FILE__, __LINE__,
- "CFI: unknown pointer encoding");
+ internal_error (__FILE__, __LINE__, "CFI: unknown pointer encoding");
}
return ret;
}
static LONGEST
-read_initial_length (bfd * abfd, char *buf, int *bytes_read)
+read_initial_length (bfd *abfd, char *buf, int *bytes_read)
{
LONGEST ret = 0;
}
static ULONGEST
-read_length (bfd * abfd, char *buf, int *bytes_read, int dwarf64)
+read_length (bfd *abfd, char *buf, int *bytes_read, int dwarf64)
{
if (dwarf64)
{
case DW_CFA_set_loc:
fs->pc = read_encoded_pointer (objfile->obfd, &insn_ptr,
fs->addr_encoding);
-
+
if (pointer_encoding (fs->addr_encoding) != PE_absptr)
- warning ("CFI: DW_CFA_set_loc uses relative addressing");
-
+ warning ("CFI: DW_CFA_set_loc uses relative addressing");
+
break;
case DW_CFA_advance_loc1:
fs->pc = fde->initial_location;
- if (fde->cie_ptr)
- {
- cie = fde->cie_ptr;
-
- fs->code_align = cie->code_align;
- fs->data_align = cie->data_align;
- fs->retaddr_column = cie->ra;
- fs->addr_encoding = cie->addr_encoding;
- fs->objfile = cie->objfile;
-
- execute_cfa_program (cie->objfile, cie->data,
- cie->data + cie->data_length, context, fs);
- execute_cfa_program (cie->objfile, fde->data,
- fde->data + fde->data_length, context, fs);
- }
- else
- internal_error (__FILE__, __LINE__,
- "%s(): Internal error: fde->cie_ptr==NULL !", __func__);
+ gdb_assert (fde->cie_ptr != NULL);
+
+ cie = fde->cie_ptr;
+
+ fs->code_align = cie->code_align;
+ fs->data_align = cie->data_align;
+ fs->retaddr_column = cie->ra;
+ fs->addr_encoding = cie->addr_encoding;
+ fs->objfile = cie->objfile;
+
+ execute_cfa_program (cie->objfile, cie->data,
+ cie->data + cie->data_length, context, fs);
+ execute_cfa_program (cie->objfile, fde->data,
+ fde->data + fde->data_length, context, fs);
}
static void
switch (context->reg[regnum].how)
{
case REG_CTX_UNSAVED:
- read_register_gen (regnum, reg);
+ deprecated_read_register_gen (regnum, reg);
break;
case REG_CTX_SAVED_OFFSET:
target_read_memory (context->cfa + context->reg[regnum].loc.offset,
reg, REGISTER_RAW_SIZE (regnum));
break;
case REG_CTX_SAVED_REG:
- read_register_gen (context->reg[regnum].loc.reg, reg);
+ deprecated_read_register_gen (context->reg[regnum].loc.reg, reg);
break;
case REG_CTX_SAVED_ADDR:
target_read_memory (context->reg[regnum].loc.addr,
{
case DW_OP_deref:
{
- char *ptr = (char *) result;
- result = read_pointer (objfile->obfd, &ptr);
+ int len = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
+ if (len != 4 && len != 8)
+ internal_error (__FILE__, __LINE__,
+ "execute_stack_op error");
+ result = read_memory_unsigned_integer (result, len);
}
break;
case DW_OP_deref_size:
{
- char *ptr = (char *) result;
- switch (*op_ptr++)
- {
- case 1:
- result = read_1u (objfile->obfd, &ptr);
- break;
- case 2:
- result = read_2u (objfile->obfd, &ptr);
- break;
- case 4:
- result = read_4u (objfile->obfd, &ptr);
- break;
- case 8:
- result = read_8u (objfile->obfd, &ptr);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- "execute_stack_op error");
- }
+ int len = *op_ptr++;
+ if (len != 1 && len != 2 && len != 4 && len != 8)
+ internal_error (__FILE__, __LINE__,
+ "execute_stack_op error");
+ result = read_memory_unsigned_integer (result, len);
}
break;
case DW_OP_ne:
result = (LONGEST) first != (LONGEST) second;
break;
- default: /* This label is here just to avoid warning. */
+ default:
+ error ("execute_stack_op: Unknown DW_OP_ value");
break;
}
}
update_context (struct context *context, struct frame_state *fs, int chain)
{
struct context *orig_context;
- CORE_ADDR cfa;
+ CORE_ADDR cfa = 0;
long i;
unwind_tmp_obstack_init ();
context->reg[i].how = REG_CTX_SAVED_ADDR;
context->reg[i].loc.addr =
orig_context->reg[fs->regs.reg[i].loc.reg].loc.addr;
+ break;
default:
- internal_error (__FILE__, __LINE__,
- "%s: unknown register rule", __func__);
+ internal_error (__FILE__, __LINE__, "bad switch");
}
break;
case REG_SAVED_EXP:
}
break;
default:
- internal_error (__FILE__, __LINE__,
- "%s: unknown register rule", __func__);
+ internal_error (__FILE__, __LINE__, "bad switch");
}
get_reg ((char *) &context->ra, context, fs->retaddr_column);
unwind_tmp_obstack_free ();
unsigned long length;
ULONGEST cie_id;
ULONGEST unit_offset = start - frame_buffer;
- int bytes_read, dwarf64, flag_pcrel;
+ int bytes_read, dwarf64;
char *block_end;
length = read_initial_length (abfd, start, &bytes_read);
cie->addr_encoding);
switch (pointer_encoding (cie->addr_encoding))
- {
+ {
case PE_absptr:
- break;
+ break;
case PE_pcrel:
- /* start-frame_buffer gives offset from
- the beginning of actual section. */
- init_loc += curr_section_vma + start - frame_buffer;
- break;
+ /* start-frame_buffer gives offset from
+ the beginning of actual section. */
+ init_loc += curr_section_vma + start - frame_buffer;
+ break;
default:
- warning ("CFI: Unsupported pointer encoding\n");
- }
+ warning ("CFI: Unsupported pointer encoding\n");
+ }
/* For relocatable objects we must add an offset telling
where the section is actually mapped in the memory. */
and don't need to care about duplicate FDEs, because
.debug_frame is parsed first. */
if (eh_frame == 2)
- for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++)
- {
- /* We assume that FDEs in .debug_frame and .eh_frame
- have the same order (if they are present, of course).
- If we find a duplicate entry for one FDE and save
- it's index to last_dup_fde it's very likely, that
- we'll find an entry for the following FDE right after
- the previous one. Thus in many cases we'll run this
- loop only once. */
- last_dup_fde = (last_dup_fde + i) % fde_chunks.elems;
- if (fde_chunks.array[last_dup_fde]->initial_location
- == init_loc)
- {
- dup = 1;
- break;
- }
- }
+ for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++)
+ {
+ /* We assume that FDEs in .debug_frame and .eh_frame
+ have the same order (if they are present, of course).
+ If we find a duplicate entry for one FDE and save
+ it's index to last_dup_fde it's very likely, that
+ we'll find an entry for the following FDE right after
+ the previous one. Thus in many cases we'll run this
+ loop only once. */
+ last_dup_fde = (last_dup_fde + i) % fde_chunks.elems;
+ if (fde_chunks.array[last_dup_fde]->initial_location
+ == init_loc)
+ {
+ dup = 1;
+ break;
+ }
+ }
/* Allocate a new entry only if this FDE isn't a duplicate of
something we have already seen. */
eh_frame==1. */
if (dwarf_frame_offset)
- {
- parse_frame_info (objfile, dwarf_frame_offset,
- dwarf_frame_size, 0 /* = debug_frame */);
- after_debug_frame = 1;
- }
+ {
+ parse_frame_info (objfile, dwarf_frame_offset,
+ dwarf_frame_size, 0 /* = debug_frame */ );
+ after_debug_frame = 1;
+ }
if (dwarf_eh_frame_offset)
- parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size,
- 1 /* = eh_frame */ + after_debug_frame);
+ parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size,
+ 1 /* = eh_frame */ + after_debug_frame);
}
/* Return the frame address. */
CORE_ADDR
-cfi_read_fp ()
+cfi_read_fp (void)
{
struct context *context;
struct frame_state *fs;
if (fs->cfa_how == CFA_REG_OFFSET)
{
val -= fs->cfa_offset;
- write_register_gen (fs->cfa_reg, (char *) &val);
+ deprecated_write_register_gen (fs->cfa_reg, (char *) &val);
}
else
warning ("Can't write fp.");
void
cfi_pop_frame (struct frame_info *fi)
{
- char regbuf[MAX_REGISTER_RAW_SIZE];
+ char *regbuf = alloca (MAX_REGISTER_RAW_SIZE);
int regnum;
- fi = get_current_frame ();
-
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
get_reg (regbuf, UNWIND_CONTEXT (fi), regnum);
- write_register_bytes (REGISTER_BYTE (regnum), regbuf,
- REGISTER_RAW_SIZE (regnum));
+ deprecated_write_register_bytes (REGISTER_BYTE (regnum), regbuf,
+ REGISTER_RAW_SIZE (regnum));
}
write_register (PC_REGNUM, UNWIND_CONTEXT (fi)->ra);
}
/* Sets the pc of the frame. */
-void
+CORE_ADDR
cfi_init_frame_pc (int fromleaf, struct frame_info *fi)
{
- if (fi->next)
- get_reg ((char *) &(fi->pc), UNWIND_CONTEXT (fi->next), PC_REGNUM);
+ if (get_next_frame (fi))
+ {
+ CORE_ADDR pc;
+ /* FIXME: cagney/2002-12-04: This is straight wrong. It's
+ assuming that the PC is CORE_ADDR (a host quantity) in size. */
+ get_reg ((void *)&pc, UNWIND_CONTEXT (get_next_frame (fi)), PC_REGNUM);
+ return pc;
+ }
else
- fi->pc = read_pc ();
+ return read_pc ();
}
/* Initialize unwind context informations of the frame. */
void
cfi_get_saved_register (char *raw_buffer,
int *optimized,
- CORE_ADDR * addrp,
+ CORE_ADDR *addrp,
struct frame_info *frame,
int regnum, enum lval_type *lval)
{
if (!frame->next)
{
- read_register_gen (regnum, raw_buffer);
+ deprecated_read_register_gen (regnum, raw_buffer);
if (lval != NULL)
*lval = lval_register;
if (addrp != NULL)
switch (UNWIND_CONTEXT (frame)->reg[regnum].how)
{
case REG_CTX_UNSAVED:
- read_register_gen (regnum, raw_buffer);
+ deprecated_read_register_gen (regnum, raw_buffer);
if (lval != NULL)
*lval = not_lval;
if (optimized != NULL)
UNWIND_CONTEXT (frame)->reg[regnum].loc.offset;
break;
case REG_CTX_SAVED_REG:
- read_register_gen (UNWIND_CONTEXT (frame)->reg[regnum].loc.reg,
- raw_buffer);
+ deprecated_read_register_gen (UNWIND_CONTEXT (frame)->reg[regnum].loc.reg,
+ raw_buffer);
if (lval != NULL)
*lval = lval_register;
if (addrp != NULL)