* win32-i386-low.c: Use __x86_64__ macro instead of __x86_64 to
[external/binutils.git] / gdb / gdbserver / win32-i386-low.c
1 /* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
2
3    This file is part of GDB.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include "server.h"
19 #include "win32-low.h"
20 #include "i386-low.h"
21
22 #ifndef CONTEXT_EXTENDED_REGISTERS
23 #define CONTEXT_EXTENDED_REGISTERS 0
24 #endif
25
26 #define FCS_REGNUM 27
27 #define FOP_REGNUM 31
28
29 #define FLAG_TRACE_BIT 0x100
30
31 #ifdef __x86_64__
32 /* Defined in auto-generated file reg-amd64.c.  */
33 void init_registers_amd64 (void);
34 #else
35 /* Defined in auto-generated file reg-i386.c.  */
36 void init_registers_i386 (void);
37 #endif
38
39 static struct i386_debug_reg_state debug_reg_state;
40
41 static int debug_registers_changed = 0;
42 static int debug_registers_used = 0;
43
44 /* Update the inferior's debug register REGNUM from STATE.  */
45
46 void
47 i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
48 {
49   if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
50     fatal ("Invalid debug register %d", regnum);
51
52   /* debug_reg_state.dr_mirror is already set.
53      Just notify i386_set_thread_context, i386_thread_added
54      that the registers need to be updated.  */
55   debug_registers_changed = 1;
56   debug_registers_used = 1;
57 }
58
59 /* Update the inferior's DR7 debug control register from STATE.  */
60
61 void
62 i386_dr_low_set_control (const struct i386_debug_reg_state *state)
63 {
64   /* debug_reg_state.dr_control_mirror is already set.
65      Just notify i386_set_thread_context, i386_thread_added
66      that the registers need to be updated.  */
67   debug_registers_changed = 1;
68   debug_registers_used = 1;
69 }
70
71 /* Get the value of the DR6 debug status register from the inferior
72    and record it in STATE.  */
73
74 void
75 i386_dr_low_get_status (struct i386_debug_reg_state *state)
76 {
77   /* We don't need to do anything here, the last call to thread_rec for
78      current_event.dwThreadId id has already set it.  */
79 }
80
81 /* Watchpoint support.  */
82
83 static int
84 i386_insert_point (char type, CORE_ADDR addr, int len)
85 {
86   switch (type)
87     {
88     case '2':
89     case '3':
90     case '4':
91       return i386_low_insert_watchpoint (&debug_reg_state,
92                                          type, addr, len);
93     default:
94       /* Unsupported.  */
95       return 1;
96     }
97 }
98
99 static int
100 i386_remove_point (char type, CORE_ADDR addr, int len)
101 {
102   switch (type)
103     {
104     case '2':
105     case '3':
106     case '4':
107       return i386_low_remove_watchpoint (&debug_reg_state,
108                                          type, addr, len);
109     default:
110       /* Unsupported.  */
111       return 1;
112     }
113 }
114
115 static int
116 i386_stopped_by_watchpoint (void)
117 {
118   return i386_low_stopped_by_watchpoint (&debug_reg_state);
119 }
120
121 static CORE_ADDR
122 i386_stopped_data_address (void)
123 {
124   CORE_ADDR addr;
125   if (i386_low_stopped_data_address (&debug_reg_state, &addr))
126     return addr;
127   return 0;
128 }
129
130 static void
131 i386_initial_stuff (void)
132 {
133   i386_low_init_dregs (&debug_reg_state);
134   debug_registers_changed = 0;
135   debug_registers_used = 0;
136 }
137
138 static void
139 i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
140 {
141   /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if
142      the system doesn't support extended registers.  */
143   static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS;
144
145  again:
146   th->context.ContextFlags = (CONTEXT_FULL
147                               | CONTEXT_FLOATING_POINT
148                               | CONTEXT_DEBUG_REGISTERS
149                               | extended_registers);
150
151   if (!GetThreadContext (th->h, &th->context))
152     {
153       DWORD e = GetLastError ();
154
155       if (extended_registers && e == ERROR_INVALID_PARAMETER)
156         {
157           extended_registers = 0;
158           goto again;
159         }
160
161       error ("GetThreadContext failure %ld\n", (long) e);
162     }
163
164   debug_registers_changed = 0;
165
166   if (th->tid == current_event->dwThreadId)
167     {
168       /* Copy dr values from the current thread.  */
169       struct i386_debug_reg_state *dr = &debug_reg_state;
170       dr->dr_mirror[0] = th->context.Dr0;
171       dr->dr_mirror[1] = th->context.Dr1;
172       dr->dr_mirror[2] = th->context.Dr2;
173       dr->dr_mirror[3] = th->context.Dr3;
174       dr->dr_status_mirror = th->context.Dr6;
175       dr->dr_control_mirror = th->context.Dr7;
176     }
177 }
178
179 static void
180 i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
181 {
182   if (debug_registers_changed)
183     {
184       struct i386_debug_reg_state *dr = &debug_reg_state;
185       th->context.Dr0 = dr->dr_mirror[0];
186       th->context.Dr1 = dr->dr_mirror[1];
187       th->context.Dr2 = dr->dr_mirror[2];
188       th->context.Dr3 = dr->dr_mirror[3];
189       /* th->context.Dr6 = dr->dr_status_mirror;
190          FIXME: should we set dr6 also ?? */
191       th->context.Dr7 = dr->dr_control_mirror;
192     }
193
194   SetThreadContext (th->h, &th->context);
195 }
196
197 static void
198 i386_thread_added (win32_thread_info *th)
199 {
200   /* Set the debug registers for the new thread if they are used.  */
201   if (debug_registers_used)
202     {
203       struct i386_debug_reg_state *dr = &debug_reg_state;
204       th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
205       GetThreadContext (th->h, &th->context);
206
207       th->context.Dr0 = dr->dr_mirror[0];
208       th->context.Dr1 = dr->dr_mirror[1];
209       th->context.Dr2 = dr->dr_mirror[2];
210       th->context.Dr3 = dr->dr_mirror[3];
211       /* th->context.Dr6 = dr->dr_status_mirror;
212          FIXME: should we set dr6 also ?? */
213       th->context.Dr7 = dr->dr_control_mirror;
214
215       SetThreadContext (th->h, &th->context);
216       th->context.ContextFlags = 0;
217     }
218 }
219
220 static void
221 i386_single_step (win32_thread_info *th)
222 {
223   th->context.EFlags |= FLAG_TRACE_BIT;
224 }
225
226 #ifndef __x86_64__
227
228 /* An array of offset mappings into a Win32 Context structure.
229    This is a one-to-one mapping which is indexed by gdb's register
230    numbers.  It retrieves an offset into the context structure where
231    the 4 byte register is located.
232    An offset value of -1 indicates that Win32 does not provide this
233    register in it's CONTEXT structure.  In this case regptr will return
234    a pointer into a dummy register.  */
235 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
236 static const int mappings[] = {
237   context_offset (Eax),
238   context_offset (Ecx),
239   context_offset (Edx),
240   context_offset (Ebx),
241   context_offset (Esp),
242   context_offset (Ebp),
243   context_offset (Esi),
244   context_offset (Edi),
245   context_offset (Eip),
246   context_offset (EFlags),
247   context_offset (SegCs),
248   context_offset (SegSs),
249   context_offset (SegDs),
250   context_offset (SegEs),
251   context_offset (SegFs),
252   context_offset (SegGs),
253   context_offset (FloatSave.RegisterArea[0 * 10]),
254   context_offset (FloatSave.RegisterArea[1 * 10]),
255   context_offset (FloatSave.RegisterArea[2 * 10]),
256   context_offset (FloatSave.RegisterArea[3 * 10]),
257   context_offset (FloatSave.RegisterArea[4 * 10]),
258   context_offset (FloatSave.RegisterArea[5 * 10]),
259   context_offset (FloatSave.RegisterArea[6 * 10]),
260   context_offset (FloatSave.RegisterArea[7 * 10]),
261   context_offset (FloatSave.ControlWord),
262   context_offset (FloatSave.StatusWord),
263   context_offset (FloatSave.TagWord),
264   context_offset (FloatSave.ErrorSelector),
265   context_offset (FloatSave.ErrorOffset),
266   context_offset (FloatSave.DataSelector),
267   context_offset (FloatSave.DataOffset),
268   context_offset (FloatSave.ErrorSelector),
269   /* XMM0-7 */
270   context_offset (ExtendedRegisters[10 * 16]),
271   context_offset (ExtendedRegisters[11 * 16]),
272   context_offset (ExtendedRegisters[12 * 16]),
273   context_offset (ExtendedRegisters[13 * 16]),
274   context_offset (ExtendedRegisters[14 * 16]),
275   context_offset (ExtendedRegisters[15 * 16]),
276   context_offset (ExtendedRegisters[16 * 16]),
277   context_offset (ExtendedRegisters[17 * 16]),
278   /* MXCSR */
279   context_offset (ExtendedRegisters[24])
280 };
281 #undef context_offset
282
283 #else /* __x86_64__ */
284
285 #define context_offset(x) (offsetof (CONTEXT, x))
286 static const int mappings[] =
287 {
288   context_offset (Rax),
289   context_offset (Rbx),
290   context_offset (Rcx),
291   context_offset (Rdx),
292   context_offset (Rsi),
293   context_offset (Rdi),
294   context_offset (Rbp),
295   context_offset (Rsp),
296   context_offset (R8),
297   context_offset (R9),
298   context_offset (R10),
299   context_offset (R11),
300   context_offset (R12),
301   context_offset (R13),
302   context_offset (R14),
303   context_offset (R15),
304   context_offset (Rip),
305   context_offset (EFlags),
306   context_offset (SegCs),
307   context_offset (SegSs),
308   context_offset (SegDs),
309   context_offset (SegEs),
310   context_offset (SegFs),
311   context_offset (SegGs),
312   context_offset (FloatSave.FloatRegisters[0]),
313   context_offset (FloatSave.FloatRegisters[1]),
314   context_offset (FloatSave.FloatRegisters[2]),
315   context_offset (FloatSave.FloatRegisters[3]),
316   context_offset (FloatSave.FloatRegisters[4]),
317   context_offset (FloatSave.FloatRegisters[5]),
318   context_offset (FloatSave.FloatRegisters[6]),
319   context_offset (FloatSave.FloatRegisters[7]),
320   context_offset (FloatSave.ControlWord),
321   context_offset (FloatSave.StatusWord),
322   context_offset (FloatSave.TagWord),
323   context_offset (FloatSave.ErrorSelector),
324   context_offset (FloatSave.ErrorOffset),
325   context_offset (FloatSave.DataSelector),
326   context_offset (FloatSave.DataOffset),
327   context_offset (FloatSave.ErrorSelector)
328   /* XMM0-7 */ ,
329   context_offset (Xmm0),
330   context_offset (Xmm1),
331   context_offset (Xmm2),
332   context_offset (Xmm3),
333   context_offset (Xmm4),
334   context_offset (Xmm5),
335   context_offset (Xmm6),
336   context_offset (Xmm7),
337   context_offset (Xmm8),
338   context_offset (Xmm9),
339   context_offset (Xmm10),
340   context_offset (Xmm11),
341   context_offset (Xmm12),
342   context_offset (Xmm13),
343   context_offset (Xmm14),
344   context_offset (Xmm15),
345   /* MXCSR */
346   context_offset (FloatSave.MxCsr)
347 };
348 #undef context_offset
349
350 #endif /* __x86_64__ */
351
352 /* Fetch register from gdbserver regcache data.  */
353 static void
354 i386_fetch_inferior_register (struct regcache *regcache,
355                               win32_thread_info *th, int r)
356 {
357   char *context_offset = (char *) &th->context + mappings[r];
358
359   long l;
360   if (r == FCS_REGNUM)
361     {
362       l = *((long *) context_offset) & 0xffff;
363       supply_register (regcache, r, (char *) &l);
364     }
365   else if (r == FOP_REGNUM)
366     {
367       l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
368       supply_register (regcache, r, (char *) &l);
369     }
370   else
371     supply_register (regcache, r, context_offset);
372 }
373
374 /* Store a new register value into the thread context of TH.  */
375 static void
376 i386_store_inferior_register (struct regcache *regcache,
377                               win32_thread_info *th, int r)
378 {
379   char *context_offset = (char *) &th->context + mappings[r];
380   collect_register (regcache, r, context_offset);
381 }
382
383 static const unsigned char i386_win32_breakpoint = 0xcc;
384 #define i386_win32_breakpoint_len 1
385
386 static void
387 init_windows_x86 (void)
388 {
389 #ifdef __x86_64__
390   init_registers_amd64 ();
391 #else
392   init_registers_i386 ();
393 #endif
394 }
395
396 struct win32_target_ops the_low_target = {
397   init_windows_x86,
398   sizeof (mappings) / sizeof (mappings[0]),
399   i386_initial_stuff,
400   i386_get_thread_context,
401   i386_set_thread_context,
402   i386_thread_added,
403   i386_fetch_inferior_register,
404   i386_store_inferior_register,
405   i386_single_step,
406   &i386_win32_breakpoint,
407   i386_win32_breakpoint_len,
408   i386_insert_point,
409   i386_remove_point,
410   i386_stopped_by_watchpoint,
411   i386_stopped_data_address
412 };