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 20569e0f06dSSimon Schubert 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