This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Dwarf2 virtual frame pointer


Hi,
The default frame pointer accessor only copes with a fixed frame pointer.
I've added a dwarf2_virtual_frame_pointer function, which can be enabled
with
 set_gdbarch_virtual_frame_pointer (gdbarch, dwarf2_virtual_frame_pointer)

It executes the cfa for the supplied PC and determines which register
is the frame pointer at that point.  I've not hooked it into any
existing architectures, but verified its functionality on an unrealeased
architecture where $sp or $fp might be the relevent register.

I've tested on i686-pc-linux-gnu also, ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-02-10  Nathan Sidwell  <nathan@codesourcery.com>

	* dwarf2-frame.c: #include arch-utils.h
	(execute_cfa_program): Take pc argument, not next_frame.  Adjust.
	(dwarf2_frame_cache): Adjust execute_cfa_program calls.
	(dwarf2_virtual_frame_pointer): New.
	* dwarf2-frame.h (dwarf2_virtual_frame_pointer): New.

Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.47
diff -c -3 -p -r1.47 dwarf2-frame.c
*** dwarf2-frame.c	20 Nov 2004 10:10:17 -0000	1.47
--- dwarf2-frame.c	10 Feb 2005 09:13:58 -0000
***************
*** 32,37 ****
--- 32,38 ----
  #include "symtab.h"
  #include "objfiles.h"
  #include "regcache.h"
+ #include "arch-utils.h"
  
  #include "gdb_assert.h"
  #include "gdb_string.h"
*************** execute_stack_op (unsigned char *exp, UL
*** 266,275 ****
  
  static void
  execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
! 		     struct frame_info *next_frame,
! 		     struct dwarf2_frame_state *fs)
  {
-   CORE_ADDR pc = frame_pc_unwind (next_frame);
    int bytes_read;
  
    while (insn_ptr < insn_end && fs->pc <= pc)
--- 267,274 ----
  
  static void
  execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
! 		     CORE_ADDR pc, struct dwarf2_frame_state *fs)
  {
    int bytes_read;
  
    while (insn_ptr < insn_end && fs->pc <= pc)
*************** dwarf2_frame_cache (struct frame_info *n
*** 599,604 ****
--- 598,604 ----
    struct dwarf2_frame_cache *cache;
    struct dwarf2_frame_state *fs;
    struct dwarf2_fde *fde;
+   CORE_ADDR pc;
  
    if (*this_cache)
      return *this_cache;
*************** dwarf2_frame_cache (struct frame_info *n
*** 628,634 ****
       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);
! 
    /* Find the correct FDE.  */
    fde = dwarf2_frame_find_fde (&fs->pc);
    gdb_assert (fde != NULL);
--- 628,635 ----
       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);
!   pc = frame_pc_unwind (next_frame);
!   
    /* Find the correct FDE.  */
    fde = dwarf2_frame_find_fde (&fs->pc);
    gdb_assert (fde != NULL);
*************** dwarf2_frame_cache (struct frame_info *n
*** 639,653 ****
    fs->retaddr_column = fde->cie->return_address_register;
  
    /* First decode all the insns in the CIE.  */
!   execute_cfa_program (fde->cie->initial_instructions,
! 		       fde->cie->end, next_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);
  
    /* Caclulate the CFA.  */
    switch (fs->cfa_how)
--- 640,654 ----
    fs->retaddr_column = fde->cie->return_address_register;
  
    /* First decode all the insns in the CIE.  */
!   execute_cfa_program (fde->cie->initial_instructions, fde->cie->end,
! 		       pc, 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, pc, fs);
  
    /* Caclulate the CFA.  */
    switch (fs->cfa_how)
*************** dwarf2_frame_base_sniffer (struct frame_
*** 938,943 ****
--- 939,1000 ----
    return NULL;
  }
  
+ 
+ /* Find the frame register that is in use at pc.  */
+ 
+ void
+ dwarf2_virtual_frame_pointer (CORE_ADDR pc,
+ 			      int *frame_regnum, LONGEST *frame_offset)
+ {
+   static CORE_ADDR cached_pc;
+   static int cached_regnum;
+   static int cached_offset;
+ 
+   if (cached_pc != pc)
+     {
+       struct cleanup *old_chain;
+       struct gdbarch *gdbarch = current_gdbarch; /* Bleah! */
+       struct dwarf2_frame_state *fs;
+       struct dwarf2_fde *fde;
+   
+       /* Allocate and initialize the frame state.  */
+       fs = XMALLOC (struct dwarf2_frame_state);
+       memset (fs, 0, sizeof (struct dwarf2_frame_state));
+       old_chain = make_cleanup (dwarf2_frame_state_free, fs);
+ 
+       fs->pc = pc;
+   
+       /* Find the correct FDE.  */
+       fde = dwarf2_frame_find_fde (&fs->pc);
+       if (!fde)
+ 	{
+ 	  legacy_virtual_frame_pointer (pc, frame_regnum, frame_offset);
+ 	  return;
+ 	}
+   
+       /* Extract any interesting information from the CIE.  */
+       fs->data_align = fde->cie->data_alignment_factor;
+       fs->code_align = fde->cie->code_alignment_factor;
+       fs->retaddr_column = fde->cie->return_address_register;
+       
+       /* First decode all the insns in the CIE.  */
+       execute_cfa_program (fde->cie->initial_instructions, fde->cie->end,
+ 			   pc, fs);
+ 
+       /* Then decode the insns in the FDE up to our target PC.  */
+       execute_cfa_program (fde->instructions, fde->end, pc, fs);
+ 
+       cached_pc = pc;
+       cached_regnum = DWARF2_REG_TO_REGNUM (fs->cfa_reg);
+       cached_offset = 0;
+       
+       do_cleanups (old_chain);
+     }
+   
+   *frame_regnum = cached_regnum;
+   *frame_offset = cached_offset;
+ }
+ 
  /* A minimal decoding of DWARF2 compilation units.  We only decode
     what's needed to get to the call frame information.  */
  
Index: dwarf2-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 dwarf2-frame.h
*** dwarf2-frame.h	7 Nov 2004 21:16:11 -0000	1.7
--- dwarf2-frame.h	10 Feb 2005 09:13:58 -0000
*************** extern const struct frame_base *
*** 103,106 ****
--- 103,109 ----
  
  void dwarf2_frame_build_info (struct objfile *objfile);
  
+ void dwarf2_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum,
+ 				   LONGEST *frame_offset);
+ 
  #endif /* dwarf2-frame.h */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]