OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [frame.c] - Diff between revs 1181 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1181 Rev 1765
/* Cache and manage frames for GDB, the GNU debugger.
/* Cache and manage frames for GDB, the GNU debugger.
 
 
   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
   2001, 2002 Free Software Foundation, Inc.
   2001, 2002 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   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 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "frame.h"
#include "frame.h"
#include "target.h"
#include "target.h"
#include "value.h"
#include "value.h"
#include "inferior.h"   /* for inferior_ptid */
#include "inferior.h"   /* for inferior_ptid */
#include "regcache.h"
#include "regcache.h"
#include "gdb_assert.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "builtin-regs.h"
#include "builtin-regs.h"
 
 
/* Return a frame uniq ID that can be used to, later re-find the
/* Return a frame uniq ID that can be used to, later re-find the
   frame.  */
   frame.  */
 
 
void
void
get_frame_id (struct frame_info *fi, struct frame_id *id)
get_frame_id (struct frame_info *fi, struct frame_id *id)
{
{
  if (fi == NULL)
  if (fi == NULL)
    {
    {
      id->base = 0;
      id->base = 0;
      id->pc = 0;
      id->pc = 0;
    }
    }
  else
  else
    {
    {
      id->base = FRAME_FP (fi);
      id->base = FRAME_FP (fi);
      id->pc = fi->pc;
      id->pc = fi->pc;
    }
    }
}
}
 
 
struct frame_info *
struct frame_info *
frame_find_by_id (struct frame_id id)
frame_find_by_id (struct frame_id id)
{
{
  struct frame_info *frame;
  struct frame_info *frame;
 
 
  /* ZERO denotes the null frame, let the caller decide what to do
  /* ZERO denotes the null frame, let the caller decide what to do
     about it.  Should it instead return get_current_frame()?  */
     about it.  Should it instead return get_current_frame()?  */
  if (id.base == 0 && id.pc == 0)
  if (id.base == 0 && id.pc == 0)
    return NULL;
    return NULL;
 
 
  for (frame = get_current_frame ();
  for (frame = get_current_frame ();
       frame != NULL;
       frame != NULL;
       frame = get_prev_frame (frame))
       frame = get_prev_frame (frame))
    {
    {
      if (INNER_THAN (FRAME_FP (frame), id.base))
      if (INNER_THAN (FRAME_FP (frame), id.base))
        /* ``inner/current < frame < id.base''.  Keep looking along
        /* ``inner/current < frame < id.base''.  Keep looking along
           the frame chain.  */
           the frame chain.  */
        continue;
        continue;
      if (INNER_THAN (id.base, FRAME_FP (frame)))
      if (INNER_THAN (id.base, FRAME_FP (frame)))
        /* ``inner/current < id.base < frame''.  Oops, gone past it.
        /* ``inner/current < id.base < frame''.  Oops, gone past it.
           Just give up.  */
           Just give up.  */
        return NULL;
        return NULL;
      /* FIXME: cagney/2002-04-21: This isn't sufficient.  It should
      /* FIXME: cagney/2002-04-21: This isn't sufficient.  It should
         use id.pc to check that the two frames belong to the same
         use id.pc to check that the two frames belong to the same
         function.  Otherwise we'll do things like match dummy frames
         function.  Otherwise we'll do things like match dummy frames
         or mis-match frameless functions.  However, until someone
         or mis-match frameless functions.  However, until someone
         notices, stick with the existing behavour.  */
         notices, stick with the existing behavour.  */
      return frame;
      return frame;
    }
    }
  return NULL;
  return NULL;
}
}
 
 
/* FIND_SAVED_REGISTER ()
/* FIND_SAVED_REGISTER ()
 
 
   Return the address in which frame FRAME's value of register REGNUM
   Return the address in which frame FRAME's value of register REGNUM
   has been saved in memory.  Or return zero if it has not been saved.
   has been saved in memory.  Or return zero if it has not been saved.
   If REGNUM specifies the SP, the value we return is actually
   If REGNUM specifies the SP, the value we return is actually
   the SP value, not an address where it was saved.  */
   the SP value, not an address where it was saved.  */
 
 
