* symfile.c (add_psymbol_to_bcache): Return a const pointer. Use
[deliverable/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 38static void sparc64_linux_sigframe_init (const struct tramp_frame *self,
5366653e 39 struct frame_info *this_frame,
81f726ab
DM
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,
5366653e 60 struct frame_info *this_frame,
81f726ab
DM
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
5366653e 67 base = get_frame_register_unsigned (this_frame, SPARC_O1_REGNUM);
81f726ab 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
5366653e 87 base = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
80f9e3aa
DM
88 if (base & 1)
89 base += BIAS;
90
5366653e 91 addr = get_frame_memory_unsigned (this_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
e8467b5a
DM
177/* Set the program counter for process PTID to PC. */
178
179#define TSTATE_SYSCALL 0x0000000000000020ULL
180
181static void
182sparc64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
183{
184 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
185 ULONGEST state;
186
187 regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
188 regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
189
190 /* Clear the "in syscall" bit to prevent the kernel from
191 messing with the PCs we just installed, if we happen to be
192 within an interrupted system call that the kernel wants to
193 restart.
194
195 Note that after we return from the dummy call, the TSTATE et al.
196 registers will be automatically restored, and the kernel
197 continues to restart the system call at this point. */
198 regcache_cooked_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
199 state &= ~TSTATE_SYSCALL;
200 regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
201}
202
07c5f590
DM
203\f
204
386c036b
MK
205static void
206sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
207{
208 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
209
07c5f590
DM
210 tdep->gregset = regset_alloc (gdbarch, sparc64_linux_supply_core_gregset,
211 sparc64_linux_collect_core_gregset);
212 tdep->sizeof_gregset = 288;
213
214 tdep->fpregset = regset_alloc (gdbarch, sparc64_linux_supply_core_fpregset,
215 sparc64_linux_collect_core_fpregset);
216 tdep->sizeof_fpregset = 280;
217
81f726ab 218 tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe);
78a0fd57 219
b2a0b9b2 220 /* Hook in the DWARF CFI frame unwinder. */
87a7da84 221 dwarf2_append_unwinders (gdbarch);
b2a0b9b2 222
20338726
DM
223 sparc64_init_abi (info, gdbarch);
224
a33e488c
MK
225 /* GNU/Linux has SVR4-style shared libraries... */
226 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
227 set_solib_svr4_fetch_link_map_offsets
228 (gdbarch, svr4_lp64_fetch_link_map_offsets);
386c036b 229
a33e488c
MK
230 /* ...which means that we need some special handling when doing
231 prologue analysis. */
232 tdep->plt_entry_size = 16;
b2756930
KB
233
234 /* Enable TLS support. */
235 set_gdbarch_fetch_tls_load_module_address (gdbarch,
236 svr4_fetch_objfile_link_map);
0b4294d3
DM
237
238 /* Make sure we can single-step over signal return system calls. */
239 tdep->step_trap = sparc64_linux_step_trap;
e8467b5a
DM
240
241 set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
386c036b 242}
70f1dc74 243\f
386c036b
MK
244
245/* Provide a prototype to silence -Wmissing-prototypes. */
246extern void _initialize_sparc64_linux_tdep (void);
247
248void
249_initialize_sparc64_linux_tdep (void)
250{
251 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
252 GDB_OSABI_LINUX, sparc64_linux_init_abi);
253}
This page took 0.408551 seconds and 4 git commands to generate.