Switch the license of all .c files to GPLv3.
[deliverable/binutils-gdb.git] / gdb / tramp-frame.c
CommitLineData
d2259dd3
AC
1/* Signal trampoline unwinder, for GDB the GNU Debugger.
2
6aba47ca 3 Copyright (C) 2004, 2007 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 *
44tramp_frame_cache (struct frame_info *next_frame,
45 void **this_cache)
46{
47 CORE_ADDR pc = frame_pc_unwind (next_frame);
48 struct tramp_frame_cache *tramp_cache = (*this_cache);
49 if (tramp_cache->trad_cache == NULL)
50 {
51 tramp_cache->trad_cache = trad_frame_cache_zalloc (next_frame);
52 tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
53 next_frame,
54 tramp_cache->trad_cache,
55 tramp_cache->func);
56 }
57 return tramp_cache->trad_cache;
58}
59
60static void
61tramp_frame_this_id (struct frame_info *next_frame,
62 void **this_cache,
63 struct frame_id *this_id)
64{
65 struct trad_frame_cache *trad_cache
66 = tramp_frame_cache (next_frame, this_cache);
67 trad_frame_get_id (trad_cache, this_id);
68}
69
70static void
71tramp_frame_prev_register (struct frame_info *next_frame,
72 void **this_cache,
73 int prev_regnum,
74 int *optimizedp,
75 enum lval_type * lvalp,
76 CORE_ADDR *addrp,
10c42a71 77 int *realnump, gdb_byte *valuep)
d2259dd3
AC
78{
79 struct trad_frame_cache *trad_cache
80 = tramp_frame_cache (next_frame, this_cache);
81 trad_frame_get_register (trad_cache, next_frame, prev_regnum, optimizedp,
82 lvalp, addrp, realnump, valuep);
83}
84
85static CORE_ADDR
304396fb
AC
86tramp_frame_start (const struct tramp_frame *tramp,
87 struct frame_info *next_frame, CORE_ADDR pc)
d2259dd3
AC
88{
89 int ti;
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;
96 for (i = 0; 1; i++)
97 {
fc1a4b47 98 gdb_byte buf[sizeof (tramp->insn[0])];
1196bfda 99 ULONGEST insn;
2cd8546d 100 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
d2259dd3 101 return func;
304396fb
AC
102 if (!safe_frame_unwind_memory (next_frame,
103 func + i * tramp->insn_size,
104 buf, tramp->insn_size))
d2259dd3
AC
105 break;
106 insn = extract_unsigned_integer (buf, tramp->insn_size);
2cd8546d 107 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
d2259dd3
AC
108 break;
109 }
110 }
111 /* Trampoline doesn't match. */
112 return 0;
113}
114
115static int
116tramp_frame_sniffer (const struct frame_unwind *self,
117 struct frame_info *next_frame,
118 void **this_cache)
119{
120 const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
121 CORE_ADDR pc = frame_pc_unwind (next_frame);
122 CORE_ADDR func;
d2259dd3
AC
123 struct tramp_frame_cache *tramp_cache;
124
0efcf9dc
RC
125 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
126 section, then this is not a trampoline. However, this assumption is
127 false on HPUX which has a signal trampoline that has a name; it can
128 also be false when using an alternative signal stack. */
304396fb 129 func = tramp_frame_start (tramp, next_frame, pc);
d2259dd3
AC
130 if (func == 0)
131 return 0;
132 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
133 tramp_cache->func = func;
134 tramp_cache->tramp_frame = tramp;
135 (*this_cache) = tramp_cache;
136 return 1;
137}
138
139void
fb2be677
AC
140tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
141 const struct tramp_frame *tramp_frame)
d2259dd3
AC
142{
143 struct frame_data *data;
144 struct frame_unwind *unwinder;
1196bfda
AC
145 int i;
146
147 /* Check that the instruction sequence contains a sentinel. */
148 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
149 {
2cd8546d 150 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
1196bfda
AC
151 break;
152 }
153 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
2cd8546d 154 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
d2259dd3
AC
155
156 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
157 unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
158
159 data->tramp_frame = tramp_frame;
1f586765 160 unwinder->type = tramp_frame->frame_type;
d2259dd3
AC
161 unwinder->unwind_data = data;
162 unwinder->sniffer = tramp_frame_sniffer;
163 unwinder->this_id = tramp_frame_this_id;
164 unwinder->prev_register = tramp_frame_prev_register;
fb2be677 165 frame_unwind_prepend_unwinder (gdbarch, unwinder);
d2259dd3 166}
This page took 0.32258 seconds and 4 git commands to generate.