GDB (API)
/home/stan/gdb/src/gdb/trad-frame.c
Go to the documentation of this file.
00001 /* Traditional frame unwind support, for GDB the GNU Debugger.
00002 
00003    Copyright (C) 2003-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "frame.h"
00022 #include "trad-frame.h"
00023 #include "regcache.h"
00024 #include "frame-unwind.h"
00025 #include "value.h"
00026 
00027 struct trad_frame_cache
00028 {
00029   struct frame_info *this_frame;
00030   CORE_ADDR this_base;
00031   struct trad_frame_saved_reg *prev_regs;
00032   struct frame_id this_id;
00033 };
00034 
00035 struct trad_frame_cache *
00036 trad_frame_cache_zalloc (struct frame_info *this_frame)
00037 {
00038   struct trad_frame_cache *this_trad_cache;
00039 
00040   this_trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
00041   this_trad_cache->prev_regs = trad_frame_alloc_saved_regs (this_frame);
00042   this_trad_cache->this_frame = this_frame;
00043   return this_trad_cache;
00044 }
00045 
00046 /* A traditional frame is unwound by analysing the function prologue
00047    and using the information gathered to track registers.  For
00048    non-optimized frames, the technique is reliable (just need to check
00049    for all potential instruction sequences).  */
00050 
00051 struct trad_frame_saved_reg *
00052 trad_frame_alloc_saved_regs (struct frame_info *this_frame)
00053 {
00054   int regnum;
00055   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00056   int numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
00057   struct trad_frame_saved_reg *this_saved_regs
00058     = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
00059 
00060   for (regnum = 0; regnum < numregs; regnum++)
00061     {
00062       this_saved_regs[regnum].realreg = regnum;
00063       this_saved_regs[regnum].addr = -1;
00064     }      
00065   return this_saved_regs;
00066 }
00067 
00068 enum { TF_REG_VALUE = -1, TF_REG_UNKNOWN = -2 };
00069 
00070 int
00071 trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
00072 {
00073   return (this_saved_regs[regnum].realreg == TF_REG_VALUE);
00074 }
00075 
00076 int
00077 trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
00078 {
00079   return (this_saved_regs[regnum].realreg >= 0
00080           && this_saved_regs[regnum].addr != -1);
00081 }
00082 
00083 int
00084 trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
00085                       int regnum)
00086 {
00087   return (this_saved_regs[regnum].realreg >= 0
00088           && this_saved_regs[regnum].addr == -1);
00089 }
00090 
00091 void
00092 trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
00093                       int regnum, LONGEST val)
00094 {
00095   /* Make the REALREG invalid, indicating that the ADDR contains the
00096      register's value.  */
00097   this_saved_regs[regnum].realreg = TF_REG_VALUE;
00098   this_saved_regs[regnum].addr = val;
00099 }
00100 
00101 void
00102 trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
00103                           int regnum, LONGEST val)
00104 {
00105   /* External interface for users of trad_frame_cache
00106      (who cannot access the prev_regs object directly).  */
00107   trad_frame_set_value (this_trad_cache->prev_regs, regnum, val);
00108 }
00109 
00110 void
00111 trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
00112                             int regnum, int realreg)
00113 {
00114   this_trad_cache->prev_regs[regnum].realreg = realreg;
00115   this_trad_cache->prev_regs[regnum].addr = -1;
00116 }
00117 
00118 void
00119 trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
00120                          int regnum, CORE_ADDR addr)
00121 {
00122   this_trad_cache->prev_regs[regnum].addr = addr;
00123 }
00124 
00125 void
00126 trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
00127                         int regnum)
00128 {
00129   /* Make the REALREG invalid, indicating that the value is not known.  */
00130   this_saved_regs[regnum].realreg = TF_REG_UNKNOWN;
00131   this_saved_regs[regnum].addr = -1;
00132 }
00133 
00134 struct value *
00135 trad_frame_get_prev_register (struct frame_info *this_frame,
00136                               struct trad_frame_saved_reg this_saved_regs[],
00137                               int regnum)
00138 {
00139   if (trad_frame_addr_p (this_saved_regs, regnum))
00140     /* The register was saved in memory.  */
00141     return frame_unwind_got_memory (this_frame, regnum,
00142                                     this_saved_regs[regnum].addr);
00143   else if (trad_frame_realreg_p (this_saved_regs, regnum))
00144     return frame_unwind_got_register (this_frame, regnum,
00145                                       this_saved_regs[regnum].realreg);
00146   else if (trad_frame_value_p (this_saved_regs, regnum))
00147     /* The register's value is available.  */
00148     return frame_unwind_got_constant (this_frame, regnum,
00149                                       this_saved_regs[regnum].addr);
00150   else
00151     return frame_unwind_got_optimized (this_frame, regnum);
00152 }
00153 
00154 struct value *
00155 trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
00156                          struct frame_info *this_frame,
00157                          int regnum)
00158 {
00159   return trad_frame_get_prev_register (this_frame, this_trad_cache->prev_regs,
00160                                        regnum);
00161 }
00162 
00163 void
00164 trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
00165                    struct frame_id this_id)
00166 {
00167   this_trad_cache->this_id = this_id;
00168 }
00169 
00170 void
00171 trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
00172                    struct frame_id *this_id)
00173 {
00174   (*this_id) = this_trad_cache->this_id;
00175 }
00176 
00177 void
00178 trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
00179                           CORE_ADDR this_base)
00180 {
00181   this_trad_cache->this_base = this_base;
00182 }
00183 
00184 CORE_ADDR
00185 trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache)
00186 {
00187   return this_trad_cache->this_base;
00188 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines