TILEGX Linux: Fill 'collect_regset' in regset structure.
[deliverable/binutils-gdb.git] / gdb / m68klinux-tdep.c
CommitLineData
0a595803
AS
1/* Motorola m68k target-dependent support for GNU/Linux.
2
ecd75fc8 3 Copyright (C) 1996-2014 Free Software Foundation, Inc.
0a595803
AS
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
0a595803
AS
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/>. */
0a595803
AS
19
20#include "defs.h"
21#include "gdbcore.h"
8de307e0
AS
22#include "doublest.h"
23#include "floatformat.h"
0a595803
AS
24#include "frame.h"
25#include "target.h"
d0b45d99 26#include "gdbtypes.h"
55809acb 27#include "osabi.h"
eb2e12d7
AS
28#include "regcache.h"
29#include "objfiles.h"
30#include "symtab.h"
d0b45d99 31#include "m68k-tdep.h"
17e20bce
AC
32#include "trad-frame.h"
33#include "frame-unwind.h"
fefa1888
AS
34#include "glibc-tdep.h"
35#include "solib-svr4.h"
0ebdb728
MS
36#include "auxv.h"
37#include "observer.h"
38#include "elf/common.h"
a5ee0f0c 39#include "linux-tdep.h"
0a595803 40\f
eb2e12d7
AS
41/* Offsets (in target ints) into jmp_buf. */
42
43#define M68K_LINUX_JB_ELEMENT_SIZE 4
44#define M68K_LINUX_JB_PC 7
45
0a595803
AS
46/* Check whether insn1 and insn2 are parts of a signal trampoline. */
47
48#define IS_SIGTRAMP(insn1, insn2) \
49 (/* addaw #20,sp; moveq #119,d0; trap #0 */ \
50 (insn1 == 0xdefc0014 && insn2 == 0x70774e40) \
51 /* moveq #119,d0; trap #0 */ \
52 || insn1 == 0x70774e40)
53
54#define IS_RT_SIGTRAMP(insn1, insn2) \
55 (/* movel #173,d0; trap #0 */ \
56 (insn1 == 0x203c0000 && insn2 == 0x00ad4e40) \
57 /* moveq #82,d0; notb d0; trap #0 */ \
58 || (insn1 == 0x70524600 && (insn2 >> 16) == 0x4e40))
59
f36bf22c
AS
60/* Return non-zero if THIS_FRAME corresponds to a signal trampoline. For
61 the sake of m68k_linux_get_sigtramp_info we also distinguish between
8de307e0 62 non-RT and RT signal trampolines. */
0a595803 63
eb2e12d7 64static int
f36bf22c 65m68k_linux_pc_in_sigtramp (struct frame_info *this_frame)
0a595803 66{
e17a4113
UW
67 struct gdbarch *gdbarch = get_frame_arch (this_frame);
68 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
f36bf22c 69 gdb_byte buf[12];
0a595803 70 unsigned long insn0, insn1, insn2;
f36bf22c 71 CORE_ADDR pc = get_frame_pc (this_frame);
0a595803 72
c95f5026 73 if (!safe_frame_unwind_memory (this_frame, pc - 4, buf, sizeof (buf)))
0a595803 74 return 0;
e17a4113
UW
75 insn1 = extract_unsigned_integer (buf + 4, 4, byte_order);
76 insn2 = extract_unsigned_integer (buf + 8, 4, byte_order);
0a595803
AS
77 if (IS_SIGTRAMP (insn1, insn2))
78 return 1;
79 if (IS_RT_SIGTRAMP (insn1, insn2))
80 return 2;
81
e17a4113 82 insn0 = extract_unsigned_integer (buf, 4, byte_order);
0a595803
AS
83 if (IS_SIGTRAMP (insn0, insn1))
84 return 1;
85 if (IS_RT_SIGTRAMP (insn0, insn1))
86 return 2;
87
55809acb
AS
88 insn0 = ((insn0 << 16) & 0xffffffff) | (insn1 >> 16);
89 insn1 = ((insn1 << 16) & 0xffffffff) | (insn2 >> 16);
0a595803
AS
90 if (IS_SIGTRAMP (insn0, insn1))
91 return 1;
92 if (IS_RT_SIGTRAMP (insn0, insn1))
93 return 2;
94
95 return 0;
96}
97
8de307e0
AS
98/* From <asm/sigcontext.h>. */
99static int m68k_linux_sigcontext_reg_offset[M68K_NUM_REGS] =
0a595803 100{
8de307e0
AS
101 2 * 4, /* %d0 */
102 3 * 4, /* %d1 */
103 -1, /* %d2 */
104 -1, /* %d3 */
105 -1, /* %d4 */
106 -1, /* %d5 */
107 -1, /* %d6 */
108 -1, /* %d7 */
109 4 * 4, /* %a0 */
110 5 * 4, /* %a1 */
111 -1, /* %a2 */
112 -1, /* %a3 */
113 -1, /* %a4 */
114 -1, /* %a5 */
115 -1, /* %fp */
116 1 * 4, /* %sp */
0ebdb728 117 6 * 4, /* %sr */
8de307e0
AS
118 6 * 4 + 2, /* %pc */
119 8 * 4, /* %fp0 */
120 11 * 4, /* %fp1 */
121 -1, /* %fp2 */
122 -1, /* %fp3 */
123 -1, /* %fp4 */
124 -1, /* %fp5 */
125 -1, /* %fp6 */
126 -1, /* %fp7 */
127 14 * 4, /* %fpcr */
128 15 * 4, /* %fpsr */
129 16 * 4 /* %fpiaddr */
130};
131
0ebdb728
MS
132static int m68k_uclinux_sigcontext_reg_offset[M68K_NUM_REGS] =
133{
134 2 * 4, /* %d0 */
135 3 * 4, /* %d1 */
136 -1, /* %d2 */
137 -1, /* %d3 */
138 -1, /* %d4 */
139 -1, /* %d5 */
140 -1, /* %d6 */
141 -1, /* %d7 */
142 4 * 4, /* %a0 */
143 5 * 4, /* %a1 */
144 -1, /* %a2 */
145 -1, /* %a3 */
146 -1, /* %a4 */
147 6 * 4, /* %a5 */
148 -1, /* %fp */
149 1 * 4, /* %sp */
150 7 * 4, /* %sr */
151 7 * 4 + 2, /* %pc */
152 -1, /* %fp0 */
153 -1, /* %fp1 */
154 -1, /* %fp2 */
155 -1, /* %fp3 */
156 -1, /* %fp4 */
157 -1, /* %fp5 */
158 -1, /* %fp6 */
159 -1, /* %fp7 */
160 -1, /* %fpcr */
161 -1, /* %fpsr */
162 -1 /* %fpiaddr */
163};
164
8de307e0
AS
165/* From <asm/ucontext.h>. */
166static int m68k_linux_ucontext_reg_offset[M68K_NUM_REGS] =
167{
168 6 * 4, /* %d0 */
169 7 * 4, /* %d1 */
170 8 * 4, /* %d2 */
171 9 * 4, /* %d3 */
172 10 * 4, /* %d4 */
173 11 * 4, /* %d5 */
174 12 * 4, /* %d6 */
175 13 * 4, /* %d7 */
176 14 * 4, /* %a0 */
177 15 * 4, /* %a1 */
178 16 * 4, /* %a2 */
179 17 * 4, /* %a3 */
180 18 * 4, /* %a4 */
181 19 * 4, /* %a5 */
182 20 * 4, /* %fp */
183 21 * 4, /* %sp */
184 23 * 4, /* %sr */
185 22 * 4, /* %pc */
186 27 * 4, /* %fp0 */
187 30 * 4, /* %fp1 */
188 33 * 4, /* %fp2 */
189 36 * 4, /* %fp3 */
190 39 * 4, /* %fp4 */
191 42 * 4, /* %fp5 */
192 45 * 4, /* %fp6 */
193 48 * 4, /* %fp7 */
194 24 * 4, /* %fpcr */
195 25 * 4, /* %fpsr */
196 26 * 4 /* %fpiaddr */
197};
198
199
200/* Get info about saved registers in sigtramp. */
201
17e20bce
AC
202struct m68k_linux_sigtramp_info
203{
204 /* Address of sigcontext. */
205 CORE_ADDR sigcontext_addr;
206
207 /* Offset of registers in `struct sigcontext'. */
208 int *sc_reg_offset;
209};
210
0ebdb728
MS
211/* Nonzero if running on uClinux. */
212static int target_is_uclinux;
213
214static void
215m68k_linux_inferior_created (struct target_ops *objfile, int from_tty)
216{
e9efe249
UW
217 /* Record that we will need to re-evaluate whether we are running on a
218 uClinux or normal GNU/Linux target (see m68k_linux_get_sigtramp_info). */
0ebdb728
MS
219 target_is_uclinux = -1;
220}
221
17e20bce 222static struct m68k_linux_sigtramp_info
f36bf22c 223m68k_linux_get_sigtramp_info (struct frame_info *this_frame)
8de307e0 224{
e17a4113
UW
225 struct gdbarch *gdbarch = get_frame_arch (this_frame);
226 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
8de307e0 227 CORE_ADDR sp;
17e20bce 228 struct m68k_linux_sigtramp_info info;
8de307e0 229
c01cbb3d
YQ
230 /* Determine whether we are running on a uClinux or normal GNU/Linux
231 target so we can use the correct sigcontext layouts. */
0ebdb728 232 if (target_is_uclinux == -1)
c01cbb3d 233 target_is_uclinux = linux_is_uclinux ();
0ebdb728 234
f36bf22c 235 sp = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM);
0a595803
AS
236
237 /* Get sigcontext address, it is the third parameter on the stack. */
e17a4113 238 info.sigcontext_addr = read_memory_unsigned_integer (sp + 8, 4, byte_order);
8de307e0 239
f36bf22c 240 if (m68k_linux_pc_in_sigtramp (this_frame) == 2)
8de307e0 241 info.sc_reg_offset = m68k_linux_ucontext_reg_offset;
0a595803 242 else
f36bf22c
AS
243 info.sc_reg_offset = (target_is_uclinux
244 ? m68k_uclinux_sigcontext_reg_offset
245 : m68k_linux_sigcontext_reg_offset);
8de307e0 246 return info;
0a595803
AS
247}
248
17e20bce
AC
249/* Signal trampolines. */
250
251static struct trad_frame_cache *
f36bf22c 252m68k_linux_sigtramp_frame_cache (struct frame_info *this_frame,
17e20bce
AC
253 void **this_cache)
254{
255 struct frame_id this_id;
256 struct trad_frame_cache *cache;
e17a4113
UW
257 struct gdbarch *gdbarch = get_frame_arch (this_frame);
258 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
259 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
17e20bce 260 struct m68k_linux_sigtramp_info info;
f36bf22c 261 gdb_byte buf[4];
17e20bce
AC
262 int i;
263
264 if (*this_cache)
265 return *this_cache;
266
f36bf22c 267 cache = trad_frame_cache_zalloc (this_frame);
17e20bce
AC
268
269 /* FIXME: cagney/2004-05-01: This is is long standing broken code.
270 The frame ID's code address should be the start-address of the
271 signal trampoline and not the current PC within that
272 trampoline. */
f36bf22c 273 get_frame_register (this_frame, M68K_SP_REGNUM, buf);
17e20bce 274 /* See the end of m68k_push_dummy_call. */
e17a4113
UW
275 this_id = frame_id_build (extract_unsigned_integer (buf, 4, byte_order)
276 - 4 + 8, get_frame_pc (this_frame));
17e20bce
AC
277 trad_frame_set_id (cache, this_id);
278
f36bf22c 279 info = m68k_linux_get_sigtramp_info (this_frame);
17e20bce
AC
280
281 for (i = 0; i < M68K_NUM_REGS; i++)
282 if (info.sc_reg_offset[i] != -1)
283 trad_frame_set_reg_addr (cache, i,
284 info.sigcontext_addr + info.sc_reg_offset[i]);
285
286 *this_cache = cache;
287 return cache;
288}
289
290static void
f36bf22c 291m68k_linux_sigtramp_frame_this_id (struct frame_info *this_frame,
17e20bce
AC
292 void **this_cache,
293 struct frame_id *this_id)
294{
295 struct trad_frame_cache *cache =
f36bf22c 296 m68k_linux_sigtramp_frame_cache (this_frame, this_cache);
17e20bce
AC
297 trad_frame_get_id (cache, this_id);
298}
299
f36bf22c
AS
300static struct value *
301m68k_linux_sigtramp_frame_prev_register (struct frame_info *this_frame,
17e20bce 302 void **this_cache,
f36bf22c 303 int regnum)
17e20bce
AC
304{
305 /* Make sure we've initialized the cache. */
306 struct trad_frame_cache *cache =
f36bf22c
AS
307 m68k_linux_sigtramp_frame_cache (this_frame, this_cache);
308 return trad_frame_get_register (cache, this_frame, regnum);
309}
310
311static int
312m68k_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
313 struct frame_info *this_frame,
314 void **this_prologue_cache)
315{
316 return m68k_linux_pc_in_sigtramp (this_frame);
17e20bce
AC
317}
318
319static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
320{
321 SIGTRAMP_FRAME,
8fbca658 322 default_frame_unwind_stop_reason,
17e20bce 323 m68k_linux_sigtramp_frame_this_id,
f36bf22c
AS
324 m68k_linux_sigtramp_frame_prev_register,
325 NULL,
326 m68k_linux_sigtramp_frame_sniffer
17e20bce
AC
327};
328
55809acb
AS
329static void
330m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
331{
eb2e12d7
AS
332 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
333
a5ee0f0c
PA
334 linux_init_abi (info, gdbarch);
335
eb2e12d7
AS
336 tdep->jb_pc = M68K_LINUX_JB_PC;
337 tdep->jb_elt_size = M68K_LINUX_JB_ELEMENT_SIZE;
338
f595cb19 339 /* GNU/Linux uses a calling convention that's similar to SVR4. It
8d3239d5 340 returns integer values in %d0/%d1, pointer values in %a0 and
f595cb19
MK
341 floating values in %fp0, just like SVR4, but uses %a1 to pass the
342 address to store a structure value. It also returns small
343 structures in registers instead of memory. */
344 m68k_svr4_init_abi (info, gdbarch);
345 tdep->struct_value_regnum = M68K_A1_REGNUM;
346 tdep->struct_return = reg_struct_return;
eb2e12d7 347
9418f048
UW
348 set_gdbarch_decr_pc_after_break (gdbarch, 2);
349
f36bf22c 350 frame_unwind_append_unwinder (gdbarch, &m68k_linux_sigtramp_frame_unwind);
eb2e12d7
AS
351
352 /* Shared library handling. */
fefa1888
AS
353
354 /* GNU/Linux uses SVR4-style shared libraries. */
355 set_solib_svr4_fetch_link_map_offsets (gdbarch,
356 svr4_ilp32_fetch_link_map_offsets);
357
358 /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
359 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
360
eb2e12d7 361 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
b2756930
KB
362
363 /* Enable TLS support. */
364 set_gdbarch_fetch_tls_load_module_address (gdbarch,
365 svr4_fetch_objfile_link_map);
007cafee
AS
366
367 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
55809acb
AS
368}
369
63807e1d
PA
370/* Provide a prototype to silence -Wmissing-prototypes. */
371extern initialize_file_ftype _initialize_m68k_linux_tdep;
372
55809acb
AS
373void
374_initialize_m68k_linux_tdep (void)
375{
376 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_LINUX,
377 m68k_linux_init_abi);
0ebdb728 378 observer_attach_inferior_created (m68k_linux_inferior_created);
55809acb 379}
This page took 1.223884 seconds and 4 git commands to generate.