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