Fix memory access problems exposed by fuzzed binaries.
[deliverable/binutils-gdb.git] / gdb / tramp-frame.c
CommitLineData
d2259dd3
AC
1/* Signal trampoline unwinder, for GDB the GNU Debugger.
2
ecd75fc8 3 Copyright (C) 2004-2014 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"
29
30struct frame_data
31{
32 const struct tramp_frame *tramp_frame;
33};
34
35struct tramp_frame_cache
36{
37 CORE_ADDR func;
38 const struct tramp_frame *tramp_frame;
39 struct trad_frame_cache *trad_cache;
40};
41
42static struct trad_frame_cache *
25492ce3 43tramp_frame_cache (struct frame_info *this_frame,
d2259dd3
AC
44 void **this_cache)
45{
d2259dd3 46 struct tramp_frame_cache *tramp_cache = (*this_cache);
5d502164 47
d2259dd3
AC
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);
5d502164 66
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 76 = tramp_frame_cache (this_frame, this_cache);
5d502164 77
25492ce3 78 return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
d2259dd3
AC
79}
80
81static CORE_ADDR
304396fb 82tramp_frame_start (const struct tramp_frame *tramp,
25492ce3 83 struct frame_info *this_frame, CORE_ADDR pc)
d2259dd3 84{
e17a4113
UW
85 struct gdbarch *gdbarch = get_frame_arch (this_frame);
86 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d2259dd3 87 int ti;
5d502164 88
d2259dd3
AC
89 /* Search through the trampoline for one that matches the
90 instruction sequence around PC. */
2cd8546d 91 for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
d2259dd3
AC
92 {
93 CORE_ADDR func = pc - tramp->insn_size * ti;
94 int i;
5d502164 95
d2259dd3
AC
96 for (i = 0; 1; i++)
97 {
fc1a4b47 98 gdb_byte buf[sizeof (tramp->insn[0])];
1196bfda 99 ULONGEST insn;
5d502164 100
2cd8546d 101 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
d2259dd3 102 return func;
25492ce3 103 if (!safe_frame_unwind_memory (this_frame,
304396fb
AC
104 func + i * tramp->insn_size,
105 buf, tramp->insn_size))
d2259dd3 106 break;
e17a4113 107 insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
2cd8546d 108 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
d2259dd3
AC
109 break;
110 }
111 }
112 /* Trampoline doesn't match. */
113 return 0;
114}
115
116static int
117tramp_frame_sniffer (const struct frame_unwind *self,
25492ce3 118 struct frame_info *this_frame,
d2259dd3
AC
119 void **this_cache)
120{
121 const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
25492ce3 122 CORE_ADDR pc = get_frame_pc (this_frame);
d2259dd3 123 CORE_ADDR func;
d2259dd3
AC
124 struct tramp_frame_cache *tramp_cache;
125
0efcf9dc
RC
126 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
127 section, then this is not a trampoline. However, this assumption is
128 false on HPUX which has a signal trampoline that has a name; it can
129 also be false when using an alternative signal stack. */
25492ce3 130 func = tramp_frame_start (tramp, this_frame, pc);
d2259dd3
AC
131 if (func == 0)
132 return 0;
133 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
134 tramp_cache->func = func;
135 tramp_cache->tramp_frame = tramp;
136 (*this_cache) = tramp_cache;
137 return 1;
138}
139
140void
fb2be677
AC
141tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
142 const struct tramp_frame *tramp_frame)
d2259dd3
AC
143{
144 struct frame_data *data;
145 struct frame_unwind *unwinder;
1196bfda
AC
146 int i;
147
148 /* Check that the instruction sequence contains a sentinel. */
149 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
150 {
2cd8546d 151 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
1196bfda
AC
152 break;
153 }
154 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
2cd8546d 155 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
d2259dd3
AC
156
157 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
158 unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
159
160 data->tramp_frame = tramp_frame;
1f586765 161 unwinder->type = tramp_frame->frame_type;
d2259dd3
AC
162 unwinder->unwind_data = data;
163 unwinder->sniffer = tramp_frame_sniffer;
4a2fbb50 164 unwinder->stop_reason = default_frame_unwind_stop_reason;
d2259dd3
AC
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 1.157117 seconds and 4 git commands to generate.