* amd64obsd-tdep.c, amd64obsd-nat.c: New files.
[external/binutils.git] / gdb / amd64obsd-tdep.c
1 /* Target-dependent code for OpenBSD/amd64.
2
3    Copyright 2003, 2004 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "gdbcore.h"
25 #include "osabi.h"
26 #include "target.h"
27
28 #include "gdb_assert.h"
29 #include "gdb_string.h"
30
31 #include "x86-64-tdep.h"
32
33 /* Support for signal handlers.  */
34
35 static const int amd64obsd_page_size = 4096;
36
37 static int
38 amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
39 {
40   CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
41   const char sigreturn[] =
42   {
43     0x48, 0xc7, 0xc0,
44     0x67, 0x00, 0x00, 0x00,     /* movq $SYS_sigreturn, %rax */
45     0x0f, 0x05                  /* syscall */
46   };
47   char *buf;
48
49   if (name)
50     return 0;
51
52   /* If we can't read the instructions at START_PC, return zero.  */
53   buf = alloca (sizeof sigreturn);
54   if (target_read_memory (start_pc + 0x7, buf, sizeof sigreturn))
55     return 0;
56
57   /* Check for sigreturn(2).  */
58   if (memcmp (buf, sigreturn, sizeof sigreturn))
59     return 0;
60
61   return 1;
62 }
63
64 /* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
65    routine, return the address of the associated sigcontext structure.  */
66
67 static CORE_ADDR
68 amd64obsd_sigcontext_addr (struct frame_info *next_frame)
69 {
70   /* The %rsp register points at `struct sigcontext' upon entry of a
71      signal trampoline.  */
72   return frame_unwind_register_unsigned (next_frame, X86_64_RSP_REGNUM);
73 }
74 \f
75 /* OpenBSD 3.5 or later.  */
76
77 /* Mapping between the general-purpose registers in `struct reg'
78    format and GDB's register cache layout.  */
79
80 /* From <machine/reg.h>.  Used for ptrace(2), but not for core dumps.  */
81 int amd64obsd_r_reg_offset[] =
82 {
83   14 * 8,                       /* %rax */
84   13 * 8,                       /* %rbx */
85   3 * 8,                        /* %rcx */
86   2 * 8,                        /* %rdx */
87   1 * 8,                        /* %rsi */
88   0 * 8,                        /* %rdi */
89   12 * 8,                       /* %rbp */
90   15 * 8,                       /* %rsp */
91   4 * 8,                        /* %r8 .. */
92   5 * 8,
93   6 * 8,
94   7 * 8,
95   8 * 8,
96   9 * 8,
97   10 * 8,
98   11 * 8,                       /* ... %r15 */
99   16 * 8,                       /* %rip */
100   17 * 8,                       /* %eflags */
101   18 * 8,                       /* %cs */
102   19 * 8,                       /* %ss */
103   20 * 8,                       /* %ds */
104   21 * 8,                       /* %es */
105   22 * 8,                       /* %fs */
106   23 * 8                        /* %gs */
107 };
108
109 /* From <machine/signal.h>.  Also used for core dumps.  */
110 static int amd64obsd_sc_reg_offset[] =
111 {
112   14 * 8,                       /* %rax */
113   13 * 8,                       /* %rbx */
114   3 * 8,                        /* %rcx */
115   2 * 8,                        /* %rdx */
116   1 * 8,                        /* %rsi */
117   0 * 8,                        /* %rdi */
118   12 * 8,                       /* %rbp */
119   24 * 8,                       /* %rsp */
120   4 * 8,                        /* %r8 ... */
121   5 * 8,
122   6 * 8,
123   7 * 8,
124   8 * 8,
125   9 * 8,
126   10 * 8,
127   11 * 8,                       /* ... %r15 */
128   21 * 8,                       /* %rip */
129   23 * 8,                       /* %eflags */
130   22 * 8,                       /* %cs */
131   25 * 8,                       /* %ss */
132   18 * 8,                       /* %ds */
133   17 * 8,                       /* %es */
134   16 * 8,                       /* %fs */
135   15 * 8                        /* %gs */
136 };
137
138 static void
139 amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
140 {
141   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
142
143   /* Initialize general-purpose register set details first.  */
144   tdep->gregset_reg_offset = amd64obsd_sc_reg_offset;
145   tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
146   tdep->sizeof_gregset = 26 * 8;
147
148   x86_64_init_abi (info, gdbarch);
149
150   tdep->jb_pc_offset = 7 * 8;
151
152   set_gdbarch_pc_in_sigtramp (gdbarch, amd64obsd_pc_in_sigtramp);
153   tdep->sigcontext_addr = amd64obsd_sigcontext_addr;
154   tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
155   tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
156 }
157 \f
158
159 /* Provide a prototype to silence -Wmissing-prototypes.  */
160 void _initialize_amd64obsd_tdep (void);
161
162 void
163 _initialize_amd64obsd_ndep (void)
164 {
165   /* The OpenBSD/amd64 native dependent code makes this assumption.  */
166   gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == X86_64_NUM_GREGS);
167
168   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
169                           GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi);
170 }