]> Git Repo - binutils.git/blob - gdb/amd64-linux-tdep.c
* gdb.cp/hang.exp: Use .cc instead of .C.
[binutils.git] / gdb / amd64-linux-tdep.c
1 /* Target-dependent code for GNU/Linux x86-64.
2
3    Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008
4    Free Software Foundation, Inc.
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
11    the Free Software Foundation; either version 3 of the License, or
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
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "gdbcore.h"
25 #include "regcache.h"
26 #include "osabi.h"
27 #include "symtab.h"
28 #include "gdbtypes.h"
29 #include "reggroups.h"
30 #include "amd64-linux-tdep.h"
31
32 #include "gdb_string.h"
33
34 #include "amd64-tdep.h"
35 #include "solib-svr4.h"
36
37 /* Mapping between the general-purpose registers in `struct user'
38    format and GDB's register cache layout.  */
39
40 /* From <sys/reg.h>.  */
41 static int amd64_linux_gregset_reg_offset[] =
42 {
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 */
67 };
68 \f
69
70 /* Support for signal handlers.  */
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
77 static const gdb_byte linux_sigtramp_code[] =
78 {
79   /* mov $__NR_rt_sigreturn, %rax */
80   LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
81   /* syscall */
82   LINUX_SIGTRAMP_INSN1, 0x05
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
91 amd64_linux_sigtramp_start (struct frame_info *next_frame)
92 {
93   CORE_ADDR pc = frame_pc_unwind (next_frame);
94   gdb_byte buf[LINUX_SIGTRAMP_LEN];
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
103   if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
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;
112       if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
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
122 /* Return whether the frame preceding NEXT_FRAME corresponds to a
123    GNU/Linux sigtramp routine.  */
124
125 static int
126 amd64_linux_sigtramp_p (struct frame_info *next_frame)
127 {
128   CORE_ADDR pc = frame_pc_unwind (next_frame);
129   char *name;
130
131   find_pc_partial_function (pc, &name, NULL, NULL);
132
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)
140     return (amd64_linux_sigtramp_start (next_frame) != 0);
141
142   return (strcmp ("__restore_rt", name) == 0);
143 }
144
145 /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
146 #define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
147
148 /* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
149    routine, return the address of the associated sigcontext structure.  */
150
151 static CORE_ADDR
152 amd64_linux_sigcontext_addr (struct frame_info *next_frame)
153 {
154   CORE_ADDR sp;
155   gdb_byte buf[8];
156
157   frame_unwind_register (next_frame,
158                          gdbarch_sp_regnum (get_frame_arch (next_frame)), buf);
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.  */
167   return sp + AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
168 }
169 \f
170
171 /* From <asm/sigcontext.h>.  */
172 static int amd64_linux_sc_reg_offset[] =
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 */
192
193   /* FIXME: kettenis/2002030531: The registers %cs, %fs and %gs are
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.  */
197   -1,                           /* %cs */
198   -1,                           /* %ss */
199   -1,                           /* %ds */
200   -1,                           /* %es */
201   -1,                           /* %fs */
202   -1                            /* %gs */
203 };
204
205 /* Replacement register functions which know about %orig_rax.  */
206
207 static const char *
208 amd64_linux_register_name (struct gdbarch *gdbarch, int reg)
209 {
210   if (reg == AMD64_LINUX_ORIG_RAX_REGNUM)
211     return "orig_rax";
212
213   return amd64_register_name (gdbarch, reg);
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
239 amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
240 {
241   regcache_cooked_write_unsigned (regcache, AMD64_RIP_REGNUM, pc);
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.  */
257   regcache_cooked_write_unsigned (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, -1);
258 }
259
260 static void
261 amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
262 {
263   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
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
269   amd64_init_abi (info, gdbarch);
270
271   tdep->sigtramp_p = amd64_linux_sigtramp_p;
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);
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);
279
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
287   /* Enable TLS support.  */
288   set_gdbarch_fetch_tls_load_module_address (gdbarch,
289                                              svr4_fetch_objfile_link_map);
290 }
291 \f
292
293 /* Provide a prototype to silence -Wmissing-prototypes.  */
294 extern void _initialize_amd64_linux_tdep (void);
295
296 void
297 _initialize_amd64_linux_tdep (void)
298 {
299   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
300                           GDB_OSABI_LINUX, amd64_linux_init_abi);
301 }
This page took 0.038462 seconds and 4 git commands to generate.