CORE_ADDR
CORE_ADDR
find_saved_register (struct frame_info *frame, int regnum)
find_saved_register (struct frame_info *frame, int regnum)
{
{
  register struct frame_info *frame1 = NULL;
  register struct frame_info *frame1 = NULL;
  register CORE_ADDR addr = 0;
  register CORE_ADDR addr = 0;
 
 
  if (frame == NULL)            /* No regs saved if want current frame */
  if (frame == NULL)            /* No regs saved if want current frame */
    return 0;
    return 0;
 
 
  /* Note that the following loop assumes that registers used in
  /* Note that the following loop assumes that registers used in
     frame x will be saved only in the frame that x calls and frames
     frame x will be saved only in the frame that x calls and frames
     interior to it.  */
     interior to it.  */
  while (1)
  while (1)
    {
    {
      QUIT;
      QUIT;
      frame1 = get_next_frame (frame);
      frame1 = get_next_frame (frame);
      if (frame1 == 0)
      if (frame1 == 0)
        break;
        break;
      frame = frame1;
      frame = frame1;
      FRAME_INIT_SAVED_REGS (frame1);
      FRAME_INIT_SAVED_REGS (frame1);
      if (frame1->saved_regs[regnum])
      if (frame1->saved_regs[regnum])
        {
        {
          addr = frame1->saved_regs[regnum];
          addr = frame1->saved_regs[regnum];
          break;
          break;
        }
        }
    }
    }
 
 
  return addr;
  return addr;
}
}
 
 
void
void
frame_register_unwind (struct frame_info *frame, int regnum,
frame_register_unwind (struct frame_info *frame, int regnum,
                       int *optimizedp, enum lval_type *lvalp,
                       int *optimizedp, enum lval_type *lvalp,
                       CORE_ADDR *addrp, int *realnump, void *bufferp)
                       CORE_ADDR *addrp, int *realnump, void *bufferp)
{
{
  struct frame_unwind_cache *cache;
  struct frame_unwind_cache *cache;
 
 
  /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
  /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
     that the value proper does not need to be fetched.  */
     that the value proper does not need to be fetched.  */
  gdb_assert (optimizedp != NULL);
  gdb_assert (optimizedp != NULL);
  gdb_assert (lvalp != NULL);
  gdb_assert (lvalp != NULL);
  gdb_assert (addrp != NULL);
  gdb_assert (addrp != NULL);
  gdb_assert (realnump != NULL);
  gdb_assert (realnump != NULL);
  /* gdb_assert (bufferp != NULL); */
  /* gdb_assert (bufferp != NULL); */
 
 
  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
     special case, there was always an inner frame dedicated to the
     special case, there was always an inner frame dedicated to the
     hardware registers.  Unfortunatly, there is too much unwind code
     hardware registers.  Unfortunatly, there is too much unwind code
     around that looks up/down the frame chain while making the
     around that looks up/down the frame chain while making the
     assumption that each frame level is using the same unwind code.  */
     assumption that each frame level is using the same unwind code.  */
 
 
  if (frame == NULL)
  if (frame == NULL)
    {
    {
      /* We're in the inner-most frame, get the value direct from the
      /* We're in the inner-most frame, get the value direct from the
         register cache.  */
         register cache.  */
      *optimizedp = 0;
      *optimizedp = 0;
      *lvalp = lval_register;
      *lvalp = lval_register;
      /* ULGH!  Code uses the offset into the raw register byte array
      /* ULGH!  Code uses the offset into the raw register byte array
         as a way of identifying a register.  */
         as a way of identifying a register.  */
      *addrp = REGISTER_BYTE (regnum);
      *addrp = REGISTER_BYTE (regnum);
      /* Should this code test ``register_cached (regnum) < 0'' and do
      /* Should this code test ``register_cached (regnum) < 0'' and do
         something like set realnum to -1 when the register isn't
         something like set realnum to -1 when the register isn't
         available?  */
         available?  */
      *realnump = regnum;
      *realnump = regnum;
      if (bufferp)
      if (bufferp)
        read_register_gen (regnum, bufferp);
        read_register_gen (regnum, bufferp);
      return;
      return;
    }
    }
 
 
  /* Ask this frame to unwind its register.  */
  /* Ask this frame to unwind its register.  */
  frame->register_unwind (frame, &frame->register_unwind_cache, regnum,
  frame->register_unwind (frame, &frame->register_unwind_cache, regnum,
                          optimizedp, lvalp, addrp, realnump, bufferp);
                          optimizedp, lvalp, addrp, realnump, bufferp);
}
}
 
 
 
 
void
void
generic_unwind_get_saved_register (char *raw_buffer,
generic_unwind_get_saved_register (char *raw_buffer,
                                   int *optimizedp,
                                   int *optimizedp,
                                   CORE_ADDR *addrp,
                                   CORE_ADDR *addrp,
                                   struct frame_info *frame,
                                   struct frame_info *frame,
                                   int regnum,
                                   int regnum,
                                   enum lval_type *lvalp)
                                   enum lval_type *lvalp)
{
{
  int optimizedx;
  int optimizedx;
  CORE_ADDR addrx;
  CORE_ADDR addrx;
  int realnumx;
  int realnumx;
  enum lval_type lvalx;
  enum lval_type lvalx;
 
 
  if (!target_has_registers)
  if (!target_has_registers)
    error ("No registers.");
    error ("No registers.");
 
 
  /* Keep things simple, ensure that all the pointers (except valuep)
  /* Keep things simple, ensure that all the pointers (except valuep)
     are non NULL.  */
     are non NULL.  */
  if (optimizedp == NULL)
  if (optimizedp == NULL)
    optimizedp = &optimizedx;
    optimizedp = &optimizedx;
  if (lvalp == NULL)
  if (lvalp == NULL)
    lvalp = &lvalx;
    lvalp = &lvalx;
  if (addrp == NULL)
  if (addrp == NULL)
    addrp = &addrx;
    addrp = &addrx;
 
 
  /* Reached the the bottom (youngest, inner most) of the frame chain
  /* Reached the the bottom (youngest, inner most) of the frame chain
     (youngest, inner most) frame, go direct to the hardware register
     (youngest, inner most) frame, go direct to the hardware register
     cache (do not pass go, do not try to cache the value, ...).  The
     cache (do not pass go, do not try to cache the value, ...).  The
     unwound value would have been cached in frame->next but that
     unwound value would have been cached in frame->next but that
     doesn't exist.  This doesn't matter as the hardware register
     doesn't exist.  This doesn't matter as the hardware register
     cache is stopping any unnecessary accesses to the target.  */
     cache is stopping any unnecessary accesses to the target.  */
 
 
  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
     special case, there was always an inner frame dedicated to the
     special case, there was always an inner frame dedicated to the
     hardware registers.  Unfortunatly, there is too much unwind code
     hardware registers.  Unfortunatly, there is too much unwind code
     around that looks up/down the frame chain while making the
     around that looks up/down the frame chain while making the
     assumption that each frame level is using the same unwind code.  */
     assumption that each frame level is using the same unwind code.  */
 
 
  if (frame == NULL)
  if (frame == NULL)
    frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, &realnumx,
    frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, &realnumx,
                           raw_buffer);
                           raw_buffer);
  else
  else
    frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
    frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
                           &realnumx, raw_buffer);
                           &realnumx, raw_buffer);
}
}
 
 
void
void
get_saved_register (char *raw_buffer,
get_saved_register (char *raw_buffer,
                    int *optimized,
                    int *optimized,
                    CORE_ADDR *addrp,
                    CORE_ADDR *addrp,
                    struct frame_info *frame,
                    struct frame_info *frame,
                    int regnum,
                    int regnum,
                    enum lval_type *lval)
                    enum lval_type *lval)
{
{
  GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
  GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
}
}
 
 
/* frame_register_read ()
/* frame_register_read ()
 
 
   Find and return the value of REGNUM for the specified stack frame.
   Find and return the value of REGNUM for the specified stack frame.
   The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
   The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
 
 
   Returns 0 if the register value could not be found.  */
   Returns 0 if the register value could not be found.  */
 
 
