]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/sparc64-linux-tdep.c
Updated copyright notices for most files.
[thirdparty/binutils-gdb.git] / gdb / sparc64-linux-tdep.c
CommitLineData
386c036b
MK
1/* Target-dependent code for GNU/Linux UltraSPARC.
2
9b254dd1 3 Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
386c036b
MK
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
386c036b
MK
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/>. */
386c036b
MK
19
20#include "defs.h"
78a0fd57
DM
21#include "frame.h"
22#include "frame-unwind.h"
b2a0b9b2 23#include "dwarf2-frame.h"
07c5f590 24#include "regset.h"
0b4294d3 25#include "regcache.h"
386c036b 26#include "gdbarch.h"
0b4294d3 27#include "gdbcore.h"
386c036b 28#include "osabi.h"
b2756930 29#include "solib-svr4.h"
78a0fd57
DM
30#include "symtab.h"
31#include "trad-frame.h"
70f1dc74 32#include "tramp-frame.h"
78a0fd57 33
386c036b
MK
34#include "sparc64-tdep.h"
35
70f1dc74 36/* Signal trampoline support. */
78a0fd57 37
81f726ab
DM
38static void sparc64_linux_sigframe_init (const struct tramp_frame *self,
39 struct frame_info *next_frame,
40 struct trad_frame_cache *this_cache,
41 CORE_ADDR func);
78a0fd57 42
70f1dc74
MK
43/* See sparc-linux-tdep.c for details. Note that 64-bit binaries only
44 use RT signals. */
45
46static const struct tramp_frame sparc64_linux_rt_sigframe =
47{
81f726ab
DM
48 SIGTRAMP_FRAME,
49 4,
50 {
70f1dc74
MK
51 { 0x82102065, -1 }, /* mov __NR_rt_sigreturn, %g1 */
52 { 0x91d0206d, -1 }, /* ta 0x6d */
81f726ab
DM
53 { TRAMP_SENTINEL_INSN, -1 }
54 },
55 sparc64_linux_sigframe_init
56};
78a0fd57 57
81f726ab
DM
58static void
59sparc64_linux_sigframe_init (const struct tramp_frame *self,
60 struct frame_info *next_frame,
61 struct trad_frame_cache *this_cache,
62 CORE_ADDR func)
78a0fd57 63{
80f9e3aa 64 CORE_ADDR base, addr, sp_addr;
78a0fd57
DM
65 int regnum;
66
81f726ab
DM
67 base = frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM);
68 base += 128;
78a0fd57 69
70f1dc74 70 /* Offsets from <bits/sigcontext.h>. */
78a0fd57
DM
71
72 /* Since %g0 is always zero, keep the identity encoding. */
70f1dc74 73 addr = base + 8;
80f9e3aa 74 sp_addr = base + ((SPARC_SP_REGNUM - SPARC_G0_REGNUM) * 8);
81f726ab
DM
75 for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++)
76 {
77 trad_frame_set_reg_addr (this_cache, regnum, addr);
78 addr += 8;
79 }
78a0fd57 80
70f1dc74
MK
81 trad_frame_set_reg_addr (this_cache, SPARC64_STATE_REGNUM, addr + 0);
82 trad_frame_set_reg_addr (this_cache, SPARC64_PC_REGNUM, addr + 8);
83 trad_frame_set_reg_addr (this_cache, SPARC64_NPC_REGNUM, addr + 16);
84 trad_frame_set_reg_addr (this_cache, SPARC64_Y_REGNUM, addr + 24);
85 trad_frame_set_reg_addr (this_cache, SPARC64_FPRS_REGNUM, addr + 28);
78a0fd57 86
80f9e3aa
DM
87 base = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
88 if (base & 1)
89 base += BIAS;
90
91 addr = get_frame_memory_unsigned (next_frame, sp_addr, 8);
81f726ab
DM
92 if (addr & 1)
93 addr += BIAS;
78a0fd57 94
81f726ab
DM
95 for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
96 {
97 trad_frame_set_reg_addr (this_cache, regnum, addr);
98 addr += 8;
99 }
100 trad_frame_set_id (this_cache, frame_id_build (base, func));
78a0fd57
DM
101}
102\f
0b4294d3
DM
103/* Return the address of a system call's alternative return
104 address. */
105
106static CORE_ADDR
0b1b3e42 107sparc64_linux_step_trap (struct frame_info *frame, unsigned long insn)
0b4294d3
DM
108{
109 if (insn == 0x91d0206d)
110 {
0b1b3e42 111 ULONGEST sp = get_frame_register_unsigned (frame, SPARC_SP_REGNUM);
0b4294d3
DM
112 if (sp & 1)
113 sp += BIAS;
114
115 /* The kernel puts the sigreturn registers on the stack,
116 and this is where the signal unwinding state is take from
117 when returning from a signal.
118
119 A siginfo_t sits 192 bytes from the base of the stack. This
120 siginfo_t is 128 bytes, and is followed by the sigreturn
121 register save area. The saved PC sits at a 136 byte offset
122 into there. */
123
124 return read_memory_unsigned_integer (sp + 192 + 128 + 136, 8);
125 }
126
127 return 0;
128}
129\f
70f1dc74 130
07c5f590
DM
131const struct sparc_gregset sparc64_linux_core_gregset =
132{
133 32 * 8, /* %tstate */
134 33 * 8, /* %tpc */
135 34 * 8, /* %tnpc */
136 35 * 8, /* %y */
137 -1, /* %wim */
138 -1, /* %tbr */
139 1 * 8, /* %g1 */
140 16 * 8, /* %l0 */
141 8, /* y size */
142};
143\f
144
145static void
146sparc64_linux_supply_core_gregset (const struct regset *regset,
147 struct regcache *regcache,
148 int regnum, const void *gregs, size_t len)
149{
150 sparc64_supply_gregset (&sparc64_linux_core_gregset, regcache, regnum, gregs);
151}
152
153static void
154sparc64_linux_collect_core_gregset (const struct regset *regset,
155 const struct regcache *regcache,
156 int regnum, void *gregs, size_t len)
157{
158 sparc64_collect_gregset (&sparc64_linux_core_gregset, regcache, regnum, gregs);
159}
160
161static void
162sparc64_linux_supply_core_fpregset (const struct regset *regset,
163 struct regcache *regcache,
164 int regnum, const void *fpregs, size_t len)
165{
166 sparc64_supply_fpregset (regcache, regnum, fpregs);
167}
168
169static void
170sparc64_linux_collect_core_fpregset (const struct regset *regset,
171 const struct regcache *regcache,
172 int regnum, void *fpregs, size_t len)
173{
174 sparc64_collect_fpregset (regcache, regnum, fpregs);
175}
176
177\f
178
386c036b
MK
179static void
180sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
181{
182 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
183
07c5f590
DM
184 tdep->gregset = regset_alloc (gdbarch, sparc64_linux_supply_core_gregset,
185 sparc64_linux_collect_core_gregset);
186 tdep->sizeof_gregset = 288;
187
188 tdep->fpregset = regset_alloc (gdbarch, sparc64_linux_supply_core_fpregset,
189 sparc64_linux_collect_core_fpregset);
190 tdep->sizeof_fpregset = 280;
191
81f726ab 192 tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe);
78a0fd57 193
b2a0b9b2
DM
194 /* Hook in the DWARF CFI frame unwinder. */
195 frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
196
20338726
DM
197 sparc64_init_abi (info, gdbarch);
198
a33e488c
MK
199 /* GNU/Linux has SVR4-style shared libraries... */
200 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
201 set_solib_svr4_fetch_link_map_offsets
202 (gdbarch, svr4_lp64_fetch_link_map_offsets);
386c036b 203
a33e488c
MK
204 /* ...which means that we need some special handling when doing
205 prologue analysis. */
206 tdep->plt_entry_size = 16;
b2756930
KB
207
208 /* Enable TLS support. */
209 set_gdbarch_fetch_tls_load_module_address (gdbarch,
210 svr4_fetch_objfile_link_map);
0b4294d3
DM
211
212 /* Make sure we can single-step over signal return system calls. */
213 tdep->step_trap = sparc64_linux_step_trap;
386c036b 214}
70f1dc74 215\f
386c036b
MK
216
217/* Provide a prototype to silence -Wmissing-prototypes. */
218extern void _initialize_sparc64_linux_tdep (void);
219
220void
221_initialize_sparc64_linux_tdep (void)
222{
223 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
224 GDB_OSABI_LINUX, sparc64_linux_init_abi);
225}