]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tramp-frame.c
*** empty log message ***
[thirdparty/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
AC
47 struct tramp_frame_cache *tramp_cache = (*this_cache);
48 if (tramp_cache->trad_cache == NULL)
49 {
25492ce3 50 tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame);
d2259dd3 51 tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
25492ce3 52 this_frame,
d2259dd3
AC
53 tramp_cache->trad_cache,
54 tramp_cache->func);
55 }
56 return tramp_cache->trad_cache;
57}
58
59static void
25492ce3 60tramp_frame_this_id (struct frame_info *this_frame,
d2259dd3
AC
61 void **this_cache,
62 struct frame_id *this_id)
63{
64 struct trad_frame_cache *trad_cache
25492ce3 65 = tramp_frame_cache (this_frame, this_cache);
d2259dd3
AC
66 trad_frame_get_id (trad_cache, this_id);
67}
68
25492ce3
DJ
69static struct value *
70tramp_frame_prev_register (struct frame_info *this_frame,
d2259dd3 71 void **this_cache,
25492ce3 72 int prev_regnum)
d2259dd3
AC
73{
74 struct trad_frame_cache *trad_cache
25492ce3
DJ
75 = tramp_frame_cache (this_frame, this_cache);
76 return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
d2259dd3
AC
77}
78
79static CORE_ADDR
304396fb 80tramp_frame_start (const struct tramp_frame *tramp,
25492ce3 81 struct frame_info *this_frame, CORE_ADDR pc)
d2259dd3 82{
e17a4113
UW
83 struct gdbarch *gdbarch = get_frame_arch (this_frame);
84 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d2259dd3
AC
85 int ti;
86 /* Search through the trampoline for one that matches the
87 instruction sequence around PC. */
2cd8546d 88 for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
d2259dd3
AC
89 {
90 CORE_ADDR func = pc - tramp->insn_size * ti;
91 int i;
92 for (i = 0; 1; i++)
93 {
fc1a4b47 94 gdb_byte buf[sizeof (tramp->insn[0])];
1196bfda 95 ULONGEST insn;
2cd8546d 96 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
d2259dd3 97 return func;
25492ce3 98 if (!safe_frame_unwind_memory (this_frame,
304396fb
AC
99 func + i * tramp->insn_size,
100 buf, tramp->insn_size))
d2259dd3 101 break;
e17a4113 102 insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
2cd8546d 103 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
d2259dd3
AC
104 break;
105 }
106 }
107 /* Trampoline doesn't match. */
108 return 0;
109}
110
111static int
112tramp_frame_sniffer (const struct frame_unwind *self,
25492ce3 113 struct frame_info *this_frame,
d2259dd3
AC
114 void **this_cache)
115{
116 const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
25492ce3 117 CORE_ADDR pc = get_frame_pc (this_frame);
d2259dd3 118 CORE_ADDR func;
d2259dd3
AC
119 struct tramp_frame_cache *tramp_cache;
120
0efcf9dc
RC
121 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
122 section, then this is not a trampoline. However, this assumption is
123 false on HPUX which has a signal trampoline that has a name; it can
124 also be false when using an alternative signal stack. */
25492ce3 125 func = tramp_frame_start (tramp, this_frame, pc);
d2259dd3
AC
126 if (func == 0)
127 return 0;
128 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
129 tramp_cache->func = func;
130 tramp_cache->tramp_frame = tramp;
131 (*this_cache) = tramp_cache;
132 return 1;
133}
134
135void
fb2be677
AC
136tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
137 const struct tramp_frame *tramp_frame)
d2259dd3
AC
138{
139 struct frame_data *data;
140 struct frame_unwind *unwinder;
1196bfda
AC
141 int i;
142
143 /* Check that the instruction sequence contains a sentinel. */
144 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
145 {
2cd8546d 146 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
1196bfda
AC
147 break;
148 }
149 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
2cd8546d 150 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
d2259dd3
AC
151
152 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
153 unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
154
155 data->tramp_frame = tramp_frame;
1f586765 156 unwinder->type = tramp_frame->frame_type;
d2259dd3
AC
157 unwinder->unwind_data = data;
158 unwinder->sniffer = tramp_frame_sniffer;
159 unwinder->this_id = tramp_frame_this_id;
160 unwinder->prev_register = tramp_frame_prev_register;
fb2be677 161 frame_unwind_prepend_unwinder (gdbarch, unwinder);
d2259dd3 162}