Commit | Line | Data |
---|---|---|
51433e4b | 1 | /* Target-dependent code for GNU/Linux x86-64. |
a4b6fc86 | 2 | |
0fb0cc75 | 3 | Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
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" | |
35669430 | 23 | #include "arch-utils.h" |
187e21d1 | 24 | #include "frame.h" |
53e95fcf JS |
25 | #include "gdbcore.h" |
26 | #include "regcache.h" | |
84dc46cb | 27 | #include "osabi.h" |
911bc6ee | 28 | #include "symtab.h" |
8695c747 DJ |
29 | #include "gdbtypes.h" |
30 | #include "reggroups.h" | |
31 | #include "amd64-linux-tdep.h" | |
53e95fcf | 32 | |
c4f35dd8 | 33 | #include "gdb_string.h" |
53e95fcf | 34 | |
9c1488cb | 35 | #include "amd64-tdep.h" |
187e21d1 | 36 | #include "solib-svr4.h" |
eba29c8c ML |
37 | |
38 | /* Mapping between the general-purpose registers in `struct user' | |
187e21d1 | 39 | format and GDB's register cache layout. */ |
eba29c8c | 40 | |
187e21d1 MK |
41 | /* From <sys/reg.h>. */ |
42 | static int amd64_linux_gregset_reg_offset[] = | |
eba29c8c | 43 | { |
187e21d1 MK |
44 | 10 * 8, /* %rax */ |
45 | 5 * 8, /* %rbx */ | |
46 | 11 * 8, /* %rcx */ | |
47 | 12 * 8, /* %rdx */ | |
48 | 13 * 8, /* %rsi */ | |
49 | 14 * 8, /* %rdi */ | |
50 | 4 * 8, /* %rbp */ | |
51 | 19 * 8, /* %rsp */ | |
52 | 9 * 8, /* %r8 ... */ | |
53 | 8 * 8, | |
54 | 7 * 8, | |
55 | 6 * 8, | |
56 | 3 * 8, | |
57 | 2 * 8, | |
58 | 1 * 8, | |
59 | 0 * 8, /* ... %r15 */ | |
60 | 16 * 8, /* %rip */ | |
61 | 18 * 8, /* %eflags */ | |
62 | 17 * 8, /* %cs */ | |
63 | 20 * 8, /* %ss */ | |
64 | 23 * 8, /* %ds */ | |
65 | 24 * 8, /* %es */ | |
66 | 25 * 8, /* %fs */ | |
67 | 26 * 8 /* %gs */ | |
eba29c8c | 68 | }; |
187e21d1 | 69 | \f |
eba29c8c | 70 | |
187e21d1 | 71 | /* Support for signal handlers. */ |
c4f35dd8 MK |
72 | |
73 | #define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */ | |
74 | #define LINUX_SIGTRAMP_OFFSET0 0 | |
75 | #define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */ | |
76 | #define LINUX_SIGTRAMP_OFFSET1 7 | |
77 | ||
4252dc94 | 78 | static const gdb_byte linux_sigtramp_code[] = |
c4f35dd8 MK |
79 | { |
80 | /* mov $__NR_rt_sigreturn, %rax */ | |
baed091b ML |
81 | LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00, |
82 | /* syscall */ | |
83 | LINUX_SIGTRAMP_INSN1, 0x05 | |
53e95fcf JS |
84 | }; |
85 | ||
86 | #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) | |
87 | ||
88 | /* If PC is in a sigtramp routine, return the address of the start of | |
89 | the routine. Otherwise, return 0. */ | |
90 | ||
91 | static CORE_ADDR | |
10458914 | 92 | amd64_linux_sigtramp_start (struct frame_info *this_frame) |
53e95fcf | 93 | { |
10458914 | 94 | CORE_ADDR pc = get_frame_pc (this_frame); |
4252dc94 | 95 | gdb_byte buf[LINUX_SIGTRAMP_LEN]; |
c4f35dd8 MK |
96 | |
97 | /* We only recognize a signal trampoline if PC is at the start of | |
98 | one of the two instructions. We optimize for finding the PC at | |
99 | the start, as will be the case when the trampoline is not the | |
100 | first frame on the stack. We assume that in the case where the | |
101 | PC is not at the start of the instruction sequence, there will be | |
102 | a few trailing readable bytes on the stack. */ | |
103 | ||
10458914 | 104 | if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) |
53e95fcf JS |
105 | return 0; |
106 | ||
107 | if (buf[0] != LINUX_SIGTRAMP_INSN0) | |
108 | { | |
109 | if (buf[0] != LINUX_SIGTRAMP_INSN1) | |
110 | return 0; | |
111 | ||
112 | pc -= LINUX_SIGTRAMP_OFFSET1; | |
10458914 | 113 | if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) |
53e95fcf JS |
114 | return 0; |
115 | } | |
116 | ||
117 | if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) | |
118 | return 0; | |
119 | ||
120 | return pc; | |
121 | } | |
122 | ||
10458914 DJ |
123 | /* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp |
124 | routine. */ | |
baed091b | 125 | |
c4f35dd8 | 126 | static int |
10458914 | 127 | amd64_linux_sigtramp_p (struct frame_info *this_frame) |
baed091b | 128 | { |
10458914 | 129 | CORE_ADDR pc = get_frame_pc (this_frame); |
911bc6ee MK |
130 | char *name; |
131 | ||
132 | find_pc_partial_function (pc, &name, NULL, NULL); | |
133 | ||
c4f35dd8 MK |
134 | /* If we have NAME, we can optimize the search. The trampoline is |
135 | named __restore_rt. However, it isn't dynamically exported from | |
136 | the shared C library, so the trampoline may appear to be part of | |
137 | the preceding function. This should always be sigaction, | |
138 | __sigaction, or __libc_sigaction (all aliases to the same | |
139 | function). */ | |
140 | if (name == NULL || strstr (name, "sigaction") != NULL) | |
10458914 | 141 | return (amd64_linux_sigtramp_start (this_frame) != 0); |
c4f35dd8 MK |
142 | |
143 | return (strcmp ("__restore_rt", name) == 0); | |
baed091b ML |
144 | } |
145 | ||
c4f35dd8 | 146 | /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */ |
51433e4b | 147 | #define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40 |
b64bbf8c | 148 | |
10458914 DJ |
149 | /* Assuming THIS_FRAME is a GNU/Linux sigtramp routine, return the |
150 | address of the associated sigcontext structure. */ | |
baed091b | 151 | |
c4f35dd8 | 152 | static CORE_ADDR |
10458914 | 153 | amd64_linux_sigcontext_addr (struct frame_info *this_frame) |
baed091b | 154 | { |
c4f35dd8 | 155 | CORE_ADDR sp; |
4252dc94 | 156 | gdb_byte buf[8]; |
c4f35dd8 | 157 | |
10458914 | 158 | get_frame_register (this_frame, AMD64_RSP_REGNUM, 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); | |
35669430 DE |
290 | |
291 | /* Displaced stepping. */ | |
292 | set_gdbarch_displaced_step_copy_insn (gdbarch, | |
293 | amd64_displaced_step_copy_insn); | |
294 | set_gdbarch_displaced_step_fixup (gdbarch, amd64_displaced_step_fixup); | |
295 | set_gdbarch_displaced_step_free_closure (gdbarch, | |
296 | simple_displaced_step_free_closure); | |
297 | set_gdbarch_displaced_step_location (gdbarch, | |
298 | displaced_step_at_entry_point); | |
2213a65d | 299 | } |
c4f35dd8 | 300 | \f |
2213a65d MK |
301 | |
302 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
51433e4b | 303 | extern void _initialize_amd64_linux_tdep (void); |
2213a65d MK |
304 | |
305 | void | |
51433e4b | 306 | _initialize_amd64_linux_tdep (void) |
2213a65d | 307 | { |
51433e4b MK |
308 | gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, |
309 | GDB_OSABI_LINUX, amd64_linux_init_abi); | |
2213a65d | 310 | } |