File: | src/gnu/usr.bin/binutils/gdb/tramp-frame.c |
Warning: | line 49, column 13 Value stored to 'pc' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Signal trampoline unwinder, for GDB the GNU Debugger. |
2 | |
3 | Copyright 2004 Free Software Foundation, Inc. |
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 |
9 | the Free Software Foundation; either version 2 of the License, or |
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 |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ |
21 | |
22 | #include "defs.h" |
23 | #include "tramp-frame.h" |
24 | #include "frame-unwind.h" |
25 | #include "gdbcore.h" |
26 | #include "symtab.h" |
27 | #include "objfiles.h" |
28 | #include "target.h" |
29 | #include "trad-frame.h" |
30 | #include "frame-base.h" |
31 | #include "gdb_assert.h" |
32 | |
33 | struct frame_data |
34 | { |
35 | const struct tramp_frame *tramp_frame; |
36 | }; |
37 | |
38 | struct tramp_frame_cache |
39 | { |
40 | CORE_ADDR func; |
41 | const struct tramp_frame *tramp_frame; |
42 | struct trad_frame_cache *trad_cache; |
43 | }; |
44 | |
45 | static struct trad_frame_cache * |
46 | tramp_frame_cache (struct frame_info *next_frame, |
47 | void **this_cache) |
48 | { |
49 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
Value stored to 'pc' during its initialization is never read | |
50 | struct tramp_frame_cache *tramp_cache = (*this_cache); |
51 | if (tramp_cache->trad_cache == NULL((void*)0)) |
52 | { |
53 | tramp_cache->trad_cache = trad_frame_cache_zalloc (next_frame); |
54 | tramp_cache->tramp_frame->init (tramp_cache->tramp_frame, |
55 | next_frame, |
56 | tramp_cache->trad_cache, |
57 | tramp_cache->func); |
58 | } |
59 | return tramp_cache->trad_cache; |
60 | } |
61 | |
62 | static void |
63 | tramp_frame_this_id (struct frame_info *next_frame, |
64 | void **this_cache, |
65 | struct frame_id *this_id) |
66 | { |
67 | struct trad_frame_cache *trad_cache |
68 | = tramp_frame_cache (next_frame, this_cache); |
69 | trad_frame_get_id (trad_cache, this_id); |
70 | } |
71 | |
72 | static void |
73 | tramp_frame_prev_register (struct frame_info *next_frame, |
74 | void **this_cache, |
75 | int prev_regnum, |
76 | int *optimizedp, |
77 | enum lval_type * lvalp, |
78 | CORE_ADDR *addrp, |
79 | int *realnump, void *valuep) |
80 | { |
81 | struct trad_frame_cache *trad_cache |
82 | = tramp_frame_cache (next_frame, this_cache); |
83 | trad_frame_get_register (trad_cache, next_frame, prev_regnum, optimizedp, |
84 | lvalp, addrp, realnump, valuep); |
85 | } |
86 | |
87 | static CORE_ADDR |
88 | tramp_frame_start (const struct tramp_frame *tramp, |
89 | struct frame_info *next_frame, CORE_ADDR pc) |
90 | { |
91 | int ti; |
92 | /* Search through the trampoline for one that matches the |
93 | instruction sequence around PC. */ |
94 | for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN((long) -1); ti++) |
95 | { |
96 | CORE_ADDR func = pc - tramp->insn_size * ti; |
97 | int i; |
98 | for (i = 0; 1; i++) |
99 | { |
100 | bfd_byte buf[sizeof (tramp->insn[0])]; |
101 | ULONGESTunsigned long insn; |
102 | if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN((long) -1)) |
103 | return func; |
104 | if (!safe_frame_unwind_memory (next_frame, |
105 | func + i * tramp->insn_size, |
106 | buf, tramp->insn_size)) |
107 | break; |
108 | insn = extract_unsigned_integer (buf, tramp->insn_size); |
109 | if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask)) |
110 | break; |
111 | } |
112 | } |
113 | /* Trampoline doesn't match. */ |
114 | return 0; |
115 | } |
116 | |
117 | static int |
118 | tramp_frame_sniffer (const struct frame_unwind *self, |
119 | struct frame_info *next_frame, |
120 | void **this_cache) |
121 | { |
122 | const struct tramp_frame *tramp = self->unwind_data->tramp_frame; |
123 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
124 | CORE_ADDR func; |
125 | char *name; |
126 | struct tramp_frame_cache *tramp_cache; |
127 | |
128 | /* If the function has a valid symbol name, it isn't a |
129 | trampoline. */ |
130 | find_pc_partial_function (pc, &name, NULL((void*)0), NULL((void*)0)); |
131 | if (name != NULL((void*)0)) |
132 | return 0; |
133 | /* If the function lives in a valid section (even without a starting |
134 | point) it isn't a trampoline. */ |
135 | if (find_pc_section (pc) != NULL((void*)0)) |
136 | return 0; |
137 | /* Finally, check that the trampoline matches at PC. */ |
138 | func = tramp_frame_start (tramp, next_frame, pc); |
139 | if (func == 0) |
140 | return 0; |
141 | tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache)((struct tramp_frame_cache *) frame_obstack_zalloc (sizeof (struct tramp_frame_cache))); |
142 | tramp_cache->func = func; |
143 | tramp_cache->tramp_frame = tramp; |
144 | (*this_cache) = tramp_cache; |
145 | return 1; |
146 | } |
147 | |
148 | void |
149 | tramp_frame_prepend_unwinder (struct gdbarch *gdbarch, |
150 | const struct tramp_frame *tramp_frame) |
151 | { |
152 | struct frame_data *data; |
153 | struct frame_unwind *unwinder; |
154 | int i; |
155 | |
156 | /* Check that the instruction sequence contains a sentinel. */ |
157 | for (i = 0; i < ARRAY_SIZE (tramp_frame->insn)(sizeof (tramp_frame->insn) / sizeof ((tramp_frame->insn )[0])); i++) |
158 | { |
159 | if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN((long) -1)) |
160 | break; |
161 | } |
162 | gdb_assert (i < ARRAY_SIZE (tramp_frame->insn))((void) ((i < (sizeof (tramp_frame->insn) / sizeof ((tramp_frame ->insn)[0]))) ? 0 : (internal_error ("/usr/src/gnu/usr.bin/binutils/gdb/tramp-frame.c" , 162, "%s: Assertion `%s' failed.", __PRETTY_FUNCTION__, "i < ARRAY_SIZE (tramp_frame->insn)" ), 0))); |
163 | gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes))((void) ((tramp_frame->insn_size <= sizeof (tramp_frame ->insn[0].bytes)) ? 0 : (internal_error ("/usr/src/gnu/usr.bin/binutils/gdb/tramp-frame.c" , 163, "%s: Assertion `%s' failed.", __PRETTY_FUNCTION__, "tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes)" ), 0))); |
164 | |
165 | data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data)((struct frame_data *) gdbarch_obstack_zalloc ((gdbarch), sizeof (struct frame_data))); |
166 | unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind)((struct frame_unwind *) gdbarch_obstack_zalloc ((gdbarch), sizeof (struct frame_unwind))); |
167 | |
168 | data->tramp_frame = tramp_frame; |
169 | unwinder->type = SIGTRAMP_FRAME; |
170 | unwinder->unwind_data = data; |
171 | unwinder->sniffer = tramp_frame_sniffer; |
172 | unwinder->this_id = tramp_frame_this_id; |
173 | unwinder->prev_register = tramp_frame_prev_register; |
174 | frame_unwind_prepend_unwinder (gdbarch, unwinder); |
175 | } |