2012-02-02 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / alpha-linux-tdep.c
CommitLineData
3379287a 1/* Target-dependent code for GNU/Linux on Alpha.
0b302171 2 Copyright (C) 2002-2003, 2007-2012 Free Software Foundation, Inc.
3379287a
JT
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
a9762ec7 8 the Free Software Foundation; either version 3 of the License, or
3379287a
JT
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
a9762ec7 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
3379287a
JT
18
19#include "defs.h"
5868c862 20#include "frame.h"
d2427a71 21#include "gdb_assert.h"
b02f9d57 22#include "gdb_string.h"
f1a559ae 23#include "osabi.h"
b2756930 24#include "solib-svr4.h"
982e9687 25#include "symtab.h"
b02f9d57
UW
26#include "regset.h"
27#include "regcache.h"
a5ee0f0c 28#include "linux-tdep.h"
3379287a
JT
29#include "alpha-tdep.h"
30
d2427a71
RH
31/* Under GNU/Linux, signal handler invocations can be identified by
32 the designated code sequence that is used to return from a signal
3379287a 33 handler. In particular, the return address of a signal handler
d2427a71
RH
34 points to a sequence that copies $sp to $16, loads $0 with the
35 appropriate syscall number, and finally enters the kernel.
36
37 This is somewhat complicated in that:
38 (1) the expansion of the "mov" assembler macro has changed over
39 time, from "bis src,src,dst" to "bis zero,src,dst",
40 (2) the kernel has changed from using "addq" to "lda" to load the
41 syscall number,
42 (3) there is a "normal" sigreturn and an "rt" sigreturn which
0963b4bd 43 has a different stack layout. */
d2427a71
RH
44
45static long
e17a4113 46alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc)
3379287a 47{
e17a4113 48 switch (alpha_read_insn (gdbarch, pc))
d2427a71
RH
49 {
50 case 0x47de0410: /* bis $30,$30,$16 */
51 case 0x47fe0410: /* bis $31,$30,$16 */
52 return 0;
3379287a 53
d2427a71
RH
54 case 0x43ecf400: /* addq $31,103,$0 */
55 case 0x201f0067: /* lda $0,103($31) */
56 case 0x201f015f: /* lda $0,351($31) */
57 return 4;
58
59 case 0x00000083: /* call_pal callsys */
60 return 8;
3379287a 61
3379287a
JT
62 default:
63 return -1;
64 }
d2427a71
RH
65}
66
67static LONGEST
e17a4113 68alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
d2427a71
RH
69{
70 long i, off;
71
72 if (pc & 3)
73 return -1;
74
75 /* Guess where we might be in the sequence. */
e17a4113 76 off = alpha_linux_sigtramp_offset_1 (gdbarch, pc);
d2427a71
RH
77 if (off < 0)
78 return -1;
79
80 /* Verify that the other two insns of the sequence are as we expect. */
3379287a 81 pc -= off;
d2427a71 82 for (i = 0; i < 12; i += 4)
3379287a 83 {
d2427a71
RH
84 if (i == off)
85 continue;
e17a4113 86 if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i)
d2427a71 87 return -1;
3379287a 88 }
3379287a 89
d2427a71 90 return off;
3379287a
JT
91}
92
6c72f9f9 93static int
e17a4113
UW
94alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch,
95 CORE_ADDR pc, char *func_name)
6c72f9f9 96{
e17a4113 97 return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0;
6c72f9f9
JT
98}
99
5868c862 100static CORE_ADDR
94afd7a6 101alpha_linux_sigcontext_addr (struct frame_info *this_frame)
5868c862 102{
e17a4113 103 struct gdbarch *gdbarch = get_frame_arch (this_frame);
d2427a71
RH
104 CORE_ADDR pc;
105 ULONGEST sp;
106 long off;
107
94afd7a6
UW
108 pc = get_frame_pc (this_frame);
109 sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM);
d2427a71 110
e17a4113 111 off = alpha_linux_sigtramp_offset (gdbarch, pc);
d2427a71
RH
112 gdb_assert (off >= 0);
113
114 /* __NR_rt_sigreturn has a couple of structures on the stack. This is:
115
116 struct rt_sigframe {
117 struct siginfo info;
118 struct ucontext uc;
119 };
120
0963b4bd
MS
121 offsetof (struct rt_sigframe, uc.uc_mcontext); */
122
e17a4113 123 if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f)
d2427a71
RH
124 return sp + 176;
125
126 /* __NR_sigreturn has the sigcontext structure at the top of the stack. */
127 return sp;
5868c862
JT
128}
129
b02f9d57
UW
130/* Supply register REGNUM from the buffer specified by GREGS and LEN
131 in the general-purpose register set REGSET to register cache
132 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
133
134static void
135alpha_linux_supply_gregset (const struct regset *regset,
136 struct regcache *regcache,
137 int regnum, const void *gregs, size_t len)
138{
139 const gdb_byte *regs = gregs;
140 int i;
141 gdb_assert (len >= 32 * 8);
142
143 for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
144 {
145 if (regnum == i || regnum == -1)
146 regcache_raw_supply (regcache, i, regs + i * 8);
147 }
148
149 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
150 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
151
152 if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
153 regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
154 len >= 33 * 8 ? regs + 32 * 8 : NULL);
155}
156
157/* Supply register REGNUM from the buffer specified by FPREGS and LEN
158 in the floating-point register set REGSET to register cache
159 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
160
161static void
162alpha_linux_supply_fpregset (const struct regset *regset,
163 struct regcache *regcache,
164 int regnum, const void *fpregs, size_t len)
165{
166 const gdb_byte *regs = fpregs;
167 int i;
168 gdb_assert (len >= 32 * 8);
169
170 for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
171 {
172 if (regnum == i || regnum == -1)
173 regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
174 }
175
176 if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
6afb1f32 177 regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
b02f9d57
UW
178}
179
180static struct regset alpha_linux_gregset =
181{
182 NULL,
183 alpha_linux_supply_gregset
184};
185
186static struct regset alpha_linux_fpregset =
187{
188 NULL,
189 alpha_linux_supply_fpregset
190};
191
192/* Return the appropriate register set for the core section identified
193 by SECT_NAME and SECT_SIZE. */
194
63807e1d 195static const struct regset *
b02f9d57
UW
196alpha_linux_regset_from_core_section (struct gdbarch *gdbarch,
197 const char *sect_name, size_t sect_size)
198{
199 if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8)
200 return &alpha_linux_gregset;
201
202 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8)
203 return &alpha_linux_fpregset;
204
205 return NULL;
206}
207
3379287a 208static void
baa490c4 209alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
3379287a 210{
d2427a71
RH
211 struct gdbarch_tdep *tdep;
212
a5ee0f0c
PA
213 linux_init_abi (info, gdbarch);
214
f1a559ae 215 /* Hook into the DWARF CFI frame unwinder. */
baa490c4 216 alpha_dwarf2_init_abi (info, gdbarch);
f1a559ae
RH
217
218 /* Hook into the MDEBUG frame unwinder. */
d2427a71 219 alpha_mdebug_init_abi (info, gdbarch);
36a6271d 220
d2427a71 221 tdep = gdbarch_tdep (gdbarch);
36a6271d 222 tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset;
5868c862 223 tdep->sigcontext_addr = alpha_linux_sigcontext_addr;
f2524b93 224 tdep->pc_in_sigtramp = alpha_linux_pc_in_sigtramp;
accc6d1f
JT
225 tdep->jb_pc = 2;
226 tdep->jb_elt_size = 8;
b2756930 227
982e9687
UW
228 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
229
8d005789
UW
230 set_solib_svr4_fetch_link_map_offsets
231 (gdbarch, svr4_lp64_fetch_link_map_offsets);
232
b2756930
KB
233 /* Enable TLS support. */
234 set_gdbarch_fetch_tls_load_module_address (gdbarch,
235 svr4_fetch_objfile_link_map);
b02f9d57
UW
236
237 set_gdbarch_regset_from_core_section
238 (gdbarch, alpha_linux_regset_from_core_section);
3379287a
JT
239}
240
63807e1d
PA
241/* Provide a prototype to silence -Wmissing-prototypes. */
242extern initialize_file_ftype _initialize_alpha_linux_tdep;
243
3379287a
JT
244void
245_initialize_alpha_linux_tdep (void)
246{
05816f70 247 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
70f80edf 248 alpha_linux_init_abi);
3379287a 249}
This page took 0.698053 seconds and 4 git commands to generate.