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