GDB (API)
/home/stan/gdb/src/gdb/tramp-frame.c
Go to the documentation of this file.
00001 /* Signal trampoline unwinder, for GDB the GNU Debugger.
00002 
00003    Copyright (C) 2004-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 "tramp-frame.h"
00022 #include "frame-unwind.h"
00023 #include "gdbcore.h"
00024 #include "symtab.h"
00025 #include "objfiles.h"
00026 #include "target.h"
00027 #include "trad-frame.h"
00028 #include "frame-base.h"
00029 #include "gdb_assert.h"
00030 
00031 struct frame_data
00032 {
00033   const struct tramp_frame *tramp_frame;
00034 };
00035 
00036 struct tramp_frame_cache
00037 {
00038   CORE_ADDR func;
00039   const struct tramp_frame *tramp_frame;
00040   struct trad_frame_cache *trad_cache;
00041 };
00042 
00043 static struct trad_frame_cache *
00044 tramp_frame_cache (struct frame_info *this_frame,
00045                    void **this_cache)
00046 {
00047   struct tramp_frame_cache *tramp_cache = (*this_cache);
00048 
00049   if (tramp_cache->trad_cache == NULL)
00050     {
00051       tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame);
00052       tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
00053                                       this_frame,
00054                                       tramp_cache->trad_cache,
00055                                       tramp_cache->func);
00056     }
00057   return tramp_cache->trad_cache;
00058 }
00059 
00060 static void
00061 tramp_frame_this_id (struct frame_info *this_frame,
00062                      void **this_cache,
00063                      struct frame_id *this_id)
00064 {
00065   struct trad_frame_cache *trad_cache
00066     = tramp_frame_cache (this_frame, this_cache);
00067 
00068   trad_frame_get_id (trad_cache, this_id);
00069 }
00070 
00071 static struct value *
00072 tramp_frame_prev_register (struct frame_info *this_frame,
00073                            void **this_cache,
00074                            int prev_regnum)
00075 {
00076   struct trad_frame_cache *trad_cache
00077     = tramp_frame_cache (this_frame, this_cache);
00078 
00079   return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
00080 }
00081 
00082 static CORE_ADDR
00083 tramp_frame_start (const struct tramp_frame *tramp,
00084                    struct frame_info *this_frame, CORE_ADDR pc)
00085 {
00086   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00087   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00088   int ti;
00089 
00090   /* Search through the trampoline for one that matches the
00091      instruction sequence around PC.  */
00092   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
00093     {
00094       CORE_ADDR func = pc - tramp->insn_size * ti;
00095       int i;
00096 
00097       for (i = 0; 1; i++)
00098         {
00099           gdb_byte buf[sizeof (tramp->insn[0])];
00100           ULONGEST insn;
00101 
00102           if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
00103             return func;
00104           if (!safe_frame_unwind_memory (this_frame,
00105                                          func + i * tramp->insn_size,
00106                                          buf, tramp->insn_size))
00107             break;
00108           insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
00109           if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
00110             break;
00111         }
00112     }
00113   /* Trampoline doesn't match.  */
00114   return 0;
00115 }
00116 
00117 static int
00118 tramp_frame_sniffer (const struct frame_unwind *self,
00119                      struct frame_info *this_frame,
00120                      void **this_cache)
00121 {
00122   const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
00123   CORE_ADDR pc = get_frame_pc (this_frame);
00124   CORE_ADDR func;
00125   struct tramp_frame_cache *tramp_cache;
00126 
00127   /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid 
00128      section, then this is not a trampoline.  However, this assumption is
00129      false on HPUX which has a signal trampoline that has a name; it can
00130      also be false when using an alternative signal stack.  */
00131   func = tramp_frame_start (tramp, this_frame, pc);
00132   if (func == 0)
00133     return 0;
00134   tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
00135   tramp_cache->func = func;
00136   tramp_cache->tramp_frame = tramp;
00137   (*this_cache) = tramp_cache;
00138   return 1;
00139 }
00140 
00141 void
00142 tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
00143                               const struct tramp_frame *tramp_frame)
00144 {
00145   struct frame_data *data;
00146   struct frame_unwind *unwinder;
00147   int i;
00148 
00149   /* Check that the instruction sequence contains a sentinel.  */
00150   for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
00151     {
00152       if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
00153         break;
00154     }
00155   gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
00156   gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
00157 
00158   data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
00159   unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
00160 
00161   data->tramp_frame = tramp_frame;
00162   unwinder->type = tramp_frame->frame_type;
00163   unwinder->unwind_data = data;
00164   unwinder->sniffer = tramp_frame_sniffer;
00165   unwinder->stop_reason = default_frame_unwind_stop_reason;
00166   unwinder->this_id = tramp_frame_this_id;
00167   unwinder->prev_register = tramp_frame_prev_register;
00168   frame_unwind_prepend_unwinder (gdbarch, unwinder);
00169 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines