GDB (API)
|
00001 /* Target-dependent code for QNX Neutrino x86. 00002 00003 Copyright (C) 2003-2013 Free Software Foundation, Inc. 00004 00005 Contributed by QNX Software Systems Ltd. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "frame.h" 00024 #include "osabi.h" 00025 #include "regcache.h" 00026 #include "target.h" 00027 00028 #include "gdb_assert.h" 00029 #include "gdb_string.h" 00030 00031 #include "i386-tdep.h" 00032 #include "i387-tdep.h" 00033 #include "nto-tdep.h" 00034 #include "solib.h" 00035 #include "solib-svr4.h" 00036 00037 #ifndef X86_CPU_FXSR 00038 #define X86_CPU_FXSR (1L << 12) 00039 #endif 00040 00041 /* Why 13? Look in our /usr/include/x86/context.h header at the 00042 x86_cpu_registers structure and you'll see an 'exx' junk register 00043 that is just filler. Don't ask me, ask the kernel guys. */ 00044 #define NUM_GPREGS 13 00045 00046 /* Mapping between the general-purpose registers in `struct xxx' 00047 format and GDB's register cache layout. */ 00048 00049 /* From <x86/context.h>. */ 00050 static int i386nto_gregset_reg_offset[] = 00051 { 00052 7 * 4, /* %eax */ 00053 6 * 4, /* %ecx */ 00054 5 * 4, /* %edx */ 00055 4 * 4, /* %ebx */ 00056 11 * 4, /* %esp */ 00057 2 * 4, /* %epb */ 00058 1 * 4, /* %esi */ 00059 0 * 4, /* %edi */ 00060 8 * 4, /* %eip */ 00061 10 * 4, /* %eflags */ 00062 9 * 4, /* %cs */ 00063 12 * 4, /* %ss */ 00064 -1 /* filler */ 00065 }; 00066 00067 /* Given a GDB register number REGNUM, return the offset into 00068 Neutrino's register structure or -1 if the register is unknown. */ 00069 00070 static int 00071 nto_reg_offset (int regnum) 00072 { 00073 if (regnum >= 0 && regnum < ARRAY_SIZE (i386nto_gregset_reg_offset)) 00074 return i386nto_gregset_reg_offset[regnum]; 00075 00076 return -1; 00077 } 00078 00079 static void 00080 i386nto_supply_gregset (struct regcache *regcache, char *gpregs) 00081 { 00082 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00083 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00084 00085 if(tdep->gregset == NULL) 00086 tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset, 00087 i386_collect_gregset); 00088 00089 gdb_assert (tdep->gregset_reg_offset == i386nto_gregset_reg_offset); 00090 tdep->gregset->supply_regset (tdep->gregset, regcache, -1, 00091 gpregs, NUM_GPREGS * 4); 00092 } 00093 00094 static void 00095 i386nto_supply_fpregset (struct regcache *regcache, char *fpregs) 00096 { 00097 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 00098 i387_supply_fxsave (regcache, -1, fpregs); 00099 else 00100 i387_supply_fsave (regcache, -1, fpregs); 00101 } 00102 00103 static void 00104 i386nto_supply_regset (struct regcache *regcache, int regset, char *data) 00105 { 00106 switch (regset) 00107 { 00108 case NTO_REG_GENERAL: 00109 i386nto_supply_gregset (regcache, data); 00110 break; 00111 case NTO_REG_FLOAT: 00112 i386nto_supply_fpregset (regcache, data); 00113 break; 00114 } 00115 } 00116 00117 static int 00118 i386nto_regset_id (int regno) 00119 { 00120 if (regno == -1) 00121 return NTO_REG_END; 00122 else if (regno < I386_NUM_GREGS) 00123 return NTO_REG_GENERAL; 00124 else if (regno < I386_NUM_GREGS + I387_NUM_REGS) 00125 return NTO_REG_FLOAT; 00126 else if (regno < I386_SSE_NUM_REGS) 00127 return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */ 00128 00129 return -1; /* Error. */ 00130 } 00131 00132 static int 00133 i386nto_register_area (struct gdbarch *gdbarch, 00134 int regno, int regset, unsigned *off) 00135 { 00136 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00137 00138 *off = 0; 00139 if (regset == NTO_REG_GENERAL) 00140 { 00141 if (regno == -1) 00142 return NUM_GPREGS * 4; 00143 00144 *off = nto_reg_offset (regno); 00145 if (*off == -1) 00146 return 0; 00147 return 4; 00148 } 00149 else if (regset == NTO_REG_FLOAT) 00150 { 00151 unsigned off_adjust, regsize, regset_size, regno_base; 00152 /* The following are flags indicating number in our fxsave_area. */ 00153 int first_four = (regno >= I387_FCTRL_REGNUM (tdep) 00154 && regno <= I387_FISEG_REGNUM (tdep)); 00155 int second_four = (regno > I387_FISEG_REGNUM (tdep) 00156 && regno <= I387_FOP_REGNUM (tdep)); 00157 int st_reg = (regno >= I387_ST0_REGNUM (tdep) 00158 && regno < I387_ST0_REGNUM (tdep) + 8); 00159 int xmm_reg = (regno >= I387_XMM0_REGNUM (tdep) 00160 && regno < I387_MXCSR_REGNUM (tdep)); 00161 00162 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 00163 { 00164 off_adjust = 32; 00165 regsize = 16; 00166 regset_size = 512; 00167 /* fxsave_area structure. */ 00168 if (first_four) 00169 { 00170 /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand 00171 registers. */ 00172 regsize = 2; /* Two bytes each. */ 00173 off_adjust = 0; 00174 regno_base = I387_FCTRL_REGNUM (tdep); 00175 } 00176 else if (second_four) 00177 { 00178 /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */ 00179 regsize = 4; 00180 off_adjust = 8; 00181 regno_base = I387_FISEG_REGNUM (tdep) + 1; 00182 } 00183 else if (st_reg) 00184 { 00185 /* ST registers. */ 00186 regsize = 16; 00187 off_adjust = 32; 00188 regno_base = I387_ST0_REGNUM (tdep); 00189 } 00190 else if (xmm_reg) 00191 { 00192 /* XMM registers. */ 00193 regsize = 16; 00194 off_adjust = 160; 00195 regno_base = I387_XMM0_REGNUM (tdep); 00196 } 00197 else if (regno == I387_MXCSR_REGNUM (tdep)) 00198 { 00199 regsize = 4; 00200 off_adjust = 24; 00201 regno_base = I387_MXCSR_REGNUM (tdep); 00202 } 00203 else 00204 { 00205 /* Whole regset. */ 00206 gdb_assert (regno == -1); 00207 off_adjust = 0; 00208 regno_base = 0; 00209 regsize = regset_size; 00210 } 00211 } 00212 else 00213 { 00214 regset_size = 108; 00215 /* fsave_area structure. */ 00216 if (first_four || second_four) 00217 { 00218 /* fpu_control_word, ... , fpu_ds registers. */ 00219 regsize = 4; 00220 off_adjust = 0; 00221 regno_base = I387_FCTRL_REGNUM (tdep); 00222 } 00223 else if (st_reg) 00224 { 00225 /* One of ST registers. */ 00226 regsize = 10; 00227 off_adjust = 7 * 4; 00228 regno_base = I387_ST0_REGNUM (tdep); 00229 } 00230 else 00231 { 00232 /* Whole regset. */ 00233 gdb_assert (regno == -1); 00234 off_adjust = 0; 00235 regno_base = 0; 00236 regsize = regset_size; 00237 } 00238 } 00239 00240 if (regno != -1) 00241 *off = off_adjust + (regno - regno_base) * regsize; 00242 else 00243 *off = 0; 00244 return regsize; 00245 } 00246 return -1; 00247 } 00248 00249 static int 00250 i386nto_regset_fill (const struct regcache *regcache, int regset, char *data) 00251 { 00252 if (regset == NTO_REG_GENERAL) 00253 { 00254 int regno; 00255 00256 for (regno = 0; regno < NUM_GPREGS; regno++) 00257 { 00258 int offset = nto_reg_offset (regno); 00259 if (offset != -1) 00260 regcache_raw_collect (regcache, regno, data + offset); 00261 } 00262 } 00263 else if (regset == NTO_REG_FLOAT) 00264 { 00265 if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR) 00266 i387_collect_fxsave (regcache, -1, data); 00267 else 00268 i387_collect_fsave (regcache, -1, data); 00269 } 00270 else 00271 return -1; 00272 00273 return 0; 00274 } 00275 00276 /* Return whether THIS_FRAME corresponds to a QNX Neutrino sigtramp 00277 routine. */ 00278 00279 static int 00280 i386nto_sigtramp_p (struct frame_info *this_frame) 00281 { 00282 CORE_ADDR pc = get_frame_pc (this_frame); 00283 const char *name; 00284 00285 find_pc_partial_function (pc, &name, NULL, NULL); 00286 return name && strcmp ("__signalstub", name) == 0; 00287 } 00288 00289 /* Assuming THIS_FRAME is a QNX Neutrino sigtramp routine, return the 00290 address of the associated sigcontext structure. */ 00291 00292 static CORE_ADDR 00293 i386nto_sigcontext_addr (struct frame_info *this_frame) 00294 { 00295 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00296 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00297 gdb_byte buf[4]; 00298 CORE_ADDR ptrctx; 00299 00300 /* We store __ucontext_t addr in EDI register. */ 00301 get_frame_register (this_frame, I386_EDI_REGNUM, buf); 00302 ptrctx = extract_unsigned_integer (buf, 4, byte_order); 00303 ptrctx += 24 /* Context pointer is at this offset. */; 00304 00305 return ptrctx; 00306 } 00307 00308 static void 00309 init_i386nto_ops (void) 00310 { 00311 nto_regset_id = i386nto_regset_id; 00312 nto_supply_gregset = i386nto_supply_gregset; 00313 nto_supply_fpregset = i386nto_supply_fpregset; 00314 nto_supply_altregset = nto_dummy_supply_regset; 00315 nto_supply_regset = i386nto_supply_regset; 00316 nto_register_area = i386nto_register_area; 00317 nto_regset_fill = i386nto_regset_fill; 00318 nto_fetch_link_map_offsets = 00319 svr4_ilp32_fetch_link_map_offsets; 00320 } 00321 00322 static void 00323 i386nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00324 { 00325 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00326 static struct target_so_ops nto_svr4_so_ops; 00327 00328 /* Deal with our strange signals. */ 00329 nto_initialize_signals (); 00330 00331 /* NTO uses ELF. */ 00332 i386_elf_init_abi (info, gdbarch); 00333 00334 /* Neutrino rewinds to look more normal. Need to override the i386 00335 default which is [unfortunately] to decrement the PC. */ 00336 set_gdbarch_decr_pc_after_break (gdbarch, 0); 00337 00338 tdep->gregset_reg_offset = i386nto_gregset_reg_offset; 00339 tdep->gregset_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset); 00340 tdep->sizeof_gregset = NUM_GPREGS * 4; 00341 00342 tdep->sigtramp_p = i386nto_sigtramp_p; 00343 tdep->sigcontext_addr = i386nto_sigcontext_addr; 00344 tdep->sc_reg_offset = i386nto_gregset_reg_offset; 00345 tdep->sc_num_regs = ARRAY_SIZE (i386nto_gregset_reg_offset); 00346 00347 /* Setjmp()'s return PC saved in EDX (5). */ 00348 tdep->jb_pc_offset = 20; /* 5x32 bit ints in. */ 00349 00350 set_solib_svr4_fetch_link_map_offsets 00351 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 00352 00353 /* Initialize this lazily, to avoid an initialization order 00354 dependency on solib-svr4.c's _initialize routine. */ 00355 if (nto_svr4_so_ops.in_dynsym_resolve_code == NULL) 00356 { 00357 nto_svr4_so_ops = svr4_so_ops; 00358 00359 /* Our loader handles solib relocations differently than svr4. */ 00360 nto_svr4_so_ops.relocate_section_addresses 00361 = nto_relocate_section_addresses; 00362 00363 /* Supply a nice function to find our solibs. */ 00364 nto_svr4_so_ops.find_and_open_solib 00365 = nto_find_and_open_solib; 00366 00367 /* Our linker code is in libc. */ 00368 nto_svr4_so_ops.in_dynsym_resolve_code 00369 = nto_in_dynsym_resolve_code; 00370 } 00371 set_solib_ops (gdbarch, &nto_svr4_so_ops); 00372 } 00373 00374 /* Provide a prototype to silence -Wmissing-prototypes. */ 00375 extern initialize_file_ftype _initialize_i386nto_tdep; 00376 00377 void 00378 _initialize_i386nto_tdep (void) 00379 { 00380 init_i386nto_ops (); 00381 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO, 00382 i386nto_init_abi); 00383 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, 00384 nto_elf_osabi_sniffer); 00385 }