Updated copyright notices for most files.
[deliverable/binutils-gdb.git] / gdb / tramp-frame.c
CommitLineData
d2259dd3
AC
1/* Signal trampoline unwinder, for GDB the GNU Debugger.
2
0fb0cc75 3 Copyright (C) 2004, 2007, 2008, 2009 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{
25492ce3 47 CORE_ADDR pc = get_frame_pc (this_frame);
d2259dd3
AC
48 struct tramp_frame_cache *tramp_cache = (*this_cache);
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);
d2259dd3
AC
67 trad_frame_get_id (trad_cache, this_id);
68}
69
25492ce3
DJ
70static struct value *
71tramp_frame_prev_register (struct frame_info *this_frame,
d2259dd3 72 void **this_cache,
25492ce3 73 int prev_regnum)
d2259dd3
AC
74{
75 struct trad_frame_cache *trad_cache
25492ce3
DJ
76 = tramp_frame_cache (this_frame, this_cache);
77 return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
d2259dd3
AC
78}
79
80static CORE_ADDR
304396fb 81tramp_frame_start (const struct tramp_frame *tramp,
25492ce3 82 struct frame_info *this_frame, CORE_ADDR pc)
d2259dd3
AC
83{
84 int ti;
85 /* Search through the trampoline for one that matches the
86 instruction sequence around PC. */
2cd8546d 87 for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
d2259dd3
AC
88 {
89 CORE_ADDR func = pc - tramp->insn_size * ti;
90 int i;
91 for (i = 0; 1; i++)
92 {
fc1a4b47 93 gdb_byte buf[sizeof (tramp->insn[0])];
1196bfda 94 ULONGEST insn;
2cd8546d 95 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
d2259dd3 96 return func;
25492ce3 97 if (!safe_frame_unwind_memory (this_frame,
304396fb
AC
98 func + i * tramp->insn_size,
99 buf, tramp->insn_size))
d2259dd3
AC
100 break;
101 insn = extract_unsigned_integer (buf, tramp->insn_size);
2cd8546d 102 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
d2259dd3
AC
103 break;
104 }
105 }
106 /* Trampoline doesn't match. */
107 return 0;
108}
109
110static int
111tramp_frame_sniffer (const struct frame_unwind *self,
25492ce3 112 struct frame_info *this_frame,
d2259dd3
AC
113 void **this_cache)
114{
115 const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
25492ce3 116 CORE_ADDR pc = get_frame_pc (this_frame);
d2259dd3 117 CORE_ADDR func;
d2259dd3
AC
118 struct tramp_frame_cache *tramp_cache;
119
0efcf9dc
RC
120 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
121 section, then this is not a trampoline. However, this assumption is
122 false on HPUX which has a signal trampoline that has a name; it can
123 also be false when using an alternative signal stack. */
25492ce3 124 func = tramp_frame_start (tramp, this_frame, pc);
d2259dd3
AC
125 if (func == 0)
126 return 0;
127 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
128 tramp_cache->func = func;
129 tramp_cache->tramp_frame = tramp;
130 (*this_cache) = tramp_cache;
131 return 1;
132}
133
134void
fb2be677
AC
135tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
136 const struct tramp_frame *tramp_frame)
d2259dd3
AC
137{
138 struct frame_data *data;
139 struct frame_unwind *unwinder;
1196bfda
AC
140 int i;
141
142 /* Check that the instruction sequence contains a sentinel. */
143 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
144 {
2cd8546d 145 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
1196bfda
AC
146 break;
147 }
148 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
2cd8546d 149 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
d2259dd3
AC
150
151 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
152 unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
153
154 data->tramp_frame = tramp_frame;
1f586765 155 unwinder->type = tramp_frame->frame_type;
d2259dd3
AC
156 unwinder->unwind_data = data;
157 unwinder->sniffer = tramp_frame_sniffer;
158 unwinder->this_id = tramp_frame_this_id;
159 unwinder->prev_register = tramp_frame_prev_register;
fb2be677 160 frame_unwind_prepend_unwinder (gdbarch, unwinder);
d2259dd3 161}
This page took 0.43302 seconds and 4 git commands to generate.