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