Honour PRIVATE keyword
[deliverable/binutils-gdb.git] / gdb / amd64-linux-tdep.c
CommitLineData
51433e4b 1/* Target-dependent code for GNU/Linux x86-64.
a4b6fc86 2
af233647 3 Copyright 2001, 2003, 2004 Free Software Foundation, Inc.
53e95fcf
JS
4 Contributed by Jiri Smid, SuSE Labs.
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 2 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, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
24#include "inferior.h"
25#include "gdbcore.h"
26#include "regcache.h"
84dc46cb 27#include "osabi.h"
53e95fcf 28
c4f35dd8 29#include "gdb_string.h"
53e95fcf 30
9c1488cb
MK
31#include "amd64-tdep.h"
32#include "amd64-linux-tdep.h"
eba29c8c
ML
33
34/* Register indexes to 'struct user' come from <sys/reg.h>. */
35
36#define USER_R15 0
37#define USER_R14 1
38#define USER_R13 2
39#define USER_R12 3
40#define USER_RBP 4
41#define USER_RBX 5
42#define USER_R11 6
43#define USER_R10 7
44#define USER_R9 8
45#define USER_R8 9
46#define USER_RAX 10
47#define USER_RCX 11
48#define USER_RDX 12
49#define USER_RSI 13
50#define USER_RDI 14
51#define USER_RIP 16
52#define USER_CS 17
53#define USER_EFLAGS 18
54#define USER_RSP 19
55#define USER_SS 20
56#define USER_DS 23
57#define USER_ES 24
58#define USER_FS 25
59#define USER_GS 26
60
61/* Mapping between the general-purpose registers in `struct user'
62 format and GDB's register array layout. */
63
64static int user_to_gdb_regmap[] =
65{
66 USER_RAX, USER_RBX, USER_RCX, USER_RDX,
67 USER_RSI, USER_RDI, USER_RBP, USER_RSP,
68 USER_R8, USER_R9, USER_R10, USER_R11,
69 USER_R12, USER_R13, USER_R14, USER_R15,
b0f5c6f2 70 USER_RIP, USER_EFLAGS,
af233647 71 USER_CS, USER_SS,
eba29c8c
ML
72 USER_DS, USER_ES, USER_FS, USER_GS
73};
74
75/* Fill GDB's register array with the general-purpose register values
76 in *GREGSETP. */
77
78void
51433e4b 79amd64_linux_supply_gregset (char *regp)
eba29c8c
ML
80{
81 int i;
82
90f90721 83 for (i = 0; i < AMD64_NUM_GREGS; i++)
eba29c8c
ML
84 supply_register (i, regp + (user_to_gdb_regmap[i] * 8));
85}
86
87/* Fill register REGNO (if it is a general-purpose register) in
88 *GREGSETPS with the value in GDB's register array. If REGNO is -1,
89 do this for all registers. */
90
91void
51433e4b 92amd64_linux_fill_gregset (char *regp, int regno)
eba29c8c
ML
93{
94 int i;
95
90f90721 96 for (i = 0; i < AMD64_NUM_GREGS; i++)
eba29c8c
ML
97 if (regno == -1 || regno == i)
98 regcache_collect (i, regp + (user_to_gdb_regmap[i] * 8));
99}
100
101/* The register sets used in GNU/Linux ELF core-dumps are identical to
102 the register sets used by `ptrace'. The corresponding types are
103 `elf_gregset_t' for the general-purpose registers (with
104 `elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
105 for the floating-point registers. */
106
107static void
108fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
109 int which, CORE_ADDR ignore)
110{
111 switch (which)
112 {
113 case 0: /* Integer registers. */
114 if (core_reg_size != 216)
115 warning ("Wrong size register set in core file.");
116 else
51433e4b 117 amd64_linux_supply_gregset (core_reg_sect);
eba29c8c
ML
118 break;
119
120 case 2: /* Floating point registers. */
121 case 3: /* "Extended" floating point registers. This is gdb-speak
122 for SSE/SSE2. */
123 if (core_reg_size != 512)
124 warning ("Wrong size XMM register set in core file.");
125 else
90f90721 126 amd64_supply_fxsave (current_regcache, -1, core_reg_sect);
eba29c8c
ML
127 break;
128
129 default:
130 /* Don't know what kind of register request this is; just ignore it. */
131 break;
132 }
133}
134
51433e4b 135static struct core_fns amd64_core_fns =
eba29c8c
ML
136{
137 bfd_target_elf_flavour, /* core_flavour */
138 default_check_format, /* check_format */
139 default_core_sniffer, /* core_sniffer */
140 fetch_core_registers, /* core_read_registers */
141 NULL /* next */
142};
c4f35dd8
MK
143
144#define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */
145#define LINUX_SIGTRAMP_OFFSET0 0
146#define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */
147#define LINUX_SIGTRAMP_OFFSET1 7
148
149static const unsigned char linux_sigtramp_code[] =
150{
151 /* mov $__NR_rt_sigreturn, %rax */
baed091b
ML
152 LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
153 /* syscall */
154 LINUX_SIGTRAMP_INSN1, 0x05
53e95fcf
JS
155};
156
157#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
158
159/* If PC is in a sigtramp routine, return the address of the start of
160 the routine. Otherwise, return 0. */
161
162static CORE_ADDR
51433e4b 163amd64_linux_sigtramp_start (CORE_ADDR pc)
53e95fcf
JS
164{
165 unsigned char buf[LINUX_SIGTRAMP_LEN];
c4f35dd8
MK
166
167 /* We only recognize a signal trampoline if PC is at the start of
168 one of the two instructions. We optimize for finding the PC at
169 the start, as will be the case when the trampoline is not the
170 first frame on the stack. We assume that in the case where the
171 PC is not at the start of the instruction sequence, there will be
172 a few trailing readable bytes on the stack. */
173
53e95fcf
JS
174 if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
175 return 0;
176
177 if (buf[0] != LINUX_SIGTRAMP_INSN0)
178 {
179 if (buf[0] != LINUX_SIGTRAMP_INSN1)
180 return 0;
181
182 pc -= LINUX_SIGTRAMP_OFFSET1;
183
184 if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
185 return 0;
186 }
187
188 if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
189 return 0;
190
191 return pc;
192}
193
baed091b
ML
194/* Return whether PC is in a GNU/Linux sigtramp routine. */
195
c4f35dd8 196static int
51433e4b 197amd64_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
baed091b 198{
c4f35dd8
MK
199 /* If we have NAME, we can optimize the search. The trampoline is
200 named __restore_rt. However, it isn't dynamically exported from
201 the shared C library, so the trampoline may appear to be part of
202 the preceding function. This should always be sigaction,
203 __sigaction, or __libc_sigaction (all aliases to the same
204 function). */
205 if (name == NULL || strstr (name, "sigaction") != NULL)
51433e4b 206 return (amd64_linux_sigtramp_start (pc) != 0);
c4f35dd8
MK
207
208 return (strcmp ("__restore_rt", name) == 0);
baed091b
ML
209}
210
c4f35dd8 211/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
51433e4b 212#define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
b64bbf8c 213
c4f35dd8
MK
214/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
215 routine, return the address of the associated sigcontext structure. */
baed091b 216
c4f35dd8 217static CORE_ADDR
51433e4b 218amd64_linux_sigcontext_addr (struct frame_info *next_frame)
baed091b 219{
c4f35dd8
MK
220 CORE_ADDR sp;
221 char buf[8];
222
223 frame_unwind_register (next_frame, SP_REGNUM, buf);
224 sp = extract_unsigned_integer (buf, 8);
225
226 /* The sigcontext structure is part of the user context. A pointer
227 to the user context is passed as the third argument to the signal
228 handler, i.e. in %rdx. Unfortunately %rdx isn't preserved across
229 function calls so we can't use it. Fortunately the user context
230 is part of the signal frame and the unwound %rsp directly points
231 at it. */
51433e4b 232 return sp + AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
baed091b 233}
2213a65d
MK
234\f
235
2b5e0749 236/* From <asm/sigcontext.h>. */
51433e4b 237static int amd64_linux_sc_reg_offset[] =
2b5e0749
MK
238{
239 13 * 8, /* %rax */
240 11 * 8, /* %rbx */
241 14 * 8, /* %rcx */
242 12 * 8, /* %rdx */
243 9 * 8, /* %rsi */
244 8 * 8, /* %rdi */
245 10 * 8, /* %rbp */
246 15 * 8, /* %rsp */
247 0 * 8, /* %r8 */
248 1 * 8, /* %r9 */
249 2 * 8, /* %r10 */
250 3 * 8, /* %r11 */
251 4 * 8, /* %r12 */
252 5 * 8, /* %r13 */
253 6 * 8, /* %r14 */
254 7 * 8, /* %r15 */
255 16 * 8, /* %rip */
256 17 * 8, /* %eflags */
2b5e0749 257
af233647 258 /* FIXME: kettenis/2002030531: The registers %cs, %fs and %gs are
2b5e0749
MK
259 available in `struct sigcontext'. However, they only occupy two
260 bytes instead of four, which makes using them here rather
261 difficult. Leave them out for now. */
af233647
MK
262 -1, /* %cs */
263 -1, /* %ss */
264 -1, /* %ds */
265 -1, /* %es */
2b5e0749
MK
266 -1, /* %fs */
267 -1 /* %gs */
268};
269
2213a65d 270static void
51433e4b 271amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
2213a65d 272{
c4f35dd8 273 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
90f90721 274 amd64_init_abi (info, gdbarch);
c4f35dd8 275
51433e4b 276 set_gdbarch_pc_in_sigtramp (gdbarch, amd64_linux_pc_in_sigtramp);
c4f35dd8 277
51433e4b
MK
278 tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
279 tdep->sc_reg_offset = amd64_linux_sc_reg_offset;
280 tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
2213a65d 281}
c4f35dd8 282\f
2213a65d
MK
283
284/* Provide a prototype to silence -Wmissing-prototypes. */
51433e4b 285extern void _initialize_amd64_linux_tdep (void);
2213a65d
MK
286
287void
51433e4b 288_initialize_amd64_linux_tdep (void)
2213a65d 289{
51433e4b 290 add_core_fns (&amd64_core_fns);
eba29c8c 291
51433e4b
MK
292 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
293 GDB_OSABI_LINUX, amd64_linux_init_abi);
2213a65d 294}
This page took 0.682464 seconds and 4 git commands to generate.