xref: /dflybsd-src/contrib/gdb-7/gdb/tramp-frame.c (revision 5796c8dc12c637f18a1740c26afd8d40ffa9b719)
1*5796c8dcSSimon Schubert /* Signal trampoline unwinder, for GDB the GNU Debugger.
2*5796c8dcSSimon Schubert 
3*5796c8dcSSimon Schubert    Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
4*5796c8dcSSimon Schubert 
5*5796c8dcSSimon Schubert    This file is part of GDB.
6*5796c8dcSSimon Schubert 
7*5796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
8*5796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
9*5796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
10*5796c8dcSSimon Schubert    (at your option) any later version.
11*5796c8dcSSimon Schubert 
12*5796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
13*5796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*5796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*5796c8dcSSimon Schubert    GNU General Public License for more details.
16*5796c8dcSSimon Schubert 
17*5796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
18*5796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*5796c8dcSSimon Schubert 
20*5796c8dcSSimon Schubert #include "defs.h"
21*5796c8dcSSimon Schubert #include "tramp-frame.h"
22*5796c8dcSSimon Schubert #include "frame-unwind.h"
23*5796c8dcSSimon Schubert #include "gdbcore.h"
24*5796c8dcSSimon Schubert #include "symtab.h"
25*5796c8dcSSimon Schubert #include "objfiles.h"
26*5796c8dcSSimon Schubert #include "target.h"
27*5796c8dcSSimon Schubert #include "trad-frame.h"
28*5796c8dcSSimon Schubert #include "frame-base.h"
29*5796c8dcSSimon Schubert #include "gdb_assert.h"
30*5796c8dcSSimon Schubert 
31*5796c8dcSSimon Schubert struct frame_data
32*5796c8dcSSimon Schubert {
33*5796c8dcSSimon Schubert   const struct tramp_frame *tramp_frame;
34*5796c8dcSSimon Schubert };
35*5796c8dcSSimon Schubert 
36*5796c8dcSSimon Schubert struct tramp_frame_cache
37*5796c8dcSSimon Schubert {
38*5796c8dcSSimon Schubert   CORE_ADDR func;
39*5796c8dcSSimon Schubert   const struct tramp_frame *tramp_frame;
40*5796c8dcSSimon Schubert   struct trad_frame_cache *trad_cache;
41*5796c8dcSSimon Schubert };
42*5796c8dcSSimon Schubert 
43*5796c8dcSSimon Schubert static struct trad_frame_cache *
44*5796c8dcSSimon Schubert tramp_frame_cache (struct frame_info *this_frame,
45*5796c8dcSSimon Schubert 		   void **this_cache)
46*5796c8dcSSimon Schubert {
47*5796c8dcSSimon Schubert   CORE_ADDR pc = get_frame_pc (this_frame);
48*5796c8dcSSimon Schubert   struct tramp_frame_cache *tramp_cache = (*this_cache);
49*5796c8dcSSimon Schubert   if (tramp_cache->trad_cache == NULL)
50*5796c8dcSSimon Schubert     {
51*5796c8dcSSimon Schubert       tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame);
52*5796c8dcSSimon Schubert       tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
53*5796c8dcSSimon Schubert 				      this_frame,
54*5796c8dcSSimon Schubert 				      tramp_cache->trad_cache,
55*5796c8dcSSimon Schubert 				      tramp_cache->func);
56*5796c8dcSSimon Schubert     }
57*5796c8dcSSimon Schubert   return tramp_cache->trad_cache;
58*5796c8dcSSimon Schubert }
59*5796c8dcSSimon Schubert 
60*5796c8dcSSimon Schubert static void
61*5796c8dcSSimon Schubert tramp_frame_this_id (struct frame_info *this_frame,
62*5796c8dcSSimon Schubert 		     void **this_cache,
63*5796c8dcSSimon Schubert 		     struct frame_id *this_id)
64*5796c8dcSSimon Schubert {
65*5796c8dcSSimon Schubert   struct trad_frame_cache *trad_cache
66*5796c8dcSSimon Schubert     = tramp_frame_cache (this_frame, this_cache);
67*5796c8dcSSimon Schubert   trad_frame_get_id (trad_cache, this_id);
68*5796c8dcSSimon Schubert }
69*5796c8dcSSimon Schubert 
70*5796c8dcSSimon Schubert static struct value *
71*5796c8dcSSimon Schubert tramp_frame_prev_register (struct frame_info *this_frame,
72*5796c8dcSSimon Schubert 			   void **this_cache,
73*5796c8dcSSimon Schubert 			   int prev_regnum)
74*5796c8dcSSimon Schubert {
75*5796c8dcSSimon Schubert   struct trad_frame_cache *trad_cache
76*5796c8dcSSimon Schubert     = tramp_frame_cache (this_frame, this_cache);
77*5796c8dcSSimon Schubert   return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
78*5796c8dcSSimon Schubert }
79*5796c8dcSSimon Schubert 
80*5796c8dcSSimon Schubert static CORE_ADDR
81*5796c8dcSSimon Schubert tramp_frame_start (const struct tramp_frame *tramp,
82*5796c8dcSSimon Schubert 		   struct frame_info *this_frame, CORE_ADDR pc)
83*5796c8dcSSimon Schubert {
84*5796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (this_frame);
85*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
86*5796c8dcSSimon Schubert   int ti;
87*5796c8dcSSimon Schubert   /* Search through the trampoline for one that matches the
88*5796c8dcSSimon Schubert      instruction sequence around PC.  */
89*5796c8dcSSimon Schubert   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
90*5796c8dcSSimon Schubert     {
91*5796c8dcSSimon Schubert       CORE_ADDR func = pc - tramp->insn_size * ti;
92*5796c8dcSSimon Schubert       int i;
93*5796c8dcSSimon Schubert       for (i = 0; 1; i++)
94*5796c8dcSSimon Schubert 	{
95*5796c8dcSSimon Schubert 	  gdb_byte buf[sizeof (tramp->insn[0])];
96*5796c8dcSSimon Schubert 	  ULONGEST insn;
97*5796c8dcSSimon Schubert 	  if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
98*5796c8dcSSimon Schubert 	    return func;
99*5796c8dcSSimon Schubert 	  if (!safe_frame_unwind_memory (this_frame,
100*5796c8dcSSimon Schubert 					 func + i * tramp->insn_size,
101*5796c8dcSSimon Schubert 					 buf, tramp->insn_size))
102*5796c8dcSSimon Schubert 	    break;
103*5796c8dcSSimon Schubert 	  insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
104*5796c8dcSSimon Schubert 	  if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
105*5796c8dcSSimon Schubert 	    break;
106*5796c8dcSSimon Schubert 	}
107*5796c8dcSSimon Schubert     }
108*5796c8dcSSimon Schubert   /* Trampoline doesn't match.  */
109*5796c8dcSSimon Schubert   return 0;
110*5796c8dcSSimon Schubert }
111*5796c8dcSSimon Schubert 
112*5796c8dcSSimon Schubert static int
113*5796c8dcSSimon Schubert tramp_frame_sniffer (const struct frame_unwind *self,
114*5796c8dcSSimon Schubert 		     struct frame_info *this_frame,
115*5796c8dcSSimon Schubert 		     void **this_cache)
116*5796c8dcSSimon Schubert {
117*5796c8dcSSimon Schubert   const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
118*5796c8dcSSimon Schubert   CORE_ADDR pc = get_frame_pc (this_frame);
119*5796c8dcSSimon Schubert   CORE_ADDR func;
120*5796c8dcSSimon Schubert   struct tramp_frame_cache *tramp_cache;
121*5796c8dcSSimon Schubert 
122*5796c8dcSSimon Schubert   /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
123*5796c8dcSSimon Schubert      section, then this is not a trampoline.  However, this assumption is
124*5796c8dcSSimon Schubert      false on HPUX which has a signal trampoline that has a name; it can
125*5796c8dcSSimon Schubert      also be false when using an alternative signal stack.  */
126*5796c8dcSSimon Schubert   func = tramp_frame_start (tramp, this_frame, pc);
127*5796c8dcSSimon Schubert   if (func == 0)
128*5796c8dcSSimon Schubert     return 0;
129*5796c8dcSSimon Schubert   tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
130*5796c8dcSSimon Schubert   tramp_cache->func = func;
131*5796c8dcSSimon Schubert   tramp_cache->tramp_frame = tramp;
132*5796c8dcSSimon Schubert   (*this_cache) = tramp_cache;
133*5796c8dcSSimon Schubert   return 1;
134*5796c8dcSSimon Schubert }
135*5796c8dcSSimon Schubert 
136*5796c8dcSSimon Schubert void
137*5796c8dcSSimon Schubert tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
138*5796c8dcSSimon Schubert 			      const struct tramp_frame *tramp_frame)
139*5796c8dcSSimon Schubert {
140*5796c8dcSSimon Schubert   struct frame_data *data;
141*5796c8dcSSimon Schubert   struct frame_unwind *unwinder;
142*5796c8dcSSimon Schubert   int i;
143*5796c8dcSSimon Schubert 
144*5796c8dcSSimon Schubert   /* Check that the instruction sequence contains a sentinel.  */
145*5796c8dcSSimon Schubert   for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
146*5796c8dcSSimon Schubert     {
147*5796c8dcSSimon Schubert       if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
148*5796c8dcSSimon Schubert 	break;
149*5796c8dcSSimon Schubert     }
150*5796c8dcSSimon Schubert   gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
151*5796c8dcSSimon Schubert   gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
152*5796c8dcSSimon Schubert 
153*5796c8dcSSimon Schubert   data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
154*5796c8dcSSimon Schubert   unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
155*5796c8dcSSimon Schubert 
156*5796c8dcSSimon Schubert   data->tramp_frame = tramp_frame;
157*5796c8dcSSimon Schubert   unwinder->type = tramp_frame->frame_type;
158*5796c8dcSSimon Schubert   unwinder->unwind_data = data;
159*5796c8dcSSimon Schubert   unwinder->sniffer = tramp_frame_sniffer;
160*5796c8dcSSimon Schubert   unwinder->this_id = tramp_frame_this_id;
161*5796c8dcSSimon Schubert   unwinder->prev_register = tramp_frame_prev_register;
162*5796c8dcSSimon Schubert   frame_unwind_prepend_unwinder (gdbarch, unwinder);
163*5796c8dcSSimon Schubert }
164