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