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