Commit | Line | Data |
---|---|---|
51433e4b | 1 | /* Target-dependent code for GNU/Linux x86-64. |
a4b6fc86 | 2 | |
9b254dd1 | 3 | Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008 |
6aba47ca | 4 | Free Software Foundation, Inc. |
53e95fcf JS |
5 | Contributed by Jiri Smid, SuSE Labs. |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 11 | the Free Software Foundation; either version 3 of the License, or |
53e95fcf JS |
12 | (at your option) any later version. |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
a9762ec7 | 20 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
53e95fcf JS |
21 | |
22 | #include "defs.h" | |
187e21d1 | 23 | #include "frame.h" |
53e95fcf JS |
24 | #include "gdbcore.h" |
25 | #include "regcache.h" | |
84dc46cb | 26 | #include "osabi.h" |
911bc6ee | 27 | #include "symtab.h" |
8695c747 DJ |
28 | #include "gdbtypes.h" |
29 | #include "reggroups.h" | |
30 | #include "amd64-linux-tdep.h" | |
53e95fcf | 31 | |
c4f35dd8 | 32 | #include "gdb_string.h" |
53e95fcf | 33 | |
9c1488cb | 34 | #include "amd64-tdep.h" |
187e21d1 | 35 | #include "solib-svr4.h" |
eba29c8c ML |
36 | |
37 | /* Mapping between the general-purpose registers in `struct user' | |
187e21d1 | 38 | format and GDB's register cache layout. */ |
eba29c8c | 39 | |
187e21d1 MK |
40 | /* From <sys/reg.h>. */ |
41 | static int amd64_linux_gregset_reg_offset[] = | |
eba29c8c | 42 | { |
187e21d1 MK |
43 | 10 * 8, /* %rax */ |
44 | 5 * 8, /* %rbx */ | |
45 | 11 * 8, /* %rcx */ | |
46 | 12 * 8, /* %rdx */ | |
47 | 13 * 8, /* %rsi */ | |
48 | 14 * 8, /* %rdi */ | |
49 | 4 * 8, /* %rbp */ | |
50 | 19 * 8, /* %rsp */ | |
51 | 9 * 8, /* %r8 ... */ | |
52 | 8 * 8, | |
53 | 7 * 8, | |
54 | 6 * 8, | |
55 | 3 * 8, | |
56 | 2 * 8, | |
57 | 1 * 8, | |
58 | 0 * 8, /* ... %r15 */ | |
59 | 16 * 8, /* %rip */ | |
60 | 18 * 8, /* %eflags */ | |
61 | 17 * 8, /* %cs */ | |
62 | 20 * 8, /* %ss */ | |
63 | 23 * 8, /* %ds */ | |
64 | 24 * 8, /* %es */ | |
65 | 25 * 8, /* %fs */ | |
66 | 26 * 8 /* %gs */ | |
eba29c8c | 67 | }; |
187e21d1 | 68 | \f |
eba29c8c | 69 | |
187e21d1 | 70 | /* Support for signal handlers. */ |
c4f35dd8 MK |
71 | |
72 | #define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */ | |
73 | #define LINUX_SIGTRAMP_OFFSET0 0 | |
74 | #define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */ | |
75 | #define LINUX_SIGTRAMP_OFFSET1 7 | |
76 | ||
4252dc94 | 77 | static const gdb_byte linux_sigtramp_code[] = |
c4f35dd8 MK |
78 | { |
79 | /* mov $__NR_rt_sigreturn, %rax */ | |
baed091b ML |
80 | LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00, |
81 | /* syscall */ | |
82 | LINUX_SIGTRAMP_INSN1, 0x05 | |
53e95fcf JS |
83 | }; |
84 | ||
85 | #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) | |
86 | ||
87 | /* If PC is in a sigtramp routine, return the address of the start of | |
88 | the routine. Otherwise, return 0. */ | |
89 | ||
90 | static CORE_ADDR | |
387c058c | 91 | amd64_linux_sigtramp_start (struct frame_info *next_frame) |
53e95fcf | 92 | { |
387c058c | 93 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
4252dc94 | 94 | gdb_byte buf[LINUX_SIGTRAMP_LEN]; |
c4f35dd8 MK |
95 | |
96 | /* We only recognize a signal trampoline if PC is at the start of | |
97 | one of the two instructions. We optimize for finding the PC at | |
98 | the start, as will be the case when the trampoline is not the | |
99 | first frame on the stack. We assume that in the case where the | |
100 | PC is not at the start of the instruction sequence, there will be | |
101 | a few trailing readable bytes on the stack. */ | |
102 | ||
55e5a6d0 | 103 | if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) |
53e95fcf JS |
104 | return 0; |
105 | ||
106 | if (buf[0] != LINUX_SIGTRAMP_INSN0) | |
107 | { | |
108 | if (buf[0] != LINUX_SIGTRAMP_INSN1) | |
109 | return 0; | |
110 | ||
111 | pc -= LINUX_SIGTRAMP_OFFSET1; | |
55e5a6d0 | 112 | if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) |
53e95fcf JS |
113 | return 0; |
114 | } | |
115 | ||
116 | if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) | |
117 | return 0; | |
118 | ||
119 | return pc; | |
120 | } | |
121 | ||
377d9ebd | 122 | /* Return whether the frame preceding NEXT_FRAME corresponds to a |
911bc6ee | 123 | GNU/Linux sigtramp routine. */ |
baed091b | 124 | |
c4f35dd8 | 125 | static int |
911bc6ee | 126 | amd64_linux_sigtramp_p (struct frame_info *next_frame) |
baed091b | 127 | { |
911bc6ee MK |
128 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
129 | char *name; | |
130 | ||
131 | find_pc_partial_function (pc, &name, NULL, NULL); | |
132 | ||
c4f35dd8 MK |
133 | /* If we have NAME, we can optimize the search. The trampoline is |
134 | named __restore_rt. However, it isn't dynamically exported from | |
135 | the shared C library, so the trampoline may appear to be part of | |
136 | the preceding function. This should always be sigaction, | |
137 | __sigaction, or __libc_sigaction (all aliases to the same | |
138 | function). */ | |
139 | if (name == NULL || strstr (name, "sigaction") != NULL) | |
387c058c | 140 | return (amd64_linux_sigtramp_start (next_frame) != 0); |
c4f35dd8 MK |
141 | |
142 | return (strcmp ("__restore_rt", name) == 0); | |
baed091b ML |
143 | } |
144 | ||
c4f35dd8 | 145 | /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */ |
51433e4b | 146 | #define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40 |
b64bbf8c | 147 | |
c4f35dd8 MK |
148 | /* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp |
149 | routine, return the address of the associated sigcontext structure. */ | |
baed091b | 150 | |
c4f35dd8 | 151 | static CORE_ADDR |
51433e4b | 152 | amd64_linux_sigcontext_addr (struct frame_info *next_frame) |
baed091b | 153 | { |
c4f35dd8 | 154 | CORE_ADDR sp; |
4252dc94 | 155 | gdb_byte buf[8]; |
c4f35dd8 | 156 | |
2ae02b47 UW |
157 | frame_unwind_register (next_frame, |
158 | gdbarch_sp_regnum (get_frame_arch (next_frame)), buf); | |
c4f35dd8 MK |
159 | sp = extract_unsigned_integer (buf, 8); |
160 | ||
161 | /* The sigcontext structure is part of the user context. A pointer | |
162 | to the user context is passed as the third argument to the signal | |
163 | handler, i.e. in %rdx. Unfortunately %rdx isn't preserved across | |
164 | function calls so we can't use it. Fortunately the user context | |
165 | is part of the signal frame and the unwound %rsp directly points | |
166 | at it. */ | |
51433e4b | 167 | return sp + AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET; |
baed091b | 168 | } |
2213a65d MK |
169 | \f |
170 | ||
2b5e0749 | 171 | /* From <asm/sigcontext.h>. */ |
51433e4b | 172 | static int amd64_linux_sc_reg_offset[] = |
2b5e0749 MK |
173 | { |
174 | 13 * 8, /* %rax */ | |
175 | 11 * 8, /* %rbx */ | |
176 | 14 * 8, /* %rcx */ | |
177 | 12 * 8, /* %rdx */ | |
178 | 9 * 8, /* %rsi */ | |
179 | 8 * 8, /* %rdi */ | |
180 | 10 * 8, /* %rbp */ | |
181 | 15 * 8, /* %rsp */ | |
182 | 0 * 8, /* %r8 */ | |
183 | 1 * 8, /* %r9 */ | |
184 | 2 * 8, /* %r10 */ | |
185 | 3 * 8, /* %r11 */ | |
186 | 4 * 8, /* %r12 */ | |
187 | 5 * 8, /* %r13 */ | |
188 | 6 * 8, /* %r14 */ | |
189 | 7 * 8, /* %r15 */ | |
190 | 16 * 8, /* %rip */ | |
191 | 17 * 8, /* %eflags */ | |
2b5e0749 | 192 | |
af233647 | 193 | /* FIXME: kettenis/2002030531: The registers %cs, %fs and %gs are |
2b5e0749 MK |
194 | available in `struct sigcontext'. However, they only occupy two |
195 | bytes instead of four, which makes using them here rather | |
196 | difficult. Leave them out for now. */ | |
af233647 MK |
197 | -1, /* %cs */ |
198 | -1, /* %ss */ | |
199 | -1, /* %ds */ | |
200 | -1, /* %es */ | |
2b5e0749 MK |
201 | -1, /* %fs */ |
202 | -1 /* %gs */ | |
203 | }; | |
204 | ||
8695c747 DJ |
205 | /* Replacement register functions which know about %orig_rax. */ |
206 | ||
207 | static const char * | |
d93859e2 | 208 | amd64_linux_register_name (struct gdbarch *gdbarch, int reg) |
8695c747 DJ |
209 | { |
210 | if (reg == AMD64_LINUX_ORIG_RAX_REGNUM) | |
211 | return "orig_rax"; | |
212 | ||
d93859e2 | 213 | return amd64_register_name (gdbarch, reg); |
8695c747 DJ |
214 | } |
215 | ||
216 | static struct type * | |
217 | amd64_linux_register_type (struct gdbarch *gdbarch, int reg) | |
218 | { | |
219 | if (reg == AMD64_LINUX_ORIG_RAX_REGNUM) | |
220 | return builtin_type_int64; | |
221 | ||
222 | return amd64_register_type (gdbarch, reg); | |
223 | } | |
224 | ||
225 | static int | |
226 | amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | |
227 | struct reggroup *group) | |
228 | { | |
229 | if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM) | |
230 | return (group == system_reggroup | |
231 | || group == save_reggroup | |
232 | || group == restore_reggroup); | |
233 | return default_register_reggroup_p (gdbarch, regnum, group); | |
234 | } | |
235 | ||
236 | /* Set the program counter for process PTID to PC. */ | |
237 | ||
238 | static void | |
61a1198a | 239 | amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) |
8695c747 | 240 | { |
61a1198a | 241 | regcache_cooked_write_unsigned (regcache, AMD64_RIP_REGNUM, pc); |
8695c747 DJ |
242 | |
243 | /* We must be careful with modifying the program counter. If we | |
244 | just interrupted a system call, the kernel might try to restart | |
245 | it when we resume the inferior. On restarting the system call, | |
246 | the kernel will try backing up the program counter even though it | |
247 | no longer points at the system call. This typically results in a | |
248 | SIGSEGV or SIGILL. We can prevent this by writing `-1' in the | |
249 | "orig_rax" pseudo-register. | |
250 | ||
251 | Note that "orig_rax" is saved when setting up a dummy call frame. | |
252 | This means that it is properly restored when that frame is | |
253 | popped, and that the interrupted system call will be restarted | |
254 | when we resume the inferior on return from a function call from | |
255 | within GDB. In all other cases the system call will not be | |
256 | restarted. */ | |
61a1198a | 257 | regcache_cooked_write_unsigned (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, -1); |
8695c747 DJ |
258 | } |
259 | ||
2213a65d | 260 | static void |
51433e4b | 261 | amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
2213a65d | 262 | { |
c4f35dd8 | 263 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
187e21d1 MK |
264 | |
265 | tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset; | |
266 | tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); | |
267 | tdep->sizeof_gregset = 27 * 8; | |
268 | ||
90f90721 | 269 | amd64_init_abi (info, gdbarch); |
c4f35dd8 | 270 | |
911bc6ee | 271 | tdep->sigtramp_p = amd64_linux_sigtramp_p; |
51433e4b MK |
272 | tdep->sigcontext_addr = amd64_linux_sigcontext_addr; |
273 | tdep->sc_reg_offset = amd64_linux_sc_reg_offset; | |
274 | tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset); | |
187e21d1 MK |
275 | |
276 | /* GNU/Linux uses SVR4-style shared libraries. */ | |
277 | set_solib_svr4_fetch_link_map_offsets | |
278 | (gdbarch, svr4_lp64_fetch_link_map_offsets); | |
b2756930 | 279 | |
8695c747 DJ |
280 | /* Add the %orig_rax register used for syscall restarting. */ |
281 | set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc); | |
282 | set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); | |
283 | set_gdbarch_register_name (gdbarch, amd64_linux_register_name); | |
284 | set_gdbarch_register_type (gdbarch, amd64_linux_register_type); | |
285 | set_gdbarch_register_reggroup_p (gdbarch, amd64_linux_register_reggroup_p); | |
286 | ||
b2756930 KB |
287 | /* Enable TLS support. */ |
288 | set_gdbarch_fetch_tls_load_module_address (gdbarch, | |
289 | svr4_fetch_objfile_link_map); | |
2213a65d | 290 | } |
c4f35dd8 | 291 | \f |
2213a65d MK |
292 | |
293 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
51433e4b | 294 | extern void _initialize_amd64_linux_tdep (void); |
2213a65d MK |
295 | |
296 | void | |
51433e4b | 297 | _initialize_amd64_linux_tdep (void) |
2213a65d | 298 | { |
51433e4b MK |
299 | gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, |
300 | GDB_OSABI_LINUX, amd64_linux_init_abi); | |
2213a65d | 301 | } |