1 /* Target-dependent code for QNX Neutrino x86. 2 3 Copyright 2003, 2004 Free Software Foundation, Inc. 4 5 Contributed by QNX Software Systems Ltd. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. */ 23 24 #include "gdb_string.h" 25 #include "gdb_assert.h" 26 #include "defs.h" 27 #include "frame.h" 28 #include "target.h" 29 #include "regcache.h" 30 #include "solib-svr4.h" 31 #include "i386-tdep.h" 32 #include "nto-tdep.h" 33 #include "osabi.h" 34 #include "i387-tdep.h" 35 36 #ifndef X86_CPU_FXSR 37 #define X86_CPU_FXSR (1L << 12) 38 #endif 39 40 /* Why 13? Look in our /usr/include/x86/context.h header at the 41 x86_cpu_registers structure and you'll see an 'exx' junk register 42 that is just filler. Don't ask me, ask the kernel guys. */ 43 #define NUM_GPREGS 13 44 45 /* Map a GDB register number to an offset in the reg structure. */ 46 static int regmap[] = { 47 (7 * 4), /* eax */ 48 (6 * 4), /* ecx */ 49 (5 * 4), /* edx */ 50 (4 * 4), /* ebx */ 51 (11 * 4), /* esp */ 52 (2 * 4), /* epb */ 53 (1 * 4), /* esi */ 54 (0 * 4), /* edi */ 55 (8 * 4), /* eip */ 56 (10 * 4), /* eflags */ 57 (9 * 4), /* cs */ 58 (12 * 4), /* ss */ 59 (-1 * 4) /* filler */ 60 }; 61 62 /* Given a gdb regno, return the offset into Neutrino's register structure 63 or -1 if register is unknown. */ 64 static int 65 nto_reg_offset (int regno) 66 { 67 return (regno >= 0 && regno < NUM_GPREGS) ? regmap[regno] : -1; 68 } 69 70 static void 71 i386nto_supply_gregset (char *gpregs) 72 { 73 unsigned regno; 74 int empty = 0; 75 76 for (regno = 0; regno < I386_NUM_GREGS; regno++) 77 { 78 int offset = nto_reg_offset (regno); 79 if (offset == -1) 80 regcache_raw_supply (current_regcache, regno, (char *) &empty); 81 else 82 regcache_raw_supply (current_regcache, regno, gpregs + offset); 83 } 84 } 85 86 static void 87 i386nto_supply_fpregset (char *fpregs) 88 { 89 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 90 i387_supply_fxsave (current_regcache, -1, fpregs); 91 else 92 i387_supply_fsave (current_regcache, -1, fpregs); 93 } 94 95 static void 96 i386nto_supply_regset (int regset, char *data) 97 { 98 switch (regset) 99 { 100 case NTO_REG_GENERAL: /* QNX has different ordering of GP regs than GDB. */ 101 i386nto_supply_gregset (data); 102 break; 103 case NTO_REG_FLOAT: 104 i386nto_supply_fpregset (data); 105 break; 106 } 107 } 108 109 static int 110 i386nto_regset_id (int regno) 111 { 112 if (regno == -1) 113 return NTO_REG_END; 114 else if (regno < I386_NUM_GREGS) 115 return NTO_REG_GENERAL; 116 else if (regno < I386_NUM_GREGS + I386_NUM_FREGS) 117 return NTO_REG_FLOAT; 118 119 return -1; /* Error. */ 120 } 121 122 static int 123 i386nto_register_area (int regno, int regset, unsigned *off) 124 { 125 int len; 126 127 *off = 0; 128 if (regset == NTO_REG_GENERAL) 129 { 130 if (regno == -1) 131 return NUM_GPREGS * 4; 132 133 *off = nto_reg_offset (regno); 134 if (*off == -1) 135 return 0; 136 return 4; 137 } 138 else if (regset == NTO_REG_FLOAT) 139 { 140 unsigned off_adjust, regsize, regset_size; 141 142 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 143 { 144 off_adjust = 32; 145 regsize = 16; 146 regset_size = 512; 147 } 148 else 149 { 150 off_adjust = 28; 151 regsize = 10; 152 regset_size = 128; 153 } 154 155 if (regno == -1) 156 return regset_size; 157 158 *off = (regno - FP0_REGNUM) * regsize + off_adjust; 159 return 10; 160 /* Why 10 instead of regsize? GDB only stores 10 bytes per FP 161 register so if we're sending a register back to the target, 162 we only want pdebug to write 10 bytes so as not to clobber 163 the reserved 6 bytes in the fxsave structure. */ 164 } 165 return -1; 166 } 167 168 static int 169 i386nto_regset_fill (int regset, char *data) 170 { 171 if (regset == NTO_REG_GENERAL) 172 { 173 int regno; 174 175 for (regno = 0; regno < NUM_GPREGS; regno++) 176 { 177 int offset = nto_reg_offset (regno); 178 if (offset != -1) 179 regcache_raw_collect (current_regcache, regno, data + offset); 180 } 181 } 182 else if (regset == NTO_REG_FLOAT) 183 { 184 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 185 i387_fill_fxsave (data, -1); 186 else 187 i387_fill_fsave (data, -1); 188 } 189 else 190 return -1; 191 192 return 0; 193 } 194 195 static struct link_map_offsets * 196 i386nto_svr4_fetch_link_map_offsets (void) 197 { 198 static struct link_map_offsets lmo; 199 static struct link_map_offsets *lmp = NULL; 200 201 if (lmp == NULL) 202 { 203 lmp = &lmo; 204 205 lmo.r_debug_size = 8; /* The actual size is 20 bytes, but 206 only 8 bytes are used. */ 207 lmo.r_map_offset = 4; 208 lmo.r_map_size = 4; 209 210 lmo.link_map_size = 20; /* The actual size is 552 bytes, but 211 only 20 bytes are used. */ 212 lmo.l_addr_offset = 0; 213 lmo.l_addr_size = 4; 214 215 lmo.l_name_offset = 4; 216 lmo.l_name_size = 4; 217 218 lmo.l_next_offset = 12; 219 lmo.l_next_size = 4; 220 221 lmo.l_prev_offset = 16; 222 lmo.l_prev_size = 4; 223 } 224 225 return lmp; 226 } 227 228 /* Return whether the frame preceding NEXT_FRAME corresponds to a QNX 229 Neutrino sigtramp routine. */ 230 231 static int 232 i386nto_sigtramp_p (struct frame_info *next_frame) 233 { 234 CORE_ADDR pc = frame_pc_unwind (next_frame); 235 char *name; 236 237 find_pc_partial_function (pc, &name, NULL, NULL); 238 return name && strcmp ("__signalstub", name) == 0; 239 } 240 241 #define I386_NTO_SIGCONTEXT_OFFSET 136 242 243 /* Assuming NEXT_FRAME is a frame following a QNX Neutrino sigtramp 244 routine, return the address of the associated sigcontext structure. */ 245 246 static CORE_ADDR 247 i386nto_sigcontext_addr (struct frame_info *next_frame) 248 { 249 char buf[4]; 250 CORE_ADDR sp; 251 252 frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); 253 sp = extract_unsigned_integer (buf, 4); 254 255 return sp + I386_NTO_SIGCONTEXT_OFFSET; 256 } 257 258 static void 259 init_i386nto_ops (void) 260 { 261 current_nto_target.nto_regset_id = i386nto_regset_id; 262 current_nto_target.nto_supply_gregset = i386nto_supply_gregset; 263 current_nto_target.nto_supply_fpregset = i386nto_supply_fpregset; 264 current_nto_target.nto_supply_altregset = nto_dummy_supply_regset; 265 current_nto_target.nto_supply_regset = i386nto_supply_regset; 266 current_nto_target.nto_register_area = i386nto_register_area; 267 current_nto_target.nto_regset_fill = i386nto_regset_fill; 268 current_nto_target.nto_fetch_link_map_offsets = 269 i386nto_svr4_fetch_link_map_offsets; 270 } 271 272 static void 273 i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 274 { 275 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 276 277 /* NTO uses ELF. */ 278 i386_elf_init_abi (info, gdbarch); 279 280 /* Neutrino rewinds to look more normal. Need to override the i386 281 default which is [unfortunately] to decrement the PC. */ 282 set_gdbarch_decr_pc_after_break (gdbarch, 0); 283 284 /* NTO has shared libraries. */ 285 set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); 286 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 287 288 tdep->sigtramp_p = i386nto_sigtramp_p; 289 tdep->sigcontext_addr = i386nto_sigcontext_addr; 290 tdep->sc_pc_offset = 56; 291 tdep->sc_sp_offset = 68; 292 293 /* Setjmp()'s return PC saved in EDX (5). */ 294 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */ 295 296 set_solib_svr4_fetch_link_map_offsets (gdbarch, 297 i386nto_svr4_fetch_link_map_offsets); 298 299 /* Our loader handles solib relocations slightly differently than svr4. */ 300 TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses; 301 302 /* Supply a nice function to find our solibs. */ 303 TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib; 304 305 init_i386nto_ops (); 306 } 307 308 void 309 _initialize_i386nto_tdep (void) 310 { 311 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO, 312 i386nto_init_abi); 313 } 314