Replace hardwired error handlers in tui_initialize_io
[platform/upstream/binutils.git] / gdb / amd64fbsd-tdep.c
1 /* Target-dependent code for FreeBSD/amd64.
2
3    Copyright (C) 2003-2014 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "arch-utils.h"
22 #include "frame.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "osabi.h"
26
27 #include "amd64-tdep.h"
28 #include "bsd-uthread.h"
29 #include "solib-svr4.h"
30
31 /* Support for signal handlers.  */
32
33 /* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
34    address of the associated sigcontext structure.  */
35
36 static CORE_ADDR
37 amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
38 {
39   CORE_ADDR sp;
40
41   /* The `struct sigcontext' (which really is an `ucontext_t' on
42      FreeBSD/amd64) lives at a fixed offset in the signal frame.  See
43      <machine/sigframe.h>.  */
44   sp = frame_unwind_register_unsigned (this_frame, AMD64_RSP_REGNUM);
45   return sp + 16;
46 }
47 \f
48 /* FreeBSD 5.1-RELEASE or later.  */
49
50 /* Mapping between the general-purpose registers in `struct reg'
51    format and GDB's register cache layout.
52
53    Note that some registers are 32-bit, but since we're little-endian
54    we get away with that.  */
55
56 /* From <machine/reg.h>.  */
57 static int amd64fbsd_r_reg_offset[] =
58 {
59   14 * 8,                       /* %rax */
60   11 * 8,                       /* %rbx */
61   13 * 8,                       /* %rcx */
62   12 * 8,                       /* %rdx */
63   9 * 8,                        /* %rsi */
64   8 * 8,                        /* %rdi */
65   10 * 8,                       /* %rbp */
66   20 * 8,                       /* %rsp */
67   7 * 8,                        /* %r8 ...  */
68   6 * 8,
69   5 * 8,
70   4 * 8,
71   3 * 8,
72   2 * 8,
73   1 * 8,
74   0 * 8,                        /* ... %r15 */
75   17 * 8,                       /* %rip */
76   19 * 8,                       /* %eflags */
77   18 * 8,                       /* %cs */
78   21 * 8,                       /* %ss */
79   -1,                           /* %ds */
80   -1,                           /* %es */
81   -1,                           /* %fs */
82   -1                            /* %gs */
83 };
84
85 /* Location of the signal trampoline.  */
86 CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0ULL;
87 CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0ULL;
88
89 /* From <machine/signal.h>.  */
90 int amd64fbsd_sc_reg_offset[] =
91 {
92   24 + 6 * 8,                   /* %rax */
93   24 + 7 * 8,                   /* %rbx */
94   24 + 3 * 8,                   /* %rcx */
95   24 + 2 * 8,                   /* %rdx */
96   24 + 1 * 8,                   /* %rsi */
97   24 + 0 * 8,                   /* %rdi */
98   24 + 8 * 8,                   /* %rbp */
99   24 + 22 * 8,                  /* %rsp */
100   24 + 4 * 8,                   /* %r8 ...  */
101   24 + 5 * 8,
102   24 + 9 * 8,
103   24 + 10 * 8,
104   24 + 11 * 8,
105   24 + 12 * 8,
106   24 + 13 * 8,
107   24 + 14 * 8,                  /* ... %r15 */
108   24 + 19 * 8,                  /* %rip */
109   24 + 21 * 8,                  /* %eflags */
110   24 + 20 * 8,                  /* %cs */
111   24 + 23 * 8,                  /* %ss */
112   -1,                           /* %ds */
113   -1,                           /* %es */
114   -1,                           /* %fs */
115   -1                            /* %gs */
116 };
117
118 /* From /usr/src/lib/libc/amd64/gen/_setjmp.S.  */
119 static int amd64fbsd_jmp_buf_reg_offset[] =
120 {
121   -1,                           /* %rax */
122   1 * 8,                        /* %rbx */
123   -1,                           /* %rcx */
124   -1,                           /* %rdx */
125   -1,                           /* %rsi */
126   -1,                           /* %rdi */
127   3 * 8,                        /* %rbp */
128   2 * 8,                        /* %rsp */
129   -1,                           /* %r8 ...  */
130   -1,
131   -1,
132   -1,                           /* ... %r11 */
133   4 * 8,                        /* %r12 ...  */
134   5 * 8,
135   6 * 8,
136   7 * 8,                        /* ... %r15 */
137   0 * 8                         /* %rip */
138 };
139
140 static void
141 amd64fbsd_supply_uthread (struct regcache *regcache,
142                           int regnum, CORE_ADDR addr)
143 {
144   gdb_byte buf[8];
145   int i;
146
147   gdb_assert (regnum >= -1);
148
149   for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
150     {
151       if (amd64fbsd_jmp_buf_reg_offset[i] != -1
152           && (regnum == -1 || regnum == i))
153         {
154           read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
155           regcache_raw_supply (regcache, i, buf);
156         }
157     }
158 }
159
160 static void
161 amd64fbsd_collect_uthread (const struct regcache *regcache,
162                            int regnum, CORE_ADDR addr)
163 {
164   gdb_byte buf[8];
165   int i;
166
167   gdb_assert (regnum >= -1);
168
169   for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
170     {
171       if (amd64fbsd_jmp_buf_reg_offset[i] != -1
172           && (regnum == -1 || regnum == i))
173         {
174           regcache_raw_collect (regcache, i, buf);
175           write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
176         }
177     }
178 }
179
180 static void
181 amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
182 {
183   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
184
185   /* Obviously FreeBSD is BSD-based.  */
186   i386bsd_init_abi (info, gdbarch);
187
188   tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
189   tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
190   tdep->sizeof_gregset = 22 * 8;
191
192   amd64_init_abi (info, gdbarch);
193
194   tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
195   tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
196   tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
197   tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
198   tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
199
200   /* FreeBSD provides a user-level threads implementation.  */
201   bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread);
202   bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread);
203
204   /* FreeBSD uses SVR4-style shared libraries.  */
205   set_solib_svr4_fetch_link_map_offsets
206     (gdbarch, svr4_lp64_fetch_link_map_offsets);
207 }
208 \f
209
210 /* Provide a prototype to silence -Wmissing-prototypes.  */
211 void _initialize_amd64fbsd_tdep (void);
212
213 void
214 _initialize_amd64fbsd_tdep (void)
215 {
216   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
217                           GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi);
218 }