int
int
frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
{
{
  int optim;
  int optim;
  get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
  get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
                      regnum, (enum lval_type *) NULL);
                      regnum, (enum lval_type *) NULL);
 
 
  /* FIXME: cagney/2002-05-15: This test, is just bogus.
  /* FIXME: cagney/2002-05-15: This test, is just bogus.
 
 
     It indicates that the target failed to supply a value for a
     It indicates that the target failed to supply a value for a
     register because it was "not available" at this time.  Problem
     register because it was "not available" at this time.  Problem
     is, the target still has the register and so get saved_register()
     is, the target still has the register and so get saved_register()
     may be returning a value saved on the stack.  */
     may be returning a value saved on the stack.  */
 
 
  if (register_cached (regnum) < 0)
  if (register_cached (regnum) < 0)
    return 0;                    /* register value not available */
    return 0;                    /* register value not available */
 
 
  return !optim;
  return !optim;
}
}
 
 
 
 
/* Map between a frame register number and its name.  A frame register
/* Map between a frame register number and its name.  A frame register
   space is a superset of the cooked register space --- it also
   space is a superset of the cooked register space --- it also
   includes builtin registers.  */
   includes builtin registers.  */
 
 
int
int
frame_map_name_to_regnum (const char *name, int len)
frame_map_name_to_regnum (const char *name, int len)
{
{
  int i;
  int i;
 
 
  /* Search register name space. */
  /* Search register name space. */
  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
    if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
    if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
        && strncmp (name, REGISTER_NAME (i), len) == 0)
        && strncmp (name, REGISTER_NAME (i), len) == 0)
      {
      {
        return i;
        return i;
      }
      }
 
 
  /* Try builtin registers.  */
  /* Try builtin registers.  */
  i = builtin_reg_map_name_to_regnum (name, len);
  i = builtin_reg_map_name_to_regnum (name, len);
  if (i >= 0)
  if (i >= 0)
    {
    {
      /* A builtin register doesn't fall into the architecture's
      /* A builtin register doesn't fall into the architecture's
         register range.  */
         register range.  */
      gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS);
      gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS);
      return i;
      return i;
    }
    }
 
 
  return -1;
  return -1;
}
}
 
 
const char *
const char *
frame_map_regnum_to_name (int regnum)
frame_map_regnum_to_name (int regnum)
{
{
  if (regnum < 0)
  if (regnum < 0)
    return NULL;
    return NULL;
  if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
  if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
    return REGISTER_NAME (regnum);
    return REGISTER_NAME (regnum);
  return builtin_reg_map_regnum_to_name (regnum);
  return builtin_reg_map_regnum_to_name (regnum);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.