2011-01-07 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / amd64fbsd-tdep.c
CommitLineData
68cc0bfb 1/* Target-dependent code for FreeBSD/amd64.
477f40d1 2
7b6bb8da 3 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
0fb0cc75 4 Free Software Foundation, Inc.
68cc0bfb
MK
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
68cc0bfb
MK
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
68cc0bfb
MK
20
21#include "defs.h"
22#include "arch-utils.h"
23#include "frame.h"
24#include "gdbcore.h"
25#include "regcache.h"
26#include "osabi.h"
27
1c02b2a5 28#include "gdb_assert.h"
68cc0bfb
MK
29#include "gdb_string.h"
30
85be1ca6 31#include "amd64-tdep.h"
1c02b2a5 32#include "bsd-uthread.h"
7e654c37 33#include "solib-svr4.h"
68cc0bfb
MK
34
35/* Support for signal handlers. */
36
10458914
DJ
37/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
38 address of the associated sigcontext structure. */
68cc0bfb
MK
39
40static CORE_ADDR
10458914 41amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
68cc0bfb 42{
68cc0bfb
MK
43 CORE_ADDR sp;
44
212c460c
MK
45 /* The `struct sigcontext' (which really is an `ucontext_t' on
46 FreeBSD/amd64) lives at a fixed offset in the signal frame. See
47 <machine/sigframe.h>. */
10458914 48 sp = frame_unwind_register_unsigned (this_frame, AMD64_RSP_REGNUM);
212c460c 49 return sp + 16;
68cc0bfb
MK
50}
51\f
52/* FreeBSD 5.1-RELEASE or later. */
53
477f40d1
MK
54/* Mapping between the general-purpose registers in `struct reg'
55 format and GDB's register cache layout.
56
57 Note that some registers are 32-bit, but since we're little-endian
58 we get away with that. */
59
60/* From <machine/reg.h>. */
61static int amd64fbsd_r_reg_offset[] =
62{
af233647
MK
63 14 * 8, /* %rax */
64 11 * 8, /* %rbx */
65 13 * 8, /* %rcx */
66 12 * 8, /* %rdx */
67 9 * 8, /* %rsi */
68 8 * 8, /* %rdi */
69 10 * 8, /* %rbp */
70 20 * 8, /* %rsp */
0963b4bd 71 7 * 8, /* %r8 ... */
af233647
MK
72 6 * 8,
73 5 * 8,
74 4 * 8,
75 3 * 8,
76 2 * 8,
77 1 * 8,
78 0 * 8, /* ... %r15 */
79 17 * 8, /* %rip */
80 19 * 8, /* %eflags */
81 18 * 8, /* %cs */
82 21 * 8, /* %ss */
83 -1, /* %ds */
84 -1, /* %es */
85 -1, /* %fs */
86 -1 /* %gs */
477f40d1
MK
87};
88
68cc0bfb 89/* Location of the signal trampoline. */
ec20a626
UW
90CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0ULL;
91CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0ULL;
68cc0bfb
MK
92
93/* From <machine/signal.h>. */
af233647 94int amd64fbsd_sc_reg_offset[] =
68cc0bfb 95{
212c460c
MK
96 24 + 6 * 8, /* %rax */
97 24 + 7 * 8, /* %rbx */
98 24 + 3 * 8, /* %rcx */
99 24 + 2 * 8, /* %rdx */
100 24 + 1 * 8, /* %rsi */
101 24 + 0 * 8, /* %rdi */
102 24 + 8 * 8, /* %rbp */
dac94105 103 24 + 22 * 8, /* %rsp */
0963b4bd 104 24 + 4 * 8, /* %r8 ... */
af233647
MK
105 24 + 5 * 8,
106 24 + 9 * 8,
107 24 + 10 * 8,
108 24 + 11 * 8,
109 24 + 12 * 8,
110 24 + 13 * 8,
111 24 + 14 * 8, /* ... %r15 */
dac94105
MK
112 24 + 19 * 8, /* %rip */
113 24 + 21 * 8, /* %eflags */
af233647
MK
114 24 + 20 * 8, /* %cs */
115 24 + 23 * 8, /* %ss */
68cc0bfb
MK
116 -1, /* %ds */
117 -1, /* %es */
118 -1, /* %fs */
119 -1 /* %gs */
120};
121
1c02b2a5
MK
122/* From /usr/src/lib/libc/amd64/gen/_setjmp.S. */
123static int amd64fbsd_jmp_buf_reg_offset[] =
124{
125 -1, /* %rax */
126 1 * 8, /* %rbx */
127 -1, /* %rcx */
128 -1, /* %rdx */
129 -1, /* %rsi */
130 -1, /* %rdi */
131 3 * 8, /* %rbp */
132 2 * 8, /* %rsp */
0963b4bd 133 -1, /* %r8 ... */
1c02b2a5
MK
134 -1,
135 -1,
136 -1, /* ... %r11 */
0963b4bd 137 4 * 8, /* %r12 ... */
1c02b2a5
MK
138 5 * 8,
139 6 * 8,
140 7 * 8, /* ... %r15 */
141 0 * 8 /* %rip */
142};
143
144static void
145amd64fbsd_supply_uthread (struct regcache *regcache,
146 int regnum, CORE_ADDR addr)
147{
4252dc94 148 gdb_byte buf[8];
1c02b2a5
MK
149 int i;
150
151 gdb_assert (regnum >= -1);
152
153 for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
154 {
155 if (amd64fbsd_jmp_buf_reg_offset[i] != -1
156 && (regnum == -1 || regnum == i))
157 {
158 read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
159 regcache_raw_supply (regcache, i, buf);
160 }
161 }
162}
163
164static void
165amd64fbsd_collect_uthread (const struct regcache *regcache,
166 int regnum, CORE_ADDR addr)
167{
4252dc94 168 gdb_byte buf[8];
1c02b2a5
MK
169 int i;
170
171 gdb_assert (regnum >= -1);
172
173 for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
174 {
175 if (amd64fbsd_jmp_buf_reg_offset[i] != -1
176 && (regnum == -1 || regnum == i))
177 {
178 regcache_raw_collect (regcache, i, buf);
179 write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
180 }
181 }
182}
183
63807e1d 184static void
68cc0bfb
MK
185amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
186{
187 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
188
189 /* Obviously FreeBSD is BSD-based. */
190 i386bsd_init_abi (info, gdbarch);
191
477f40d1
MK
192 tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
193 tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
194 tdep->sizeof_gregset = 22 * 8;
195
90f90721 196 amd64_init_abi (info, gdbarch);
68cc0bfb 197
10fc94a4
MK
198 tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
199 tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
200 tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
201 tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
477f40d1 202 tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
7e654c37 203
1c02b2a5
MK
204 /* FreeBSD provides a user-level threads implementation. */
205 bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread);
206 bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread);
207
7e654c37
MK
208 /* FreeBSD uses SVR4-style shared libraries. */
209 set_solib_svr4_fetch_link_map_offsets
210 (gdbarch, svr4_lp64_fetch_link_map_offsets);
68cc0bfb
MK
211}
212\f
213
214/* Provide a prototype to silence -Wmissing-prototypes. */
215void _initialize_amd64fbsd_tdep (void);
216
217void
218_initialize_amd64fbsd_tdep (void)
219{
220 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
221 GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi);
222}
This page took 0.539388 seconds and 4 git commands to generate.