1130803Smarcel/* i386-nto-tdep.c - i386 specific functionality for QNX Neutrino. 2130803Smarcel 3130803Smarcel Copyright 2003 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel Contributed by QNX Software Systems Ltd. 6130803Smarcel 7130803Smarcel This file is part of GDB. 8130803Smarcel 9130803Smarcel This program is free software; you can redistribute it and/or modify 10130803Smarcel it under the terms of the GNU General Public License as published by 11130803Smarcel the Free Software Foundation; either version 2 of the License, or 12130803Smarcel (at your option) any later version. 13130803Smarcel 14130803Smarcel This program is distributed in the hope that it will be useful, 15130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 16130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17130803Smarcel GNU General Public License for more details. 18130803Smarcel 19130803Smarcel You should have received a copy of the GNU General Public License 20130803Smarcel along with this program; if not, write to the Free Software 21130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 22130803Smarcel Boston, MA 02111-1307, USA. */ 23130803Smarcel 24130803Smarcel#include "gdb_string.h" 25130803Smarcel#include "gdb_assert.h" 26130803Smarcel#include "defs.h" 27130803Smarcel#include "frame.h" 28130803Smarcel#include "target.h" 29130803Smarcel#include "regcache.h" 30130803Smarcel#include "solib-svr4.h" 31130803Smarcel#include "i386-tdep.h" 32130803Smarcel#include "nto-tdep.h" 33130803Smarcel#include "osabi.h" 34130803Smarcel#include "i387-tdep.h" 35130803Smarcel 36130803Smarcel#ifndef X86_CPU_FXSR 37130803Smarcel#define X86_CPU_FXSR (1L << 12) 38130803Smarcel#endif 39130803Smarcel 40130803Smarcel/* Why 13? Look in our /usr/include/x86/context.h header at the 41130803Smarcel x86_cpu_registers structure and you'll see an 'exx' junk register 42130803Smarcel that is just filler. Don't ask me, ask the kernel guys. */ 43130803Smarcel#define NUM_GPREGS 13 44130803Smarcel 45130803Smarcel/* Map a GDB register number to an offset in the reg structure. */ 46130803Smarcelstatic int regmap[] = { 47130803Smarcel (7 * 4), /* eax */ 48130803Smarcel (6 * 4), /* ecx */ 49130803Smarcel (5 * 4), /* edx */ 50130803Smarcel (4 * 4), /* ebx */ 51130803Smarcel (11 * 4), /* esp */ 52130803Smarcel (2 * 4), /* epb */ 53130803Smarcel (1 * 4), /* esi */ 54130803Smarcel (0 * 4), /* edi */ 55130803Smarcel (8 * 4), /* eip */ 56130803Smarcel (10 * 4), /* eflags */ 57130803Smarcel (9 * 4), /* cs */ 58130803Smarcel (12 * 4), /* ss */ 59130803Smarcel (-1 * 4) /* filler */ 60130803Smarcel}; 61130803Smarcel 62130803Smarcel/* Given a gdb regno, return the offset into Neutrino's register structure 63130803Smarcel or -1 if register is unknown. */ 64130803Smarcelstatic int 65130803Smarcelnto_reg_offset (int regno) 66130803Smarcel{ 67130803Smarcel return (regno >= 0 && regno < NUM_GPREGS) ? regmap[regno] : -1; 68130803Smarcel} 69130803Smarcel 70130803Smarcelstatic void 71130803Smarceli386nto_supply_gregset (char *gpregs) 72130803Smarcel{ 73130803Smarcel unsigned regno; 74130803Smarcel int empty = 0; 75130803Smarcel 76130803Smarcel for (regno = 0; regno < FP0_REGNUM; regno++) 77130803Smarcel { 78130803Smarcel int offset = nto_reg_offset (regno); 79130803Smarcel if (offset == -1) 80130803Smarcel supply_register (regno, (char *) &empty); 81130803Smarcel else 82130803Smarcel supply_register (regno, gpregs + offset); 83130803Smarcel } 84130803Smarcel} 85130803Smarcel 86130803Smarcelstatic void 87130803Smarceli386nto_supply_fpregset (char *fpregs) 88130803Smarcel{ 89130803Smarcel if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 90130803Smarcel i387_supply_fxsave (current_regcache, -1, fpregs); 91130803Smarcel else 92130803Smarcel i387_supply_fsave (current_regcache, -1, fpregs); 93130803Smarcel} 94130803Smarcel 95130803Smarcelstatic void 96130803Smarceli386nto_supply_regset (int regset, char *data) 97130803Smarcel{ 98130803Smarcel switch (regset) 99130803Smarcel { 100130803Smarcel case NTO_REG_GENERAL: /* QNX has different ordering of GP regs than GDB. */ 101130803Smarcel i386nto_supply_gregset (data); 102130803Smarcel break; 103130803Smarcel case NTO_REG_FLOAT: 104130803Smarcel i386nto_supply_fpregset (data); 105130803Smarcel break; 106130803Smarcel } 107130803Smarcel} 108130803Smarcel 109130803Smarcelstatic int 110130803Smarceli386nto_regset_id (int regno) 111130803Smarcel{ 112130803Smarcel if (regno == -1) 113130803Smarcel return NTO_REG_END; 114130803Smarcel else if (regno < FP0_REGNUM) 115130803Smarcel return NTO_REG_GENERAL; 116130803Smarcel else if (regno < FPC_REGNUM) 117130803Smarcel return NTO_REG_FLOAT; 118130803Smarcel 119130803Smarcel return -1; /* Error. */ 120130803Smarcel} 121130803Smarcel 122130803Smarcelstatic int 123130803Smarceli386nto_register_area (int regno, int regset, unsigned *off) 124130803Smarcel{ 125130803Smarcel int len; 126130803Smarcel 127130803Smarcel *off = 0; 128130803Smarcel if (regset == NTO_REG_GENERAL) 129130803Smarcel { 130130803Smarcel if (regno == -1) 131130803Smarcel return NUM_GPREGS * 4; 132130803Smarcel 133130803Smarcel *off = nto_reg_offset (regno); 134130803Smarcel if (*off == -1) 135130803Smarcel return 0; 136130803Smarcel return 4; 137130803Smarcel } 138130803Smarcel else if (regset == NTO_REG_FLOAT) 139130803Smarcel { 140130803Smarcel unsigned off_adjust, regsize, regset_size; 141130803Smarcel 142130803Smarcel if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 143130803Smarcel { 144130803Smarcel off_adjust = 32; 145130803Smarcel regsize = 16; 146130803Smarcel regset_size = 512; 147130803Smarcel } 148130803Smarcel else 149130803Smarcel { 150130803Smarcel off_adjust = 28; 151130803Smarcel regsize = 10; 152130803Smarcel regset_size = 128; 153130803Smarcel } 154130803Smarcel 155130803Smarcel if (regno == -1) 156130803Smarcel return regset_size; 157130803Smarcel 158130803Smarcel *off = (regno - FP0_REGNUM) * regsize + off_adjust; 159130803Smarcel return 10; 160130803Smarcel /* Why 10 instead of regsize? GDB only stores 10 bytes per FP 161130803Smarcel register so if we're sending a register back to the target, 162130803Smarcel we only want pdebug to write 10 bytes so as not to clobber 163130803Smarcel the reserved 6 bytes in the fxsave structure. */ 164130803Smarcel } 165130803Smarcel return -1; 166130803Smarcel} 167130803Smarcel 168130803Smarcelstatic int 169130803Smarceli386nto_regset_fill (int regset, char *data) 170130803Smarcel{ 171130803Smarcel if (regset == NTO_REG_GENERAL) 172130803Smarcel { 173130803Smarcel int regno; 174130803Smarcel 175130803Smarcel for (regno = 0; regno < NUM_GPREGS; regno++) 176130803Smarcel { 177130803Smarcel int offset = nto_reg_offset (regno); 178130803Smarcel if (offset != -1) 179130803Smarcel regcache_collect (regno, data + offset); 180130803Smarcel } 181130803Smarcel } 182130803Smarcel else if (regset == NTO_REG_FLOAT) 183130803Smarcel { 184130803Smarcel if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 185130803Smarcel i387_fill_fxsave (data, -1); 186130803Smarcel else 187130803Smarcel i387_fill_fsave (data, -1); 188130803Smarcel } 189130803Smarcel else 190130803Smarcel return -1; 191130803Smarcel 192130803Smarcel return 0; 193130803Smarcel} 194130803Smarcel 195130803Smarcelstatic struct link_map_offsets * 196130803Smarceli386nto_svr4_fetch_link_map_offsets (void) 197130803Smarcel{ 198130803Smarcel static struct link_map_offsets lmo; 199130803Smarcel static struct link_map_offsets *lmp = NULL; 200130803Smarcel 201130803Smarcel if (lmp == NULL) 202130803Smarcel { 203130803Smarcel lmp = &lmo; 204130803Smarcel 205130803Smarcel lmo.r_debug_size = 8; /* The actual size is 20 bytes, but 206130803Smarcel only 8 bytes are used. */ 207130803Smarcel lmo.r_map_offset = 4; 208130803Smarcel lmo.r_map_size = 4; 209130803Smarcel 210130803Smarcel lmo.link_map_size = 20; /* The actual size is 552 bytes, but 211130803Smarcel only 20 bytes are used. */ 212130803Smarcel lmo.l_addr_offset = 0; 213130803Smarcel lmo.l_addr_size = 4; 214130803Smarcel 215130803Smarcel lmo.l_name_offset = 4; 216130803Smarcel lmo.l_name_size = 4; 217130803Smarcel 218130803Smarcel lmo.l_next_offset = 12; 219130803Smarcel lmo.l_next_size = 4; 220130803Smarcel 221130803Smarcel lmo.l_prev_offset = 16; 222130803Smarcel lmo.l_prev_size = 4; 223130803Smarcel } 224130803Smarcel 225130803Smarcel return lmp; 226130803Smarcel} 227130803Smarcel 228130803Smarcelstatic int 229130803Smarceli386nto_pc_in_sigtramp (CORE_ADDR pc, char *name) 230130803Smarcel{ 231130803Smarcel return name && strcmp ("__signalstub", name) == 0; 232130803Smarcel} 233130803Smarcel 234130803Smarcel#define I386_NTO_SIGCONTEXT_OFFSET 136 235130803Smarcel 236130803Smarcel/* Assuming NEXT_FRAME is a frame following a QNX Neutrino sigtramp 237130803Smarcel routine, return the address of the associated sigcontext structure. */ 238130803Smarcel 239130803Smarcelstatic CORE_ADDR 240130803Smarceli386nto_sigcontext_addr (struct frame_info *next_frame) 241130803Smarcel{ 242130803Smarcel char buf[4]; 243130803Smarcel CORE_ADDR sp; 244130803Smarcel 245130803Smarcel frame_unwind_register (next_frame, SP_REGNUM, buf); 246130803Smarcel sp = extract_unsigned_integer (buf, 4); 247130803Smarcel 248130803Smarcel return sp + I386_NTO_SIGCONTEXT_OFFSET; 249130803Smarcel} 250130803Smarcel 251130803Smarcelstatic void 252130803Smarcelinit_i386nto_ops (void) 253130803Smarcel{ 254130803Smarcel current_nto_target.nto_regset_id = i386nto_regset_id; 255130803Smarcel current_nto_target.nto_supply_gregset = i386nto_supply_gregset; 256130803Smarcel current_nto_target.nto_supply_fpregset = i386nto_supply_fpregset; 257130803Smarcel current_nto_target.nto_supply_altregset = nto_dummy_supply_regset; 258130803Smarcel current_nto_target.nto_supply_regset = i386nto_supply_regset; 259130803Smarcel current_nto_target.nto_register_area = i386nto_register_area; 260130803Smarcel current_nto_target.nto_regset_fill = i386nto_regset_fill; 261130803Smarcel current_nto_target.nto_fetch_link_map_offsets = 262130803Smarcel i386nto_svr4_fetch_link_map_offsets; 263130803Smarcel} 264130803Smarcel 265130803Smarcelstatic void 266130803Smarceli386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 267130803Smarcel{ 268130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 269130803Smarcel 270130803Smarcel /* NTO uses ELF. */ 271130803Smarcel i386_elf_init_abi (info, gdbarch); 272130803Smarcel 273130803Smarcel /* Neutrino rewinds to look more normal. Need to override the i386 274130803Smarcel default which is [unfortunately] to decrement the PC. */ 275130803Smarcel set_gdbarch_decr_pc_after_break (gdbarch, 0); 276130803Smarcel 277130803Smarcel /* NTO has shared libraries. */ 278130803Smarcel set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); 279130803Smarcel set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 280130803Smarcel 281130803Smarcel set_gdbarch_pc_in_sigtramp (gdbarch, i386nto_pc_in_sigtramp); 282130803Smarcel tdep->sigcontext_addr = i386nto_sigcontext_addr; 283130803Smarcel tdep->sc_pc_offset = 56; 284130803Smarcel tdep->sc_sp_offset = 68; 285130803Smarcel 286130803Smarcel /* Setjmp()'s return PC saved in EDX (5). */ 287130803Smarcel tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */ 288130803Smarcel 289130803Smarcel set_solib_svr4_fetch_link_map_offsets (gdbarch, 290130803Smarcel i386nto_svr4_fetch_link_map_offsets); 291130803Smarcel 292130803Smarcel /* Our loader handles solib relocations slightly differently than svr4. */ 293130803Smarcel TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses; 294130803Smarcel 295130803Smarcel /* Supply a nice function to find our solibs. */ 296130803Smarcel TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib; 297130803Smarcel 298130803Smarcel init_i386nto_ops (); 299130803Smarcel} 300130803Smarcel 301130803Smarcelvoid 302130803Smarcel_initialize_i386nto_tdep (void) 303130803Smarcel{ 304130803Smarcel gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO, 305130803Smarcel i386nto_init_abi); 306130803Smarcel} 307