OSDN Git Service

PR 11123
[pf3gnuchains/pf3gnuchains3x.git] / gdb / sparc64-linux-tdep.c
1 /* Target-dependent code for GNU/Linux UltraSPARC.
2
3    Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
4    Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "frame-unwind.h"
24 #include "dwarf2-frame.h"
25 #include "regset.h"
26 #include "regcache.h"
27 #include "gdbarch.h"
28 #include "gdbcore.h"
29 #include "osabi.h"
30 #include "solib-svr4.h"
31 #include "symtab.h"
32 #include "trad-frame.h"
33 #include "tramp-frame.h"
34
35 #include "sparc64-tdep.h"
36
37 /* Signal trampoline support.  */
38
39 static void sparc64_linux_sigframe_init (const struct tramp_frame *self,
40                                          struct frame_info *this_frame,
41                                          struct trad_frame_cache *this_cache,
42                                          CORE_ADDR func);
43
44 /* See sparc-linux-tdep.c for details.  Note that 64-bit binaries only
45    use RT signals.  */
46
47 static const struct tramp_frame sparc64_linux_rt_sigframe =
48 {
49   SIGTRAMP_FRAME,
50   4,
51   {
52     { 0x82102065, -1 },         /* mov __NR_rt_sigreturn, %g1 */
53     { 0x91d0206d, -1 },         /* ta  0x6d */
54     { TRAMP_SENTINEL_INSN, -1 }
55   },
56   sparc64_linux_sigframe_init
57 };
58
59 static void
60 sparc64_linux_sigframe_init (const struct tramp_frame *self,
61                              struct frame_info *this_frame,
62                              struct trad_frame_cache *this_cache,
63                              CORE_ADDR func)
64 {
65   CORE_ADDR base, addr, sp_addr;
66   int regnum;
67
68   base = get_frame_register_unsigned (this_frame, SPARC_O1_REGNUM);
69   base += 128;
70
71   /* Offsets from <bits/sigcontext.h>.  */
72
73   /* Since %g0 is always zero, keep the identity encoding.  */
74   addr = base + 8;
75   sp_addr = base + ((SPARC_SP_REGNUM - SPARC_G0_REGNUM) * 8);
76   for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++)
77     {
78       trad_frame_set_reg_addr (this_cache, regnum, addr);
79       addr += 8;
80     }
81
82   trad_frame_set_reg_addr (this_cache, SPARC64_STATE_REGNUM, addr + 0);
83   trad_frame_set_reg_addr (this_cache, SPARC64_PC_REGNUM, addr + 8);
84   trad_frame_set_reg_addr (this_cache, SPARC64_NPC_REGNUM, addr + 16);
85   trad_frame_set_reg_addr (this_cache, SPARC64_Y_REGNUM, addr + 24);
86   trad_frame_set_reg_addr (this_cache, SPARC64_FPRS_REGNUM, addr + 28);
87
88   base = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
89   if (base & 1)
90     base += BIAS;
91
92   addr = get_frame_memory_unsigned (this_frame, sp_addr, 8);
93   if (addr & 1)
94     addr += BIAS;
95
96   for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
97     {
98       trad_frame_set_reg_addr (this_cache, regnum, addr);
99       addr += 8;
100     }
101   trad_frame_set_id (this_cache, frame_id_build (base, func));
102 }
103 \f
104 /* Return the address of a system call's alternative return
105    address.  */
106
107 static CORE_ADDR
108 sparc64_linux_step_trap (struct frame_info *frame, unsigned long insn)
109 {
110   if (insn == 0x91d0206d)
111     {
112       struct gdbarch *gdbarch = get_frame_arch (frame);
113       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
114
115       ULONGEST sp = get_frame_register_unsigned (frame, SPARC_SP_REGNUM);
116       if (sp & 1)
117         sp += BIAS;
118
119       /* The kernel puts the sigreturn registers on the stack,
120          and this is where the signal unwinding state is take from
121          when returning from a signal.
122
123          A siginfo_t sits 192 bytes from the base of the stack.  This
124          siginfo_t is 128 bytes, and is followed by the sigreturn
125          register save area.  The saved PC sits at a 136 byte offset
126          into there.  */
127
128       return read_memory_unsigned_integer (sp + 192 + 128 + 136,
129                                            8, byte_order);
130     }
131
132   return 0;
133 }
134 \f
135
136 const struct sparc_gregset sparc64_linux_core_gregset =
137 {
138   32 * 8,                       /* %tstate */
139   33 * 8,                       /* %tpc */
140   34 * 8,                       /* %tnpc */
141   35 * 8,                       /* %y */
142   -1,                           /* %wim */
143   -1,                           /* %tbr */
144   1 * 8,                        /* %g1 */
145   16 * 8,                       /* %l0 */
146   8,                            /* y size */
147 };
148 \f
149
150 static void
151 sparc64_linux_supply_core_gregset (const struct regset *regset,
152                                    struct regcache *regcache,
153                                    int regnum, const void *gregs, size_t len)
154 {
155   sparc64_supply_gregset (&sparc64_linux_core_gregset, regcache, regnum, gregs);
156 }
157
158 static void
159 sparc64_linux_collect_core_gregset (const struct regset *regset,
160                                     const struct regcache *regcache,
161                                     int regnum, void *gregs, size_t len)
162 {
163   sparc64_collect_gregset (&sparc64_linux_core_gregset, regcache, regnum, gregs);
164 }
165
166 static void
167 sparc64_linux_supply_core_fpregset (const struct regset *regset,
168                                     struct regcache *regcache,
169                                     int regnum, const void *fpregs, size_t len)
170 {
171   sparc64_supply_fpregset (regcache, regnum, fpregs);
172 }
173
174 static void
175 sparc64_linux_collect_core_fpregset (const struct regset *regset,
176                                      const struct regcache *regcache,
177                                      int regnum, void *fpregs, size_t len)
178 {
179   sparc64_collect_fpregset (regcache, regnum, fpregs);
180 }
181
182 /* Set the program counter for process PTID to PC.  */
183
184 #define TSTATE_SYSCALL  0x0000000000000020ULL
185
186 static void
187 sparc64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
188 {
189   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
190   ULONGEST state;
191
192   regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
193   regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
194
195   /* Clear the "in syscall" bit to prevent the kernel from
196      messing with the PCs we just installed, if we happen to be
197      within an interrupted system call that the kernel wants to
198      restart.
199
200      Note that after we return from the dummy call, the TSTATE et al.
201      registers will be automatically restored, and the kernel
202      continues to restart the system call at this point.  */
203   regcache_cooked_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
204   state &= ~TSTATE_SYSCALL;
205   regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
206 }
207
208 \f
209
210 static void
211 sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
212 {
213   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
214
215   tdep->gregset = regset_alloc (gdbarch, sparc64_linux_supply_core_gregset,
216                                 sparc64_linux_collect_core_gregset);
217   tdep->sizeof_gregset = 288;
218
219   tdep->fpregset = regset_alloc (gdbarch, sparc64_linux_supply_core_fpregset,
220                                  sparc64_linux_collect_core_fpregset);
221   tdep->sizeof_fpregset = 280;
222
223   tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe);
224
225   /* Hook in the DWARF CFI frame unwinder.  */
226   dwarf2_append_unwinders (gdbarch);
227
228   sparc64_init_abi (info, gdbarch);
229
230   /* GNU/Linux has SVR4-style shared libraries...  */
231   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
232   set_solib_svr4_fetch_link_map_offsets
233     (gdbarch, svr4_lp64_fetch_link_map_offsets);
234
235   /* ...which means that we need some special handling when doing
236      prologue analysis.  */
237   tdep->plt_entry_size = 16;
238
239   /* Enable TLS support.  */
240   set_gdbarch_fetch_tls_load_module_address (gdbarch,
241                                              svr4_fetch_objfile_link_map);
242
243   /* Make sure we can single-step over signal return system calls.  */
244   tdep->step_trap = sparc64_linux_step_trap;
245
246   set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
247 }
248 \f
249
250 /* Provide a prototype to silence -Wmissing-prototypes.  */
251 extern void _initialize_sparc64_linux_tdep (void);
252
253 void
254 _initialize_sparc64_linux_tdep (void)
255 {
256   gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
257                           GDB_OSABI_LINUX, sparc64_linux_init_abi);
258 }