2004-04-03 Andrew Cagney <cagney@redhat.com>
[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"
187e21d1 24#include "frame.h"
53e95fcf
JS
25#include "gdbcore.h"
26#include "regcache.h"
84dc46cb 27#include "osabi.h"
53e95fcf 28
c4f35dd8 29#include "gdb_string.h"
53e95fcf 30
9c1488cb 31#include "amd64-tdep.h"
187e21d1 32#include "solib-svr4.h"
eba29c8c
ML
33
34/* Mapping between the general-purpose registers in `struct user'
187e21d1 35 format and GDB's register cache layout. */
eba29c8c 36
187e21d1
MK
37/* From <sys/reg.h>. */
38static int amd64_linux_gregset_reg_offset[] =
eba29c8c 39{
187e21d1
MK
40 10 * 8, /* %rax */
41 5 * 8, /* %rbx */
42 11 * 8, /* %rcx */
43 12 * 8, /* %rdx */
44 13 * 8, /* %rsi */
45 14 * 8, /* %rdi */
46 4 * 8, /* %rbp */
47 19 * 8, /* %rsp */
48 9 * 8, /* %r8 ... */
49 8 * 8,
50 7 * 8,
51 6 * 8,
52 3 * 8,
53 2 * 8,
54 1 * 8,
55 0 * 8, /* ... %r15 */
56 16 * 8, /* %rip */
57 18 * 8, /* %eflags */
58 17 * 8, /* %cs */
59 20 * 8, /* %ss */
60 23 * 8, /* %ds */
61 24 * 8, /* %es */
62 25 * 8, /* %fs */
63 26 * 8 /* %gs */
eba29c8c 64};
187e21d1 65\f
eba29c8c 66
187e21d1 67/* Support for signal handlers. */
c4f35dd8
MK
68
69#define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */
70#define LINUX_SIGTRAMP_OFFSET0 0
71#define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */
72#define LINUX_SIGTRAMP_OFFSET1 7
73
74static const unsigned char linux_sigtramp_code[] =
75{
76 /* mov $__NR_rt_sigreturn, %rax */
baed091b
ML
77 LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
78 /* syscall */
79 LINUX_SIGTRAMP_INSN1, 0x05
53e95fcf
JS
80};
81
82#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
83
84/* If PC is in a sigtramp routine, return the address of the start of
85 the routine. Otherwise, return 0. */
86
87static CORE_ADDR
51433e4b 88amd64_linux_sigtramp_start (CORE_ADDR pc)
53e95fcf
JS
89{
90 unsigned char buf[LINUX_SIGTRAMP_LEN];
c4f35dd8
MK
91
92 /* We only recognize a signal trampoline if PC is at the start of
93 one of the two instructions. We optimize for finding the PC at
94 the start, as will be the case when the trampoline is not the
95 first frame on the stack. We assume that in the case where the
96 PC is not at the start of the instruction sequence, there will be
97 a few trailing readable bytes on the stack. */
98
53e95fcf
JS
99 if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
100 return 0;
101
102 if (buf[0] != LINUX_SIGTRAMP_INSN0)
103 {
104 if (buf[0] != LINUX_SIGTRAMP_INSN1)
105 return 0;
106
107 pc -= LINUX_SIGTRAMP_OFFSET1;
108
109 if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
110 return 0;
111 }
112
113 if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
114 return 0;
115
116 return pc;
117}
118
baed091b
ML
119/* Return whether PC is in a GNU/Linux sigtramp routine. */
120
c4f35dd8 121static int
51433e4b 122amd64_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
baed091b 123{
c4f35dd8
MK
124 /* If we have NAME, we can optimize the search. The trampoline is
125 named __restore_rt. However, it isn't dynamically exported from
126 the shared C library, so the trampoline may appear to be part of
127 the preceding function. This should always be sigaction,
128 __sigaction, or __libc_sigaction (all aliases to the same
129 function). */
130 if (name == NULL || strstr (name, "sigaction") != NULL)
51433e4b 131 return (amd64_linux_sigtramp_start (pc) != 0);
c4f35dd8
MK
132
133 return (strcmp ("__restore_rt", name) == 0);
baed091b
ML
134}
135
c4f35dd8 136/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
51433e4b 137#define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
b64bbf8c 138
c4f35dd8
MK
139/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
140 routine, return the address of the associated sigcontext structure. */
baed091b 141
c4f35dd8 142static CORE_ADDR
51433e4b 143amd64_linux_sigcontext_addr (struct frame_info *next_frame)
baed091b 144{
c4f35dd8
MK
145 CORE_ADDR sp;
146 char buf[8];
147
148 frame_unwind_register (next_frame, SP_REGNUM, buf);
149 sp = extract_unsigned_integer (buf, 8);
150
151 /* The sigcontext structure is part of the user context. A pointer
152 to the user context is passed as the third argument to the signal
153 handler, i.e. in %rdx. Unfortunately %rdx isn't preserved across
154 function calls so we can't use it. Fortunately the user context
155 is part of the signal frame and the unwound %rsp directly points
156 at it. */
51433e4b 157 return sp + AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
baed091b 158}
2213a65d
MK
159\f
160
2b5e0749 161/* From <asm/sigcontext.h>. */
51433e4b 162static int amd64_linux_sc_reg_offset[] =
2b5e0749
MK
163{
164 13 * 8, /* %rax */
165 11 * 8, /* %rbx */
166 14 * 8, /* %rcx */
167 12 * 8, /* %rdx */
168 9 * 8, /* %rsi */
169 8 * 8, /* %rdi */
170 10 * 8, /* %rbp */
171 15 * 8, /* %rsp */
172 0 * 8, /* %r8 */
173 1 * 8, /* %r9 */
174 2 * 8, /* %r10 */
175 3 * 8, /* %r11 */
176 4 * 8, /* %r12 */
177 5 * 8, /* %r13 */
178 6 * 8, /* %r14 */
179 7 * 8, /* %r15 */
180 16 * 8, /* %rip */
181 17 * 8, /* %eflags */
2b5e0749 182
af233647 183 /* FIXME: kettenis/2002030531: The registers %cs, %fs and %gs are
2b5e0749
MK
184 available in `struct sigcontext'. However, they only occupy two
185 bytes instead of four, which makes using them here rather
186 difficult. Leave them out for now. */
af233647
MK
187 -1, /* %cs */
188 -1, /* %ss */
189 -1, /* %ds */
190 -1, /* %es */
2b5e0749
MK
191 -1, /* %fs */
192 -1 /* %gs */
193};
194
2213a65d 195static void
51433e4b 196amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
2213a65d 197{
c4f35dd8 198 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
187e21d1
MK
199
200 tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
201 tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
202 tdep->sizeof_gregset = 27 * 8;
203
90f90721 204 amd64_init_abi (info, gdbarch);
c4f35dd8 205
f561f026 206 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, amd64_linux_pc_in_sigtramp);
51433e4b
MK
207 tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
208 tdep->sc_reg_offset = amd64_linux_sc_reg_offset;
209 tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
187e21d1
MK
210
211 /* GNU/Linux uses SVR4-style shared libraries. */
212 set_solib_svr4_fetch_link_map_offsets
213 (gdbarch, svr4_lp64_fetch_link_map_offsets);
2213a65d 214}
c4f35dd8 215\f
2213a65d
MK
216
217/* Provide a prototype to silence -Wmissing-prototypes. */
51433e4b 218extern void _initialize_amd64_linux_tdep (void);
2213a65d
MK
219
220void
51433e4b 221_initialize_amd64_linux_tdep (void)
2213a65d 222{
51433e4b
MK
223 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
224 GDB_OSABI_LINUX, amd64_linux_init_abi);
2213a65d 225}
This page took 0.357031 seconds and 4 git commands to generate.