gdbserver x86 on win32: call init_target_desc
[deliverable/binutils-gdb.git] / gdb / gdbserver / win32-i386-low.c
1 /* Copyright (C) 2007-2017 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 "x86-low.h"
21 #include "x86-xstate.h"
22 #ifdef __x86_64__
23 #include "arch/amd64.h"
24 #endif
25 #include "arch/i386.h"
26 #include "tdesc.h"
27
28 #ifndef CONTEXT_EXTENDED_REGISTERS
29 #define CONTEXT_EXTENDED_REGISTERS 0
30 #endif
31
32 #define FCS_REGNUM 27
33 #define FOP_REGNUM 31
34
35 #define FLAG_TRACE_BIT 0x100
36
37 static struct x86_debug_reg_state debug_reg_state;
38
39 static int
40 update_debug_registers_callback (struct inferior_list_entry *entry,
41 void *pid_p)
42 {
43 struct thread_info *thr = (struct thread_info *) entry;
44 win32_thread_info *th = (win32_thread_info *) thread_target_data (thr);
45 int pid = *(int *) pid_p;
46
47 /* Only update the threads of this process. */
48 if (pid_of (thr) == pid)
49 {
50 /* The actual update is done later just before resuming the lwp,
51 we just mark that the registers need updating. */
52 th->debug_registers_changed = 1;
53 }
54
55 return 0;
56 }
57
58 /* Update the inferior's debug register REGNUM from STATE. */
59
60 static void
61 x86_dr_low_set_addr (int regnum, CORE_ADDR addr)
62 {
63 /* Only update the threads of this process. */
64 int pid = pid_of (current_thread);
65
66 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
67
68 find_inferior (&all_threads, update_debug_registers_callback, &pid);
69 }
70
71 /* Update the inferior's DR7 debug control register from STATE. */
72
73 static void
74 x86_dr_low_set_control (unsigned long control)
75 {
76 /* Only update the threads of this process. */
77 int pid = pid_of (current_thread);
78
79 find_inferior (&all_threads, update_debug_registers_callback, &pid);
80 }
81
82 /* Return the current value of a DR register of the current thread's
83 context. */
84
85 static DWORD64
86 win32_get_current_dr (int dr)
87 {
88 win32_thread_info *th
89 = (win32_thread_info *) thread_target_data (current_thread);
90
91 win32_require_context (th);
92
93 #define RET_DR(DR) \
94 case DR: \
95 return th->context.Dr ## DR
96
97 switch (dr)
98 {
99 RET_DR (0);
100 RET_DR (1);
101 RET_DR (2);
102 RET_DR (3);
103 RET_DR (6);
104 RET_DR (7);
105 }
106
107 #undef RET_DR
108
109 gdb_assert_not_reached ("unhandled dr");
110 }
111
112 static CORE_ADDR
113 x86_dr_low_get_addr (int regnum)
114 {
115 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
116
117 return win32_get_current_dr (regnum - DR_FIRSTADDR);
118 }
119
120 static unsigned long
121 x86_dr_low_get_control (void)
122 {
123 return win32_get_current_dr (7);
124 }
125
126 /* Get the value of the DR6 debug status register from the inferior
127 and record it in STATE. */
128
129 static unsigned long
130 x86_dr_low_get_status (void)
131 {
132 return win32_get_current_dr (6);
133 }
134
135 /* Low-level function vector. */
136 struct x86_dr_low_type x86_dr_low =
137 {
138 x86_dr_low_set_control,
139 x86_dr_low_set_addr,
140 x86_dr_low_get_addr,
141 x86_dr_low_get_status,
142 x86_dr_low_get_control,
143 sizeof (void *),
144 };
145
146 /* Breakpoint/watchpoint support. */
147
148 static int
149 i386_supports_z_point_type (char z_type)
150 {
151 switch (z_type)
152 {
153 case Z_PACKET_WRITE_WP:
154 case Z_PACKET_ACCESS_WP:
155 return 1;
156 default:
157 return 0;
158 }
159 }
160
161 static int
162 i386_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
163 int size, struct raw_breakpoint *bp)
164 {
165 switch (type)
166 {
167 case raw_bkpt_type_write_wp:
168 case raw_bkpt_type_access_wp:
169 {
170 enum target_hw_bp_type hw_type
171 = raw_bkpt_type_to_target_hw_bp_type (type);
172
173 return x86_dr_insert_watchpoint (&debug_reg_state,
174 hw_type, addr, size);
175 }
176 default:
177 /* Unsupported. */
178 return 1;
179 }
180 }
181
182 static int
183 i386_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
184 int size, struct raw_breakpoint *bp)
185 {
186 switch (type)
187 {
188 case raw_bkpt_type_write_wp:
189 case raw_bkpt_type_access_wp:
190 {
191 enum target_hw_bp_type hw_type
192 = raw_bkpt_type_to_target_hw_bp_type (type);
193
194 return x86_dr_remove_watchpoint (&debug_reg_state,
195 hw_type, addr, size);
196 }
197 default:
198 /* Unsupported. */
199 return 1;
200 }
201 }
202
203 static int
204 x86_stopped_by_watchpoint (void)
205 {
206 return x86_dr_stopped_by_watchpoint (&debug_reg_state);
207 }
208
209 static CORE_ADDR
210 x86_stopped_data_address (void)
211 {
212 CORE_ADDR addr;
213 if (x86_dr_stopped_data_address (&debug_reg_state, &addr))
214 return addr;
215 return 0;
216 }
217
218 static void
219 i386_initial_stuff (void)
220 {
221 x86_low_init_dregs (&debug_reg_state);
222 }
223
224 static void
225 i386_get_thread_context (win32_thread_info *th)
226 {
227 /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if
228 the system doesn't support extended registers. */
229 static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS;
230
231 again:
232 th->context.ContextFlags = (CONTEXT_FULL
233 | CONTEXT_FLOATING_POINT
234 | CONTEXT_DEBUG_REGISTERS
235 | extended_registers);
236
237 if (!GetThreadContext (th->h, &th->context))
238 {
239 DWORD e = GetLastError ();
240
241 if (extended_registers && e == ERROR_INVALID_PARAMETER)
242 {
243 extended_registers = 0;
244 goto again;
245 }
246
247 error ("GetThreadContext failure %ld\n", (long) e);
248 }
249 }
250
251 static void
252 i386_prepare_to_resume (win32_thread_info *th)
253 {
254 if (th->debug_registers_changed)
255 {
256 struct x86_debug_reg_state *dr = &debug_reg_state;
257
258 win32_require_context (th);
259
260 th->context.Dr0 = dr->dr_mirror[0];
261 th->context.Dr1 = dr->dr_mirror[1];
262 th->context.Dr2 = dr->dr_mirror[2];
263 th->context.Dr3 = dr->dr_mirror[3];
264 /* th->context.Dr6 = dr->dr_status_mirror;
265 FIXME: should we set dr6 also ?? */
266 th->context.Dr7 = dr->dr_control_mirror;
267
268 th->debug_registers_changed = 0;
269 }
270 }
271
272 static void
273 i386_thread_added (win32_thread_info *th)
274 {
275 th->debug_registers_changed = 1;
276 }
277
278 static void
279 i386_single_step (win32_thread_info *th)
280 {
281 th->context.EFlags |= FLAG_TRACE_BIT;
282 }
283
284 #ifndef __x86_64__
285
286 /* An array of offset mappings into a Win32 Context structure.
287 This is a one-to-one mapping which is indexed by gdb's register
288 numbers. It retrieves an offset into the context structure where
289 the 4 byte register is located.
290 An offset value of -1 indicates that Win32 does not provide this
291 register in it's CONTEXT structure. In this case regptr will return
292 a pointer into a dummy register. */
293 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
294 static const int mappings[] = {
295 context_offset (Eax),
296 context_offset (Ecx),
297 context_offset (Edx),
298 context_offset (Ebx),
299 context_offset (Esp),
300 context_offset (Ebp),
301 context_offset (Esi),
302 context_offset (Edi),
303 context_offset (Eip),
304 context_offset (EFlags),
305 context_offset (SegCs),
306 context_offset (SegSs),
307 context_offset (SegDs),
308 context_offset (SegEs),
309 context_offset (SegFs),
310 context_offset (SegGs),
311 context_offset (FloatSave.RegisterArea[0 * 10]),
312 context_offset (FloatSave.RegisterArea[1 * 10]),
313 context_offset (FloatSave.RegisterArea[2 * 10]),
314 context_offset (FloatSave.RegisterArea[3 * 10]),
315 context_offset (FloatSave.RegisterArea[4 * 10]),
316 context_offset (FloatSave.RegisterArea[5 * 10]),
317 context_offset (FloatSave.RegisterArea[6 * 10]),
318 context_offset (FloatSave.RegisterArea[7 * 10]),
319 context_offset (FloatSave.ControlWord),
320 context_offset (FloatSave.StatusWord),
321 context_offset (FloatSave.TagWord),
322 context_offset (FloatSave.ErrorSelector),
323 context_offset (FloatSave.ErrorOffset),
324 context_offset (FloatSave.DataSelector),
325 context_offset (FloatSave.DataOffset),
326 context_offset (FloatSave.ErrorSelector),
327 /* XMM0-7 */
328 context_offset (ExtendedRegisters[10 * 16]),
329 context_offset (ExtendedRegisters[11 * 16]),
330 context_offset (ExtendedRegisters[12 * 16]),
331 context_offset (ExtendedRegisters[13 * 16]),
332 context_offset (ExtendedRegisters[14 * 16]),
333 context_offset (ExtendedRegisters[15 * 16]),
334 context_offset (ExtendedRegisters[16 * 16]),
335 context_offset (ExtendedRegisters[17 * 16]),
336 /* MXCSR */
337 context_offset (ExtendedRegisters[24])
338 };
339 #undef context_offset
340
341 #else /* __x86_64__ */
342
343 #define context_offset(x) (offsetof (CONTEXT, x))
344 static const int mappings[] =
345 {
346 context_offset (Rax),
347 context_offset (Rbx),
348 context_offset (Rcx),
349 context_offset (Rdx),
350 context_offset (Rsi),
351 context_offset (Rdi),
352 context_offset (Rbp),
353 context_offset (Rsp),
354 context_offset (R8),
355 context_offset (R9),
356 context_offset (R10),
357 context_offset (R11),
358 context_offset (R12),
359 context_offset (R13),
360 context_offset (R14),
361 context_offset (R15),
362 context_offset (Rip),
363 context_offset (EFlags),
364 context_offset (SegCs),
365 context_offset (SegSs),
366 context_offset (SegDs),
367 context_offset (SegEs),
368 context_offset (SegFs),
369 context_offset (SegGs),
370 context_offset (FloatSave.FloatRegisters[0]),
371 context_offset (FloatSave.FloatRegisters[1]),
372 context_offset (FloatSave.FloatRegisters[2]),
373 context_offset (FloatSave.FloatRegisters[3]),
374 context_offset (FloatSave.FloatRegisters[4]),
375 context_offset (FloatSave.FloatRegisters[5]),
376 context_offset (FloatSave.FloatRegisters[6]),
377 context_offset (FloatSave.FloatRegisters[7]),
378 context_offset (FloatSave.ControlWord),
379 context_offset (FloatSave.StatusWord),
380 context_offset (FloatSave.TagWord),
381 context_offset (FloatSave.ErrorSelector),
382 context_offset (FloatSave.ErrorOffset),
383 context_offset (FloatSave.DataSelector),
384 context_offset (FloatSave.DataOffset),
385 context_offset (FloatSave.ErrorSelector)
386 /* XMM0-7 */ ,
387 context_offset (Xmm0),
388 context_offset (Xmm1),
389 context_offset (Xmm2),
390 context_offset (Xmm3),
391 context_offset (Xmm4),
392 context_offset (Xmm5),
393 context_offset (Xmm6),
394 context_offset (Xmm7),
395 context_offset (Xmm8),
396 context_offset (Xmm9),
397 context_offset (Xmm10),
398 context_offset (Xmm11),
399 context_offset (Xmm12),
400 context_offset (Xmm13),
401 context_offset (Xmm14),
402 context_offset (Xmm15),
403 /* MXCSR */
404 context_offset (FloatSave.MxCsr)
405 };
406 #undef context_offset
407
408 #endif /* __x86_64__ */
409
410 /* Fetch register from gdbserver regcache data. */
411 static void
412 i386_fetch_inferior_register (struct regcache *regcache,
413 win32_thread_info *th, int r)
414 {
415 char *context_offset = (char *) &th->context + mappings[r];
416
417 long l;
418 if (r == FCS_REGNUM)
419 {
420 l = *((long *) context_offset) & 0xffff;
421 supply_register (regcache, r, (char *) &l);
422 }
423 else if (r == FOP_REGNUM)
424 {
425 l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
426 supply_register (regcache, r, (char *) &l);
427 }
428 else
429 supply_register (regcache, r, context_offset);
430 }
431
432 /* Store a new register value into the thread context of TH. */
433 static void
434 i386_store_inferior_register (struct regcache *regcache,
435 win32_thread_info *th, int r)
436 {
437 char *context_offset = (char *) &th->context + mappings[r];
438 collect_register (regcache, r, context_offset);
439 }
440
441 static const unsigned char i386_win32_breakpoint = 0xcc;
442 #define i386_win32_breakpoint_len 1
443
444 static void
445 i386_arch_setup (void)
446 {
447 struct target_desc *tdesc;
448
449 #ifdef __x86_64__
450 tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
451 false);
452 #else
453 tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false);
454 #endif
455
456 init_target_desc (tdesc);
457
458 win32_tdesc = tdesc;
459 }
460
461 struct win32_target_ops the_low_target = {
462 i386_arch_setup,
463 sizeof (mappings) / sizeof (mappings[0]),
464 i386_initial_stuff,
465 i386_get_thread_context,
466 i386_prepare_to_resume,
467 i386_thread_added,
468 i386_fetch_inferior_register,
469 i386_store_inferior_register,
470 i386_single_step,
471 &i386_win32_breakpoint,
472 i386_win32_breakpoint_len,
473 i386_supports_z_point_type,
474 i386_insert_point,
475 i386_remove_point,
476 x86_stopped_by_watchpoint,
477 x86_stopped_data_address
478 };
This page took 0.044217 seconds and 5 git commands to generate.