diff options
author | Mark Kettenis <kettenis@gnu.org> | 2003-06-08 12:43:02 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2003-06-08 12:43:02 +0000 |
commit | 4538b4f4c4248114e8ef75067fab572f6dee0b98 (patch) | |
tree | 595f599c21d33cdd370333c267f83eaab27d6246 | |
parent | 17076204402e68b3779f1e85a6d5d83eae3f1a33 (diff) | |
download | gdb-4538b4f4c4248114e8ef75067fab572f6dee0b98.zip gdb-4538b4f4c4248114e8ef75067fab572f6dee0b98.tar.gz gdb-4538b4f4c4248114e8ef75067fab572f6dee0b98.tar.bz2 |
* dwarf2cfi.c, dwarf2cfi.h: Remove.
-rw-r--r-- | gdb/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/dwarf2cfi.c | 1970 | ||||
-rw-r--r-- | gdb/dwarf2cfi.h | 102 |
3 files changed, 4 insertions, 2072 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c95bd00..9cc976b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,7 @@ +2003-06-08 Mark Kettenis <kettenis@gnu.org> + + * dwarf2cfi.c, dwarf2cfi.h: Remove. + 2003-06-07 Adam Fedor <fedor@gnu.org> * gdb/objc-lang.c (FETCH_ARGUMENT): Remove macro. diff --git a/gdb/dwarf2cfi.c b/gdb/dwarf2cfi.c deleted file mode 100644 index 085c91c..0000000 --- a/gdb/dwarf2cfi.c +++ /dev/null @@ -1,1970 +0,0 @@ -/* Stack unwinding code based on dwarf2 frame info for GDB, the GNU debugger. - - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. - - Contributed by Jiri Smid, SuSE Labs. - Based on code written by Daniel Berlin (dan@dberlin.org). - - This file is part of GDB. - - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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. */ - -#include "defs.h" -#include "gdbcore.h" -#include "symtab.h" -#include "symfile.h" -#include "objfiles.h" -#include "target.h" -#include "elf/dwarf2.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. */ -struct cie_unit -{ - /* Offset of this unit in .debug_frame or .eh_frame. */ - ULONGEST offset; - - /* A null-terminated string that identifies the augmentation to this CIE or - to the FDEs that use it. */ - char *augmentation; - - /* A constant that is factored out of all advance location instructions. */ - unsigned int code_align; - - /* A constant that is factored out of all offset instructions. */ - int data_align; - - /* A constant that indicates which regiter represents the return address - of a function. */ - unsigned char ra; - - /* Indicates how addresses are encoded. */ - unsigned char addr_encoding; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; - - struct objfile *objfile; - - /* Next in chain. */ - struct cie_unit *next; -}; - -/* Frame Description Entry. */ -struct fde_unit -{ - /* Address of the first location associated with this entry. */ - CORE_ADDR initial_location; - - /* Length of program section described by this entry. */ - CORE_ADDR address_range; - - /* Pointer to asociated CIE. */ - struct cie_unit *cie_ptr; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; -}; - -struct fde_array -{ - struct fde_unit **array; - int elems; - int array_size; -}; - -struct frame_state_reg -{ - union - { - unsigned int reg; - long offset; - unsigned char *exp; - } - loc; - enum - { - REG_UNSAVED, - REG_SAVED_OFFSET, - REG_SAVED_REG, - REG_SAVED_EXP, - } - how; -}; - -struct frame_state -{ - /* Each register save state can be described in terms of a CFA slot, - another register, or a location expression. */ - struct frame_state_regs - { - struct frame_state_reg *reg; - - /* Used to implement DW_CFA_remember_state. */ - struct frame_state_regs *prev; - } - regs; - - /* The CFA can be described in terms of a reg+offset or a - location expression. */ - long cfa_offset; - int cfa_reg; - unsigned char *cfa_exp; - enum - { - CFA_UNSET, - CFA_REG_OFFSET, - CFA_EXP, - } - cfa_how; - - /* The PC described by the current frame state. */ - CORE_ADDR pc; - - /* The information we care about from the CIE/FDE. */ - int data_align; - unsigned int code_align; - unsigned char retaddr_column; - unsigned char addr_encoding; - - struct objfile *objfile; -}; - -enum ptr_encoding -{ - PE_absptr = DW_EH_PE_absptr, - PE_pcrel = DW_EH_PE_pcrel, - PE_textrel = DW_EH_PE_textrel, - PE_datarel = DW_EH_PE_datarel, - PE_funcrel = DW_EH_PE_funcrel -}; - -#define UNWIND_CONTEXT(fi) ((struct context *) (deprecated_get_frame_context (fi))) - - -static struct cie_unit *cie_chunks; -static struct fde_array fde_chunks; -/* Obstack for allocating temporary storage used during unwind operations. */ -static struct obstack unwind_tmp_obstack; - -extern file_ptr dwarf_frame_offset; -extern unsigned int dwarf_frame_size; -extern file_ptr dwarf_eh_frame_offset; -extern unsigned int dwarf_eh_frame_size; -extern asection *dwarf_frame_section; -extern asection *dwarf_eh_frame_section; - - - -extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset, - unsigned int size, asection *sectp); - -static struct fde_unit *fde_unit_alloc (void); -static struct cie_unit *cie_unit_alloc (void); -static void fde_chunks_need_space (); - -static void unwind_tmp_obstack_init (); -static void unwind_tmp_obstack_free (); - -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, - struct objfile *objfile); - -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 int compare_fde_unit (const void *a, const void *b); -void dwarf2_build_frame_info (struct objfile *objfile); - -static void execute_cfa_program (struct objfile *objfile, char *insn_ptr, - char *insn_end, struct context *context, - struct frame_state *fs); -static struct fde_unit *get_fde_for_addr (CORE_ADDR pc); -static void frame_state_for (struct context *context, struct frame_state *fs); -static void get_reg (char *reg, struct context *context, int regnum); -static CORE_ADDR execute_stack_op (struct objfile *objfile, - char *op_ptr, char *op_end, - struct context *context, - CORE_ADDR initial); -static void update_context (struct context *context, struct frame_state *fs, - int chain); - - -/* Memory allocation functions. */ -static struct fde_unit * -fde_unit_alloc (void) -{ - struct fde_unit *fde; - - fde = (struct fde_unit *) xmalloc (sizeof (struct fde_unit)); - memset (fde, 0, sizeof (struct fde_unit)); - return fde; -} - -static struct cie_unit * -cie_unit_alloc (void) -{ - struct cie_unit *cie; - - cie = (struct cie_unit *) xmalloc (sizeof (struct cie_unit)); - memset (cie, 0, sizeof (struct cie_unit)); - return cie; -} - -static void -fde_chunks_need_space (void) -{ - if (fde_chunks.elems < fde_chunks.array_size) - return; - fde_chunks.array_size = - fde_chunks.array_size ? 2 * fde_chunks.array_size : 1024; - fde_chunks.array = - xrealloc (fde_chunks.array, - sizeof (struct fde_unit) * fde_chunks.array_size); -} - -/* Alocate a new `struct context' on temporary obstack. */ -struct context * -context_alloc (void) -{ - struct context *context; - - int regs_size = sizeof (struct context_reg) * NUM_REGS; - - context = (struct context *) obstack_alloc (&unwind_tmp_obstack, - sizeof (struct context)); - memset (context, 0, sizeof (struct context)); - context->reg = (struct context_reg *) obstack_alloc (&unwind_tmp_obstack, - regs_size); - memset (context->reg, 0, regs_size); - return context; -} - -/* Alocate a new `struct frame_state' on temporary obstack. */ -struct frame_state * -frame_state_alloc (void) -{ - struct frame_state *fs; - - int regs_size = sizeof (struct frame_state_reg) * NUM_REGS; - - fs = (struct frame_state *) obstack_alloc (&unwind_tmp_obstack, - sizeof (struct frame_state)); - memset (fs, 0, sizeof (struct frame_state)); - fs->regs.reg = - (struct frame_state_reg *) obstack_alloc (&unwind_tmp_obstack, regs_size); - memset (fs->regs.reg, 0, regs_size); - return fs; -} - -static void -unwind_tmp_obstack_init (void) -{ - obstack_init (&unwind_tmp_obstack); -} - -static void -unwind_tmp_obstack_free (void) -{ - obstack_free (&unwind_tmp_obstack, NULL); - unwind_tmp_obstack_init (); -} - -void -context_cpy (struct context *dst, struct context *src) -{ - int regs_size = sizeof (struct context_reg) * NUM_REGS; - struct context_reg *dreg; - - /* 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) -{ - unsigned ret; - - ret = bfd_get_8 (abfd, (bfd_byte *) * p); - (*p)++; - return ret; -} - -static int -read_1s (bfd *abfd, char **p) -{ - int ret; - - ret = bfd_get_signed_8 (abfd, (bfd_byte *) * p); - (*p)++; - return ret; -} - -static unsigned int -read_2u (bfd *abfd, char **p) -{ - unsigned ret; - - ret = bfd_get_16 (abfd, (bfd_byte *) * p); - (*p) += 2; - return ret; -} - -static int -read_2s (bfd *abfd, char **p) -{ - int ret; - - ret = bfd_get_signed_16 (abfd, (bfd_byte *) * p); - (*p) += 2; - return ret; -} - -static unsigned int -read_4u (bfd *abfd, char **p) -{ - unsigned int ret; - - ret = bfd_get_32 (abfd, (bfd_byte *) * p); - (*p) += 4; - return ret; -} - -static int -read_4s (bfd *abfd, char **p) -{ - int ret; - - ret = bfd_get_signed_32 (abfd, (bfd_byte *) * p); - (*p) += 4; - return ret; -} - -static ULONGEST -read_8u (bfd *abfd, char **p) -{ - ULONGEST ret; - - ret = bfd_get_64 (abfd, (bfd_byte *) * p); - (*p) += 8; - return ret; -} - -static LONGEST -read_8s (bfd *abfd, char **p) -{ - LONGEST ret; - - ret = bfd_get_signed_64 (abfd, (bfd_byte *) * p); - (*p) += 8; - return ret; -} - -static ULONGEST -read_uleb128 (bfd *abfd, char **p) -{ - ULONGEST ret; - int i, shift; - unsigned char byte; - - ret = 0; - shift = 0; - i = 0; - while (1) - { - byte = bfd_get_8 (abfd, (bfd_byte *) * p); - (*p)++; - ret |= ((unsigned long) (byte & 127) << shift); - if ((byte & 128) == 0) - { - break; - } - shift += 7; - } - return ret; -} - -static LONGEST -read_sleb128 (bfd *abfd, char **p) -{ - LONGEST ret; - int i, shift, size, num_read; - unsigned char byte; - - ret = 0; - shift = 0; - size = 32; - num_read = 0; - i = 0; - while (1) - { - byte = bfd_get_8 (abfd, (bfd_byte *) * p); - (*p)++; - ret |= ((long) (byte & 127) << shift); - shift += 7; - if ((byte & 128) == 0) - { - break; - } - } - if ((shift < size) && (byte & 0x40)) - { - ret |= -(1 << shift); - } - return ret; -} - -static CORE_ADDR -read_pointer (bfd *abfd, char **p) -{ - switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT) - { - case 4: - return read_4u (abfd, p); - case 8: - return read_8u (abfd, p); - default: - error - ("dwarf cfi error: unsupported target address length [in module %s]", - bfd_get_filename (abfd)); - } -} - -/* 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) -{ - CORE_ADDR ret; - - switch (encoding & 0x0f) - { - case DW_EH_PE_absptr: - ret = read_pointer (abfd, p); - break; - - case DW_EH_PE_uleb128: - ret = read_uleb128 (abfd, p); - break; - case DW_EH_PE_sleb128: - ret = read_sleb128 (abfd, p); - break; - - case DW_EH_PE_udata2: - ret = read_2u (abfd, p); - break; - case DW_EH_PE_udata4: - ret = read_4u (abfd, p); - break; - case DW_EH_PE_udata8: - ret = read_8u (abfd, p); - break; - - case DW_EH_PE_sdata2: - ret = read_2s (abfd, p); - break; - case DW_EH_PE_sdata4: - ret = read_4s (abfd, p); - break; - case DW_EH_PE_sdata8: - ret = read_8s (abfd, p); - break; - - default: - internal_error (__FILE__, __LINE__, - "read_encoded_pointer: unknown pointer encoding [in module %s]", - bfd_get_filename (abfd)); - } - - return ret; -} - -/* 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, struct objfile *objfile) -{ - int ret; - - if (encoding & DW_EH_PE_indirect) - warning - ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect [in module %s]", - objfile->name); - - switch (encoding & 0x70) - { - case DW_EH_PE_absptr: - case DW_EH_PE_pcrel: - case DW_EH_PE_textrel: - case DW_EH_PE_datarel: - case DW_EH_PE_funcrel: - ret = encoding & 0x70; - break; - default: - internal_error (__FILE__, __LINE__, - "CFI: unknown pointer encoding [in module %s]", - objfile->name); - } - return ret; -} - -static LONGEST -read_initial_length (bfd *abfd, char *buf, int *bytes_read) -{ - LONGEST ret = 0; - - ret = bfd_get_32 (abfd, (bfd_byte *) buf); - - if (ret == 0xffffffff) - { - ret = bfd_get_64 (abfd, (bfd_byte *) buf + 4); - *bytes_read = 12; - } - else - { - *bytes_read = 4; - } - - return ret; -} - -static ULONGEST -read_length (bfd *abfd, char *buf, int *bytes_read, int dwarf64) -{ - if (dwarf64) - { - *bytes_read = 8; - return read_8u (abfd, &buf); - } - else - { - *bytes_read = 4; - return read_4u (abfd, &buf); - } -} - -static void -execute_cfa_program (struct objfile *objfile, char *insn_ptr, char *insn_end, - struct context *context, struct frame_state *fs) -{ - struct frame_state_regs *unused_rs = NULL; - - /* Don't allow remember/restore between CIE and FDE programs. */ - fs->regs.prev = NULL; - - while (insn_ptr < insn_end && fs->pc < context->ra) - { - unsigned char insn = *insn_ptr++; - ULONGEST reg, uoffset; - LONGEST offset; - - if (insn & DW_CFA_advance_loc) - fs->pc += (insn & 0x3f) * fs->code_align; - else if (insn & DW_CFA_offset) - { - reg = insn & 0x3f; - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - offset = (long) uoffset *fs->data_align; - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = offset; - } - else if (insn & DW_CFA_restore) - { - reg = insn & 0x3f; - fs->regs.reg[reg].how = REG_UNSAVED; - } - else - switch (insn) - { - case DW_CFA_set_loc: - fs->pc = read_encoded_pointer (objfile->obfd, &insn_ptr, - fs->addr_encoding); - - if (pointer_encoding (fs->addr_encoding, objfile) != PE_absptr) - warning - ("CFI: DW_CFA_set_loc uses relative addressing [in module %s]", - objfile->name); - - break; - - case DW_CFA_advance_loc1: - fs->pc += read_1u (objfile->obfd, &insn_ptr); - break; - case DW_CFA_advance_loc2: - fs->pc += read_2u (objfile->obfd, &insn_ptr); - break; - case DW_CFA_advance_loc4: - fs->pc += read_4u (objfile->obfd, &insn_ptr); - break; - - case DW_CFA_offset_extended: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - offset = (long) uoffset *fs->data_align; - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = offset; - break; - - case DW_CFA_restore_extended: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - fs->regs.reg[reg].how = REG_UNSAVED; - break; - - case DW_CFA_undefined: - case DW_CFA_same_value: - case DW_CFA_nop: - break; - - case DW_CFA_register: - { - ULONGEST reg2; - reg = read_uleb128 (objfile->obfd, &insn_ptr); - reg2 = read_uleb128 (objfile->obfd, &insn_ptr); - fs->regs.reg[reg].how = REG_SAVED_REG; - fs->regs.reg[reg].loc.reg = reg2; - } - break; - - case DW_CFA_remember_state: - { - struct frame_state_regs *new_rs; - if (unused_rs) - { - new_rs = unused_rs; - unused_rs = unused_rs->prev; - } - else - new_rs = xmalloc (sizeof (struct frame_state_regs)); - - *new_rs = fs->regs; - fs->regs.prev = new_rs; - } - break; - - case DW_CFA_restore_state: - { - struct frame_state_regs *old_rs = fs->regs.prev; - fs->regs = *old_rs; - old_rs->prev = unused_rs; - unused_rs = old_rs; - } - break; - - case DW_CFA_def_cfa: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - fs->cfa_reg = reg; - fs->cfa_offset = uoffset; - fs->cfa_how = CFA_REG_OFFSET; - break; - - case DW_CFA_def_cfa_register: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - fs->cfa_reg = reg; - fs->cfa_how = CFA_REG_OFFSET; - break; - - case DW_CFA_def_cfa_offset: - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - fs->cfa_offset = uoffset; - break; - - case DW_CFA_def_cfa_expression: - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - fs->cfa_exp = insn_ptr; - fs->cfa_how = CFA_EXP; - insn_ptr += uoffset; - break; - - case DW_CFA_expression: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - fs->regs.reg[reg].how = REG_SAVED_EXP; - fs->regs.reg[reg].loc.exp = insn_ptr; - insn_ptr += uoffset; - break; - - /* From the 2.1 draft. */ - case DW_CFA_offset_extended_sf: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - offset = read_sleb128 (objfile->obfd, &insn_ptr); - offset *= fs->data_align; - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = offset; - break; - - case DW_CFA_def_cfa_sf: - reg = read_uleb128 (objfile->obfd, &insn_ptr); - offset = read_sleb128 (objfile->obfd, &insn_ptr); - fs->cfa_offset = offset; - fs->cfa_reg = reg; - fs->cfa_how = CFA_REG_OFFSET; - break; - - case DW_CFA_def_cfa_offset_sf: - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - fs->cfa_offset = uoffset; - /* cfa_how deliberately not set. */ - break; - - case DW_CFA_GNU_window_save: - /* ??? Hardcoded for SPARC register window configuration. */ - for (reg = 16; reg < 32; ++reg) - { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); - } - break; - - case DW_CFA_GNU_args_size: - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - context->args_size = uoffset; - break; - - case DW_CFA_GNU_negative_offset_extended: - /* Obsoleted by DW_CFA_offset_extended_sf, but used by - older PowerPC code. */ - reg = read_uleb128 (objfile->obfd, &insn_ptr); - uoffset = read_uleb128 (objfile->obfd, &insn_ptr); - offset = (long) uoffset *fs->data_align; - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = -offset; - break; - - default: - error - ("dwarf cfi error: unknown cfa instruction %d [in module %s]", - insn, objfile->name); - } - } -} - -static struct fde_unit * -get_fde_for_addr (CORE_ADDR pc) -{ - size_t lo, hi; - struct fde_unit *fde = NULL; - lo = 0; - hi = fde_chunks.elems; - - while (lo < hi) - { - size_t i = (lo + hi) / 2; - fde = fde_chunks.array[i]; - if (pc < fde->initial_location) - hi = i; - else if (pc >= fde->initial_location + fde->address_range) - lo = i + 1; - else - return fde; - } - return 0; -} - -static void -frame_state_for (struct context *context, struct frame_state *fs) -{ - struct fde_unit *fde; - struct cie_unit *cie; - - context->args_size = 0; - context->lsda = 0; - - fde = get_fde_for_addr (context->ra - 1); - - if (fde == NULL) - return; - - fs->pc = fde->initial_location; - - 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 -get_reg (char *reg, struct context *context, int regnum) -{ - switch (context->reg[regnum].how) - { - case REG_CTX_UNSAVED: - 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: - deprecated_read_register_gen (context->reg[regnum].loc.reg, reg); - break; - case REG_CTX_SAVED_ADDR: - target_read_memory (context->reg[regnum].loc.addr, - reg, REGISTER_RAW_SIZE (regnum)); - break; - case REG_CTX_VALUE: - memcpy (reg, &context->reg[regnum].loc.addr, - REGISTER_RAW_SIZE (regnum)); - break; - default: - internal_error (__FILE__, __LINE__, "get_reg: unknown register rule"); - } -} - -/* Decode a DW_OP stack program. Return the top of stack. Push INITIAL - onto the stack to start. */ -static CORE_ADDR -execute_stack_op (struct objfile *objfile, - char *op_ptr, char *op_end, struct context *context, - CORE_ADDR initial) -{ - CORE_ADDR stack[64]; /* ??? Assume this is enough. */ - int stack_elt; - - stack[0] = initial; - stack_elt = 1; - - while (op_ptr < op_end) - { - enum dwarf_location_atom op = *op_ptr++; - CORE_ADDR result; - ULONGEST reg; - LONGEST offset; - - switch (op) - { - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - result = op - DW_OP_lit0; - break; - - case DW_OP_addr: - result = read_pointer (objfile->obfd, &op_ptr); - break; - - case DW_OP_const1u: - result = read_1u (objfile->obfd, &op_ptr); - break; - case DW_OP_const1s: - result = read_1s (objfile->obfd, &op_ptr); - break; - case DW_OP_const2u: - result = read_2u (objfile->obfd, &op_ptr); - break; - case DW_OP_const2s: - result = read_2s (objfile->obfd, &op_ptr); - break; - case DW_OP_const4u: - result = read_4u (objfile->obfd, &op_ptr); - break; - case DW_OP_const4s: - result = read_4s (objfile->obfd, &op_ptr); - break; - case DW_OP_const8u: - result = read_8u (objfile->obfd, &op_ptr); - break; - case DW_OP_const8s: - result = read_8s (objfile->obfd, &op_ptr); - break; - case DW_OP_constu: - result = read_uleb128 (objfile->obfd, &op_ptr); - break; - case DW_OP_consts: - result = read_sleb128 (objfile->obfd, &op_ptr); - break; - - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - get_reg ((char *) &result, context, op - DW_OP_reg0); - break; - case DW_OP_regx: - reg = read_uleb128 (objfile->obfd, &op_ptr); - get_reg ((char *) &result, context, reg); - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - offset = read_sleb128 (objfile->obfd, &op_ptr); - get_reg ((char *) &result, context, op - DW_OP_breg0); - result += offset; - break; - case DW_OP_bregx: - reg = read_uleb128 (objfile->obfd, &op_ptr); - offset = read_sleb128 (objfile->obfd, &op_ptr); - get_reg ((char *) &result, context, reg); - result += offset; - break; - - case DW_OP_dup: - if (stack_elt < 1) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = stack[stack_elt - 1]; - break; - - case DW_OP_drop: - if (--stack_elt < 0) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - goto no_push; - - case DW_OP_pick: - offset = *op_ptr++; - if (offset >= stack_elt - 1) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = stack[stack_elt - 1 - offset]; - break; - - case DW_OP_over: - if (stack_elt < 2) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = stack[stack_elt - 2]; - break; - - case DW_OP_rot: - { - CORE_ADDR t1, t2, t3; - - if (stack_elt < 3) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - t1 = stack[stack_elt - 1]; - t2 = stack[stack_elt - 2]; - t3 = stack[stack_elt - 3]; - stack[stack_elt - 1] = t2; - stack[stack_elt - 2] = t3; - stack[stack_elt - 3] = t1; - goto no_push; - } - - case DW_OP_deref: - case DW_OP_deref_size: - case DW_OP_abs: - case DW_OP_neg: - case DW_OP_not: - case DW_OP_plus_uconst: - /* Unary operations. */ - if (--stack_elt < 0) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = stack[stack_elt]; - - switch (op) - { - case DW_OP_deref: - { - int len = TARGET_ADDR_BIT / TARGET_CHAR_BIT; - if (len != 4 && len != 8) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = read_memory_unsigned_integer (result, len); - } - break; - - case DW_OP_deref_size: - { - int len = *op_ptr++; - if (len != 1 && len != 2 && len != 4 && len != 8) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - result = read_memory_unsigned_integer (result, len); - } - break; - - case DW_OP_abs: - if (result < 0) - result = -result; - break; - case DW_OP_neg: - result = -result; - break; - case DW_OP_not: - result = ~result; - break; - case DW_OP_plus_uconst: - result += read_uleb128 (objfile->obfd, &op_ptr); - break; - default: - break; - } - break; - - case DW_OP_and: - case DW_OP_div: - case DW_OP_minus: - case DW_OP_mod: - case DW_OP_mul: - case DW_OP_or: - case DW_OP_plus: - case DW_OP_le: - case DW_OP_ge: - case DW_OP_eq: - case DW_OP_lt: - case DW_OP_gt: - case DW_OP_ne: - { - /* Binary operations. */ - CORE_ADDR first, second; - if ((stack_elt -= 2) < 0) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - second = stack[stack_elt]; - first = stack[stack_elt + 1]; - - switch (op) - { - case DW_OP_and: - result = second & first; - break; - case DW_OP_div: - result = (LONGEST) second / (LONGEST) first; - break; - case DW_OP_minus: - result = second - first; - break; - case DW_OP_mod: - result = (LONGEST) second % (LONGEST) first; - break; - case DW_OP_mul: - result = second * first; - break; - case DW_OP_or: - result = second | first; - break; - case DW_OP_plus: - result = second + first; - break; - case DW_OP_shl: - result = second << first; - break; - case DW_OP_shr: - result = second >> first; - break; - case DW_OP_shra: - result = (LONGEST) second >> first; - break; - case DW_OP_xor: - result = second ^ first; - break; - case DW_OP_le: - result = (LONGEST) first <= (LONGEST) second; - break; - case DW_OP_ge: - result = (LONGEST) first >= (LONGEST) second; - break; - case DW_OP_eq: - result = (LONGEST) first == (LONGEST) second; - break; - case DW_OP_lt: - result = (LONGEST) first < (LONGEST) second; - break; - case DW_OP_gt: - result = (LONGEST) first > (LONGEST) second; - break; - case DW_OP_ne: - result = (LONGEST) first != (LONGEST) second; - break; - default: - error - ("execute_stack_op: Unknown DW_OP_ value [in module %s]", - objfile->name); - break; - } - } - break; - - case DW_OP_skip: - offset = read_2s (objfile->obfd, &op_ptr); - op_ptr += offset; - goto no_push; - - case DW_OP_bra: - if (--stack_elt < 0) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - offset = read_2s (objfile->obfd, &op_ptr); - if (stack[stack_elt] != 0) - op_ptr += offset; - goto no_push; - - case DW_OP_nop: - goto no_push; - - default: - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - } - - /* Most things push a result value. */ - if ((size_t) stack_elt >= sizeof (stack) / sizeof (*stack)) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", - objfile->name); - stack[++stack_elt] = result; - no_push:; - } - - /* We were executing this program to get a value. It should be - at top of stack. */ - if (--stack_elt < 0) - internal_error (__FILE__, __LINE__, - "execute_stack_op error [in module %s]", objfile->name); - return stack[stack_elt]; -} - -static void -update_context (struct context *context, struct frame_state *fs, int chain) -{ - struct context *orig_context; - CORE_ADDR cfa = 0; - long i; - - unwind_tmp_obstack_init (); - - orig_context = context_alloc (); - context_cpy (orig_context, context); - - /* Compute this frame's CFA. */ - switch (fs->cfa_how) - { - case CFA_REG_OFFSET: - get_reg ((char *) &cfa, context, fs->cfa_reg); - cfa += fs->cfa_offset; - break; - - case CFA_EXP: - /* ??? No way of knowing what register number is the stack pointer - to do the same sort of handling as above. Assume that if the - CFA calculation is so complicated as to require a stack program - that this will not be a problem. */ - { - char *exp = fs->cfa_exp; - ULONGEST len; - - len = read_uleb128 (fs->objfile->obfd, &exp); - cfa = (CORE_ADDR) execute_stack_op (fs->objfile, exp, - exp + len, context, 0); - break; - } - default: - break; - } - context->cfa = cfa; - - if (!chain) - orig_context->cfa = cfa; - - /* Compute the addresses of all registers saved in this frame. */ - for (i = 0; i < NUM_REGS; ++i) - switch (fs->regs.reg[i].how) - { - case REG_UNSAVED: - if (i == SP_REGNUM) - { - context->reg[i].how = REG_CTX_VALUE; - context->reg[i].loc.addr = cfa; - } - else - context->reg[i].how = REG_CTX_UNSAVED; - break; - case REG_SAVED_OFFSET: - context->reg[i].how = REG_CTX_SAVED_OFFSET; - context->reg[i].loc.offset = fs->regs.reg[i].loc.offset; - break; - case REG_SAVED_REG: - switch (orig_context->reg[fs->regs.reg[i].loc.reg].how) - { - case REG_CTX_UNSAVED: - context->reg[i].how = REG_CTX_UNSAVED; - break; - case REG_CTX_SAVED_OFFSET: - context->reg[i].how = REG_CTX_SAVED_OFFSET; - context->reg[i].loc.offset = orig_context->cfa - context->cfa + - orig_context->reg[fs->regs.reg[i].loc.reg].loc.offset; - break; - case REG_CTX_SAVED_REG: - context->reg[i].how = REG_CTX_SAVED_REG; - context->reg[i].loc.reg = - orig_context->reg[fs->regs.reg[i].loc.reg].loc.reg; - break; - case REG_CTX_SAVED_ADDR: - 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__, "bad switch 0x%02X", - orig_context->reg[fs->regs.reg[i].loc.reg].how); - } - break; - case REG_SAVED_EXP: - { - char *exp = fs->regs.reg[i].loc.exp; - ULONGEST len; - CORE_ADDR val; - - len = read_uleb128 (fs->objfile->obfd, &exp); - val = execute_stack_op (fs->objfile, exp, exp + len, - orig_context, cfa); - context->reg[i].how = REG_CTX_SAVED_ADDR; - context->reg[i].loc.addr = val; - } - break; - default: - internal_error (__FILE__, __LINE__, "bad switch 0x%02X", - fs->regs.reg[i].how); - } - get_reg ((char *) &context->ra, context, fs->retaddr_column); - unwind_tmp_obstack_free (); -} - -static int -is_cie (ULONGEST cie_id, int dwarf64) -{ - return dwarf64 ? (cie_id == 0xffffffffffffffff) : (cie_id == 0xffffffff); -} - -static int -compare_fde_unit (const void *a, const void *b) -{ - struct fde_unit **first, **second; - first = (struct fde_unit **) a; - second = (struct fde_unit **) b; - if ((*first)->initial_location > (*second)->initial_location) - return 1; - else if ((*first)->initial_location < (*second)->initial_location) - return -1; - else - return 0; -} - -/* Build the cie_chunks and fde_chunks tables from informations - found in .debug_frame and .eh_frame sections. */ -/* We can handle both of these sections almost in the same way, however there - are some exceptions: - - CIE ID is -1 in debug_frame, but 0 in eh_frame - - eh_frame may contain some more information that are used only by gcc - (eg. personality pointer, LSDA pointer, ...). Most of them we can ignore. - - In debug_frame FDE's item cie_id contains offset of it's parent CIE. - In eh_frame FDE's item cie_id is a relative pointer to the parent CIE. - Anyway we don't need to bother with this, because we are smart enough - to keep the pointer to the parent CIE of oncomming FDEs in 'last_cie'. - - Although debug_frame items can contain Augmentation as well as - eh_frame ones, I have never seen them non-empty. Thus only in eh_frame - we can encounter for example non-absolute pointers (Aug. 'R'). - -- mludvig */ -static void -parse_frame_info (struct objfile *objfile, file_ptr frame_offset, - unsigned int frame_size, asection *frame_section, - int eh_frame) -{ - bfd *abfd = objfile->obfd; - asection *curr_section_ptr; - char *start = NULL; - char *end = NULL; - char *frame_buffer = NULL; - char *curr_section_name, *aug_data; - struct cie_unit *last_cie = NULL; - int last_dup_fde = 0; - int aug_len, i; - CORE_ADDR curr_section_vma = 0; - - unwind_tmp_obstack_init (); - - frame_buffer = dwarf2_read_section (objfile, frame_offset, frame_size, - frame_section); - - start = frame_buffer; - end = frame_buffer + frame_size; - - curr_section_name = eh_frame ? ".eh_frame" : ".debug_frame"; - curr_section_ptr = bfd_get_section_by_name (abfd, curr_section_name); - if (curr_section_ptr) - curr_section_vma = curr_section_ptr->vma; - - if (start) - { - while (start < end) - { - unsigned long length; - ULONGEST cie_id; - ULONGEST unit_offset = start - frame_buffer; - int bytes_read, dwarf64; - char *block_end; - - length = read_initial_length (abfd, start, &bytes_read); - start += bytes_read; - dwarf64 = (bytes_read == 12); - block_end = start + length; - - if (length == 0) - { - start = block_end; - continue; - } - - cie_id = read_length (abfd, start, &bytes_read, dwarf64); - start += bytes_read; - - if ((eh_frame && cie_id == 0) || is_cie (cie_id, dwarf64)) - { - struct cie_unit *cie = cie_unit_alloc (); - char *aug; - - cie->objfile = objfile; - cie->next = cie_chunks; - cie_chunks = cie; - - cie->objfile = objfile; - - cie->offset = unit_offset; - - start++; /* version */ - - cie->augmentation = aug = start; - while (*start++); /* Skips last NULL as well */ - - cie->code_align = read_uleb128 (abfd, &start); - cie->data_align = read_sleb128 (abfd, &start); - cie->ra = read_1u (abfd, &start); - - /* Augmentation: - z Indicates that a uleb128 is present to size the - augmentation section. - L Indicates the encoding (and thus presence) of - an LSDA pointer in the FDE augmentation. - R Indicates a non-default pointer encoding for - FDE code pointers. - P Indicates the presence of an encoding + language - personality routine in the CIE augmentation. - - [This info comes from GCC's dwarf2out.c] - */ - if (*aug == 'z') - { - aug_len = read_uleb128 (abfd, &start); - aug_data = start; - start += aug_len; - ++aug; - } - - cie->data = start; - cie->data_length = block_end - cie->data; - - while (*aug != '\0') - { - if (aug[0] == 'e' && aug[1] == 'h') - { - aug_data += sizeof (void *); - aug++; - } - else if (aug[0] == 'R') - cie->addr_encoding = *aug_data++; - else if (aug[0] == 'P') - { - CORE_ADDR pers_addr; - int pers_addr_enc; - - pers_addr_enc = *aug_data++; - /* We don't need pers_addr value and so we - don't care about it's encoding. */ - pers_addr = read_encoded_pointer (abfd, &aug_data, - pers_addr_enc); - } - else if (aug[0] == 'L' && eh_frame) - { - int lsda_addr_enc; - - /* Perhaps we should save this to CIE for later use? - Do we need it for something in GDB? */ - lsda_addr_enc = *aug_data++; - } - else - warning ("CFI warning: unknown augmentation \"%c\"" - " in \"%s\" of\n" - "\t%s", aug[0], curr_section_name, - objfile->name); - aug++; - } - - last_cie = cie; - } - else - { - struct fde_unit *fde; - struct cie_unit *cie; - int dup = 0; - CORE_ADDR init_loc; - - /* We assume that debug_frame is in order - CIE,FDE,CIE,FDE,FDE,... and thus the CIE for this FDE - should be stored in last_cie pointer. If not, we'll - try to find it by the older way. */ - if (last_cie) - cie = last_cie; - else - { - warning ("CFI: last_cie == NULL. " - "Perhaps a malformed %s section in '%s'...?\n", - curr_section_name, objfile->name); - - cie = cie_chunks; - while (cie) - { - if (cie->objfile == objfile) - { - if (eh_frame && - (cie->offset == - (unit_offset + bytes_read - cie_id))) - break; - if (!eh_frame && (cie->offset == cie_id)) - break; - } - - cie = cie->next; - } - if (!cie) - error ("CFI: can't find CIE pointer [in module %s]", - bfd_get_filename (abfd)); - } - - init_loc = read_encoded_pointer (abfd, &start, - cie->addr_encoding); - - switch (pointer_encoding (cie->addr_encoding, objfile)) - { - case PE_absptr: - break; - case PE_pcrel: - /* 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 [in module %s]", - bfd_get_filename (abfd)); - } - - /* For relocatable objects we must add an offset telling - where the section is actually mapped in the memory. */ - init_loc += ANOFFSET (objfile->section_offsets, - SECT_OFF_TEXT (objfile)); - - /* If we have both .debug_frame and .eh_frame present in - a file, we must eliminate duplicate FDEs. For now we'll - run through all entries in fde_chunks and check it one - by one. Perhaps in the future we can implement a faster - searching algorithm. */ - /* eh_frame==2 indicates, that this file has an already - parsed .debug_frame too. When eh_frame==1 it means, that no - .debug_frame is present and thus we don't need to check for - duplicities. eh_frame==0 means, that we parse .debug_frame - 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; - } - } - - /* Allocate a new entry only if this FDE isn't a duplicate of - something we have already seen. */ - if (!dup) - { - fde_chunks_need_space (); - fde = fde_unit_alloc (); - - fde_chunks.array[fde_chunks.elems++] = fde; - - fde->initial_location = init_loc; - fde->address_range = read_encoded_pointer (abfd, &start, - cie-> - addr_encoding); - - fde->cie_ptr = cie; - - /* Here we intentionally ignore augmentation data - from FDE, because we don't need them. */ - if (cie->augmentation[0] == 'z') - start += read_uleb128 (abfd, &start); - - fde->data = start; - fde->data_length = block_end - start; - } - } - start = block_end; - } - qsort (fde_chunks.array, fde_chunks.elems, - sizeof (struct fde_unit *), compare_fde_unit); - } -} - -/* We must parse both .debug_frame section and .eh_frame because - * not all frames must be present in both of these sections. */ -void -dwarf2_build_frame_info (struct objfile *objfile) -{ - int after_debug_frame = 0; - - /* If we have .debug_frame then the parser is called with - eh_frame==0 for .debug_frame and eh_frame==2 for .eh_frame, - otherwise it's only called once for .eh_frame with argument - eh_frame==1. */ - - if (dwarf_frame_offset) - { - parse_frame_info (objfile, dwarf_frame_offset, - dwarf_frame_size, dwarf_frame_section, - 0 /* = debug_frame */ ); - after_debug_frame = 1; - } - - if (dwarf_eh_frame_offset) - parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size, - dwarf_eh_frame_section, - 1 /* = eh_frame */ + after_debug_frame); -} - -/* Return the frame address. */ -CORE_ADDR -cfi_read_fp (void) -{ - struct context *context; - struct frame_state *fs; - CORE_ADDR cfa; - - unwind_tmp_obstack_init (); - - context = context_alloc (); - fs = frame_state_alloc (); - - context->ra = read_pc () + 1; - - frame_state_for (context, fs); - update_context (context, fs, 0); - - cfa = context->cfa; - - unwind_tmp_obstack_free (); - - return cfa; -} - -/* Store the frame address. This function is not used. */ - -void -cfi_write_fp (CORE_ADDR val) -{ - struct context *context; - struct frame_state *fs; - - unwind_tmp_obstack_init (); - - context = context_alloc (); - fs = frame_state_alloc (); - - context->ra = read_pc () + 1; - - frame_state_for (context, fs); - - if (fs->cfa_how == CFA_REG_OFFSET) - { - val -= fs->cfa_offset; - deprecated_write_register_gen (fs->cfa_reg, (char *) &val); - } - else - warning ("Can't write fp."); - - unwind_tmp_obstack_free (); -} - -/* Restore the machine to the state it had before the current frame - was created. */ -void -cfi_pop_frame (struct frame_info *fi) -{ - char regbuf[MAX_REGISTER_SIZE]; - int regnum; - - for (regnum = 0; regnum < NUM_REGS; regnum++) - { - get_reg (regbuf, UNWIND_CONTEXT (fi), regnum); - deprecated_write_register_bytes (REGISTER_BYTE (regnum), regbuf, - REGISTER_RAW_SIZE (regnum)); - } - write_register (PC_REGNUM, UNWIND_CONTEXT (fi)->ra); - - flush_cached_frames (); -} - -/* Determine the address of the calling function's frame. */ -CORE_ADDR -cfi_frame_chain (struct frame_info *fi) -{ - struct context *context; - struct frame_state *fs; - CORE_ADDR cfa; - - unwind_tmp_obstack_init (); - - context = context_alloc (); - fs = frame_state_alloc (); - context_cpy (context, UNWIND_CONTEXT (fi)); - - /* outermost frame */ - if (context->ra == 0) - { - unwind_tmp_obstack_free (); - return 0; - } - - frame_state_for (context, fs); - update_context (context, fs, 1); - - cfa = context->cfa; - unwind_tmp_obstack_free (); - - return cfa; -} - -/* Sets the pc of the frame. */ -CORE_ADDR -cfi_init_frame_pc (int fromleaf, struct frame_info *fi) -{ - 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 - return read_pc (); -} - -/* Initialize unwind context informations of the frame. */ -void -cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi) -{ - struct frame_state *fs; - - unwind_tmp_obstack_init (); - - fs = frame_state_alloc (); - deprecated_set_frame_context (fi, - frame_obstack_zalloc (sizeof - (struct context))); - UNWIND_CONTEXT (fi)->reg = - frame_obstack_zalloc (sizeof (struct context_reg) * NUM_REGS); - memset (UNWIND_CONTEXT (fi)->reg, 0, - sizeof (struct context_reg) * NUM_REGS); - - if (get_next_frame (fi)) - { - context_cpy (UNWIND_CONTEXT (fi), UNWIND_CONTEXT (get_next_frame (fi))); - frame_state_for (UNWIND_CONTEXT (fi), fs); - update_context (UNWIND_CONTEXT (fi), fs, 1); - } - else - { - UNWIND_CONTEXT (fi)->ra = get_frame_pc (fi) + 1; - frame_state_for (UNWIND_CONTEXT (fi), fs); - update_context (UNWIND_CONTEXT (fi), fs, 0); - } - - unwind_tmp_obstack_free (); -} - -/* Obtain return address of the frame. */ -CORE_ADDR -cfi_get_ra (struct frame_info *fi) -{ - return UNWIND_CONTEXT (fi)->ra; -} - -/* Find register number REGNUM relative to FRAME and put its - (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable - was optimized out (and thus can't be fetched). If the variable - was fetched from memory, set *ADDRP to where it was fetched from, - otherwise it was fetched from a register. - - The argument RAW_BUFFER must point to aligned memory. */ -void -cfi_get_saved_register (char *raw_buffer, - int *optimized, - CORE_ADDR *addrp, - struct frame_info *frame, - int regnum, enum lval_type *lval) -{ - if (!target_has_registers) - error ("No registers."); - - /* Normal systems don't optimize out things with register numbers. */ - if (optimized != NULL) - *optimized = 0; - - if (addrp) /* default assumption: not found in memory */ - *addrp = 0; - - if (!get_next_frame (frame)) - { - deprecated_read_register_gen (regnum, raw_buffer); - if (lval != NULL) - *lval = lval_register; - if (addrp != NULL) - *addrp = REGISTER_BYTE (regnum); - } - else - { - frame = get_next_frame (frame); - switch (UNWIND_CONTEXT (frame)->reg[regnum].how) - { - case REG_CTX_UNSAVED: - deprecated_read_register_gen (regnum, raw_buffer); - if (lval != NULL) - *lval = not_lval; - if (optimized != NULL) - *optimized = 1; - break; - case REG_CTX_SAVED_OFFSET: - target_read_memory (UNWIND_CONTEXT (frame)->cfa + - UNWIND_CONTEXT (frame)->reg[regnum].loc.offset, - raw_buffer, REGISTER_RAW_SIZE (regnum)); - if (lval != NULL) - *lval = lval_memory; - if (addrp != NULL) - *addrp = - UNWIND_CONTEXT (frame)->cfa + - UNWIND_CONTEXT (frame)->reg[regnum].loc.offset; - break; - case REG_CTX_SAVED_REG: - deprecated_read_register_gen (UNWIND_CONTEXT (frame)->reg[regnum]. - loc.reg, raw_buffer); - if (lval != NULL) - *lval = lval_register; - if (addrp != NULL) - *addrp = - REGISTER_BYTE (UNWIND_CONTEXT (frame)->reg[regnum].loc.reg); - break; - case REG_CTX_SAVED_ADDR: - target_read_memory (UNWIND_CONTEXT (frame)->reg[regnum].loc.addr, - raw_buffer, REGISTER_RAW_SIZE (regnum)); - if (lval != NULL) - *lval = lval_memory; - if (addrp != NULL) - *addrp = UNWIND_CONTEXT (frame)->reg[regnum].loc.addr; - break; - case REG_CTX_VALUE: - memcpy (raw_buffer, &UNWIND_CONTEXT (frame)->reg[regnum].loc.addr, - REGISTER_RAW_SIZE (regnum)); - if (lval != NULL) - *lval = not_lval; - if (optimized != NULL) - *optimized = 0; - break; - default: - internal_error (__FILE__, __LINE__, - "cfi_get_saved_register: unknown register rule 0x%02X", - UNWIND_CONTEXT (frame)->reg[regnum].how); - } - } -} - -/* Return the register that the function uses for a frame pointer, - plus any necessary offset to be applied to the register before - any frame pointer offsets. */ -void -cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_reg, - LONGEST * frame_offset) -{ - struct context *context; - struct frame_state *fs; - - unwind_tmp_obstack_init (); - - context = context_alloc (); - fs = frame_state_alloc (); - - context->ra = read_pc () + 1; - - frame_state_for (context, fs); - - if (fs->cfa_how == CFA_REG_OFFSET) - { - *frame_reg = fs->cfa_reg; - *frame_offset = fs->cfa_offset; - } - else - error ("dwarf cfi error: CFA is not defined as CFA_REG_OFFSET"); - - unwind_tmp_obstack_free (); -} diff --git a/gdb/dwarf2cfi.h b/gdb/dwarf2cfi.h deleted file mode 100644 index 28a329d..0000000 --- a/gdb/dwarf2cfi.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Stack unwinding code based on dwarf2 frame info for GDB, the GNU debugger. - Copyright 2001 - Free Software Foundation, Inc. - - This file is part of GDB. - - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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. */ - -#ifndef DWARF2CFI_H -#define DWARF2CFI_H - -struct frame_info; - -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; -}; - -/* Return the frame address. */ -CORE_ADDR cfi_read_fp (); - -/* Store the frame address. */ -void cfi_write_fp (CORE_ADDR val); - -/* Restore the machine to the state it had before the current frame - was created. */ -void cfi_pop_frame (struct frame_info *); - -/* Determine the address of the calling function's frame. */ -CORE_ADDR cfi_frame_chain (struct frame_info *fi); - -/* Sets the pc of the frame. */ -CORE_ADDR cfi_init_frame_pc (int fromleaf, struct frame_info *fi); - -/* Initialize unwind context informations of the frame. */ -void cfi_init_extra_frame_info (int fromleaf, struct frame_info *fi); - -/* Obtain return address of the frame. */ -CORE_ADDR cfi_get_ra (struct frame_info *fi); - -/* Find register number REGNUM relative to FRAME and put its - (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable - was optimized out (and thus can't be fetched). If the variable - was fetched from memory, set *ADDRP to where it was fetched from, - otherwise it was fetched from a register. - - The argument RAW_BUFFER must point to aligned memory. */ -void cfi_get_saved_register (char *raw_buffer, - int *optimized, - CORE_ADDR *addrp, - struct frame_info *frame, - int regnum, enum lval_type *lval); - -/* Return the register that the function uses for a frame pointer, - plus any necessary offset to be applied to the register before - any frame pointer offsets. */ -void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum, - LONGEST * frame_offset); - -struct context *context_alloc (); -void context_cpy (struct context *dst, struct context *src); -struct frame_state *frame_state_alloc (); -#endif |