xref: /dflybsd-src/contrib/gdb-7/gdb/i386fbsd-tdep.c (revision 5796c8dc12c637f18a1740c26afd8d40ffa9b719)
1*5796c8dcSSimon Schubert /* Target-dependent code for FreeBSD/i386.
2*5796c8dcSSimon Schubert 
3*5796c8dcSSimon Schubert    Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
4*5796c8dcSSimon Schubert    Free Software Foundation, Inc.
5*5796c8dcSSimon Schubert 
6*5796c8dcSSimon Schubert    This file is part of GDB.
7*5796c8dcSSimon Schubert 
8*5796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
9*5796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
10*5796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
11*5796c8dcSSimon Schubert    (at your option) any later version.
12*5796c8dcSSimon Schubert 
13*5796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
14*5796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*5796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*5796c8dcSSimon Schubert    GNU General Public License for more details.
17*5796c8dcSSimon Schubert 
18*5796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
19*5796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20*5796c8dcSSimon Schubert 
21*5796c8dcSSimon Schubert #include "defs.h"
22*5796c8dcSSimon Schubert #include "arch-utils.h"
23*5796c8dcSSimon Schubert #include "gdbcore.h"
24*5796c8dcSSimon Schubert #include "osabi.h"
25*5796c8dcSSimon Schubert #include "regcache.h"
26*5796c8dcSSimon Schubert 
27*5796c8dcSSimon Schubert #include "gdb_assert.h"
28*5796c8dcSSimon Schubert 
29*5796c8dcSSimon Schubert #include "i386-tdep.h"
30*5796c8dcSSimon Schubert #include "i387-tdep.h"
31*5796c8dcSSimon Schubert #include "bsd-uthread.h"
32*5796c8dcSSimon Schubert #include "solib-svr4.h"
33*5796c8dcSSimon Schubert 
34*5796c8dcSSimon Schubert /* FreeBSD 3.0-RELEASE or later.  */
35*5796c8dcSSimon Schubert 
36*5796c8dcSSimon Schubert /* From <machine/reg.h>.  */
37*5796c8dcSSimon Schubert static int i386fbsd_r_reg_offset[] =
38*5796c8dcSSimon Schubert {
39*5796c8dcSSimon Schubert   9 * 4, 8 * 4, 7 * 4, 6 * 4,	/* %eax, %ecx, %edx, %ebx */
40*5796c8dcSSimon Schubert   15 * 4, 4 * 4,		/* %esp, %ebp */
41*5796c8dcSSimon Schubert   3 * 4, 2 * 4,			/* %esi, %edi */
42*5796c8dcSSimon Schubert   12 * 4, 14 * 4,		/* %eip, %eflags */
43*5796c8dcSSimon Schubert   13 * 4, 16 * 4,		/* %cs, %ss */
44*5796c8dcSSimon Schubert   1 * 4, 0 * 4, -1, -1		/* %ds, %es, %fs, %gs */
45*5796c8dcSSimon Schubert };
46*5796c8dcSSimon Schubert 
47*5796c8dcSSimon Schubert /* Sigtramp routine location.  */
48*5796c8dcSSimon Schubert CORE_ADDR i386fbsd_sigtramp_start_addr = 0xbfbfdf20;
49*5796c8dcSSimon Schubert CORE_ADDR i386fbsd_sigtramp_end_addr = 0xbfbfdff0;
50*5796c8dcSSimon Schubert 
51*5796c8dcSSimon Schubert /* From <machine/signal.h>.  */
52*5796c8dcSSimon Schubert int i386fbsd_sc_reg_offset[] =
53*5796c8dcSSimon Schubert {
54*5796c8dcSSimon Schubert   8 + 14 * 4,			/* %eax */
55*5796c8dcSSimon Schubert   8 + 13 * 4,			/* %ecx */
56*5796c8dcSSimon Schubert   8 + 12 * 4,			/* %edx */
57*5796c8dcSSimon Schubert   8 + 11 * 4,			/* %ebx */
58*5796c8dcSSimon Schubert   8 + 0 * 4,                    /* %esp */
59*5796c8dcSSimon Schubert   8 + 1 * 4,                    /* %ebp */
60*5796c8dcSSimon Schubert   8 + 10 * 4,                   /* %esi */
61*5796c8dcSSimon Schubert   8 + 9 * 4,                    /* %edi */
62*5796c8dcSSimon Schubert   8 + 3 * 4,                    /* %eip */
63*5796c8dcSSimon Schubert   8 + 4 * 4,                    /* %eflags */
64*5796c8dcSSimon Schubert   8 + 7 * 4,                    /* %cs */
65*5796c8dcSSimon Schubert   8 + 8 * 4,                    /* %ss */
66*5796c8dcSSimon Schubert   8 + 6 * 4,                    /* %ds */
67*5796c8dcSSimon Schubert   8 + 5 * 4,                    /* %es */
68*5796c8dcSSimon Schubert   8 + 15 * 4,			/* %fs */
69*5796c8dcSSimon Schubert   8 + 16 * 4			/* %gs */
70*5796c8dcSSimon Schubert };
71*5796c8dcSSimon Schubert 
72*5796c8dcSSimon Schubert /* From /usr/src/lib/libc/i386/gen/_setjmp.S.  */
73*5796c8dcSSimon Schubert static int i386fbsd_jmp_buf_reg_offset[] =
74*5796c8dcSSimon Schubert {
75*5796c8dcSSimon Schubert   -1,				/* %eax */
76*5796c8dcSSimon Schubert   -1,				/* %ecx */
77*5796c8dcSSimon Schubert   -1,				/* %edx */
78*5796c8dcSSimon Schubert   1 * 4,			/* %ebx */
79*5796c8dcSSimon Schubert   2 * 4,			/* %esp */
80*5796c8dcSSimon Schubert   3 * 4,			/* %ebp */
81*5796c8dcSSimon Schubert   4 * 4,			/* %esi */
82*5796c8dcSSimon Schubert   5 * 4,			/* %edi */
83*5796c8dcSSimon Schubert   0 * 4				/* %eip */
84*5796c8dcSSimon Schubert };
85*5796c8dcSSimon Schubert 
86*5796c8dcSSimon Schubert static void
87*5796c8dcSSimon Schubert i386fbsd_supply_uthread (struct regcache *regcache,
88*5796c8dcSSimon Schubert 			 int regnum, CORE_ADDR addr)
89*5796c8dcSSimon Schubert {
90*5796c8dcSSimon Schubert   char buf[4];
91*5796c8dcSSimon Schubert   int i;
92*5796c8dcSSimon Schubert 
93*5796c8dcSSimon Schubert   gdb_assert (regnum >= -1);
94*5796c8dcSSimon Schubert 
95*5796c8dcSSimon Schubert   for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
96*5796c8dcSSimon Schubert     {
97*5796c8dcSSimon Schubert       if (i386fbsd_jmp_buf_reg_offset[i] != -1
98*5796c8dcSSimon Schubert 	  && (regnum == -1 || regnum == i))
99*5796c8dcSSimon Schubert 	{
100*5796c8dcSSimon Schubert 	  read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
101*5796c8dcSSimon Schubert 	  regcache_raw_supply (regcache, i, buf);
102*5796c8dcSSimon Schubert 	}
103*5796c8dcSSimon Schubert     }
104*5796c8dcSSimon Schubert }
105*5796c8dcSSimon Schubert 
106*5796c8dcSSimon Schubert static void
107*5796c8dcSSimon Schubert i386fbsd_collect_uthread (const struct regcache *regcache,
108*5796c8dcSSimon Schubert 			  int regnum, CORE_ADDR addr)
109*5796c8dcSSimon Schubert {
110*5796c8dcSSimon Schubert   char buf[4];
111*5796c8dcSSimon Schubert   int i;
112*5796c8dcSSimon Schubert 
113*5796c8dcSSimon Schubert   gdb_assert (regnum >= -1);
114*5796c8dcSSimon Schubert 
115*5796c8dcSSimon Schubert   for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
116*5796c8dcSSimon Schubert     {
117*5796c8dcSSimon Schubert       if (i386fbsd_jmp_buf_reg_offset[i] != -1
118*5796c8dcSSimon Schubert 	  && (regnum == -1 || regnum == i))
119*5796c8dcSSimon Schubert 	{
120*5796c8dcSSimon Schubert 	  regcache_raw_collect (regcache, i, buf);
121*5796c8dcSSimon Schubert 	  write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
122*5796c8dcSSimon Schubert 	}
123*5796c8dcSSimon Schubert     }
124*5796c8dcSSimon Schubert }
125*5796c8dcSSimon Schubert 
126*5796c8dcSSimon Schubert static void
127*5796c8dcSSimon Schubert i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
128*5796c8dcSSimon Schubert {
129*5796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
130*5796c8dcSSimon Schubert 
131*5796c8dcSSimon Schubert   /* Obviously FreeBSD is BSD-based.  */
132*5796c8dcSSimon Schubert   i386bsd_init_abi (info, gdbarch);
133*5796c8dcSSimon Schubert 
134*5796c8dcSSimon Schubert   /* FreeBSD has a different `struct reg', and reserves some space for
135*5796c8dcSSimon Schubert      its FPU emulator in `struct fpreg'.  */
136*5796c8dcSSimon Schubert   tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
137*5796c8dcSSimon Schubert   tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
138*5796c8dcSSimon Schubert   tdep->sizeof_gregset = 18 * 4;
139*5796c8dcSSimon Schubert   tdep->sizeof_fpregset = 176;
140*5796c8dcSSimon Schubert 
141*5796c8dcSSimon Schubert   /* FreeBSD uses -freg-struct-return by default.  */
142*5796c8dcSSimon Schubert   tdep->struct_return = reg_struct_return;
143*5796c8dcSSimon Schubert 
144*5796c8dcSSimon Schubert   /* FreeBSD uses a different memory layout.  */
145*5796c8dcSSimon Schubert   tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
146*5796c8dcSSimon Schubert   tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;
147*5796c8dcSSimon Schubert 
148*5796c8dcSSimon Schubert   /* FreeBSD has a more complete `struct sigcontext'.  */
149*5796c8dcSSimon Schubert   tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
150*5796c8dcSSimon Schubert   tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
151*5796c8dcSSimon Schubert 
152*5796c8dcSSimon Schubert   /* FreeBSD provides a user-level threads implementation.  */
153*5796c8dcSSimon Schubert   bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread);
154*5796c8dcSSimon Schubert   bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread);
155*5796c8dcSSimon Schubert }
156*5796c8dcSSimon Schubert 
157*5796c8dcSSimon Schubert static void
158*5796c8dcSSimon Schubert i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
159*5796c8dcSSimon Schubert {
160*5796c8dcSSimon Schubert   /* It's almost identical to FreeBSD a.out.  */
161*5796c8dcSSimon Schubert   i386fbsdaout_init_abi (info, gdbarch);
162*5796c8dcSSimon Schubert 
163*5796c8dcSSimon Schubert   /* Except that it uses ELF.  */
164*5796c8dcSSimon Schubert   i386_elf_init_abi (info, gdbarch);
165*5796c8dcSSimon Schubert 
166*5796c8dcSSimon Schubert   /* FreeBSD ELF uses SVR4-style shared libraries.  */
167*5796c8dcSSimon Schubert   set_solib_svr4_fetch_link_map_offsets
168*5796c8dcSSimon Schubert     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
169*5796c8dcSSimon Schubert }
170*5796c8dcSSimon Schubert 
171*5796c8dcSSimon Schubert /* FreeBSD 4.0-RELEASE or later.  */
172*5796c8dcSSimon Schubert 
173*5796c8dcSSimon Schubert /* From <machine/reg.h>.  */
174*5796c8dcSSimon Schubert static int i386fbsd4_r_reg_offset[] =
175*5796c8dcSSimon Schubert {
176*5796c8dcSSimon Schubert   10 * 4, 9 * 4, 8 * 4, 7 * 4,	/* %eax, %ecx, %edx, %ebx */
177*5796c8dcSSimon Schubert   16 * 4, 5 * 4,		/* %esp, %ebp */
178*5796c8dcSSimon Schubert   4 * 4, 3 * 4,			/* %esi, %edi */
179*5796c8dcSSimon Schubert   13 * 4, 15 * 4,		/* %eip, %eflags */
180*5796c8dcSSimon Schubert   14 * 4, 17 * 4,		/* %cs, %ss */
181*5796c8dcSSimon Schubert   2 * 4, 1 * 4, 0 * 4, 18 * 4	/* %ds, %es, %fs, %gs */
182*5796c8dcSSimon Schubert };
183*5796c8dcSSimon Schubert 
184*5796c8dcSSimon Schubert /* From <machine/signal.h>.  */
185*5796c8dcSSimon Schubert int i386fbsd4_sc_reg_offset[] =
186*5796c8dcSSimon Schubert {
187*5796c8dcSSimon Schubert   20 + 11 * 4,			/* %eax */
188*5796c8dcSSimon Schubert   20 + 10 * 4,			/* %ecx */
189*5796c8dcSSimon Schubert   20 + 9 * 4,			/* %edx */
190*5796c8dcSSimon Schubert   20 + 8 * 4,			/* %ebx */
191*5796c8dcSSimon Schubert   20 + 17 * 4,			/* %esp */
192*5796c8dcSSimon Schubert   20 + 6 * 4,			/* %ebp */
193*5796c8dcSSimon Schubert   20 + 5 * 4,			/* %esi */
194*5796c8dcSSimon Schubert   20 + 4 * 4,			/* %edi */
195*5796c8dcSSimon Schubert   20 + 14 * 4,			/* %eip */
196*5796c8dcSSimon Schubert   20 + 16 * 4,			/* %eflags */
197*5796c8dcSSimon Schubert   20 + 15 * 4,			/* %cs */
198*5796c8dcSSimon Schubert   20 + 18 * 4,			/* %ss */
199*5796c8dcSSimon Schubert   20 + 3 * 4,			/* %ds */
200*5796c8dcSSimon Schubert   20 + 2 * 4,			/* %es */
201*5796c8dcSSimon Schubert   20 + 1 * 4,			/* %fs */
202*5796c8dcSSimon Schubert   20 + 0 * 4			/* %gs */
203*5796c8dcSSimon Schubert };
204*5796c8dcSSimon Schubert 
205*5796c8dcSSimon Schubert static void
206*5796c8dcSSimon Schubert i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
207*5796c8dcSSimon Schubert {
208*5796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
209*5796c8dcSSimon Schubert 
210*5796c8dcSSimon Schubert   /* Inherit stuff from older releases.  We assume that FreeBSD
211*5796c8dcSSimon Schubert      4.0-RELEASE always uses ELF.  */
212*5796c8dcSSimon Schubert   i386fbsd_init_abi (info, gdbarch);
213*5796c8dcSSimon Schubert 
214*5796c8dcSSimon Schubert   /* FreeBSD 4.0 introduced a new `struct reg'.  */
215*5796c8dcSSimon Schubert   tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
216*5796c8dcSSimon Schubert   tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
217*5796c8dcSSimon Schubert   tdep->sizeof_gregset = 19 * 4;
218*5796c8dcSSimon Schubert 
219*5796c8dcSSimon Schubert   /* FreeBSD 4.0 introduced a new `struct sigcontext'.  */
220*5796c8dcSSimon Schubert   tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
221*5796c8dcSSimon Schubert   tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
222*5796c8dcSSimon Schubert }
223*5796c8dcSSimon Schubert 
224*5796c8dcSSimon Schubert 
225*5796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes.  */
226*5796c8dcSSimon Schubert void _initialize_i386fbsd_tdep (void);
227*5796c8dcSSimon Schubert 
228*5796c8dcSSimon Schubert void
229*5796c8dcSSimon Schubert _initialize_i386fbsd_tdep (void)
230*5796c8dcSSimon Schubert {
231*5796c8dcSSimon Schubert   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT,
232*5796c8dcSSimon Schubert 			  i386fbsdaout_init_abi);
233*5796c8dcSSimon Schubert   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF,
234*5796c8dcSSimon Schubert 			  i386fbsd4_init_abi);
235*5796c8dcSSimon Schubert }
236