gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdbserver / win32-i386-low.cc
1 /* Copyright (C) 2007-2020 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 "gdbsupport/x86-xstate.h"
22 #ifdef __x86_64__
23 #include "arch/amd64.h"
24 #endif
25 #include "arch/i386.h"
26 #include "tdesc.h"
27 #include "x86-tdesc.h"
28
29 using namespace windows_nat;
30
31 #ifndef CONTEXT_EXTENDED_REGISTERS
32 #define CONTEXT_EXTENDED_REGISTERS 0
33 #endif
34
35 #define FCS_REGNUM 27
36 #define FOP_REGNUM 31
37
38 #define FLAG_TRACE_BIT 0x100
39
40 static struct x86_debug_reg_state debug_reg_state;
41
42 static void
43 update_debug_registers (thread_info *thread)
44 {
45 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
46
47 /* The actual update is done later just before resuming the lwp,
48 we just mark that the registers need updating. */
49 th->debug_registers_changed = true;
50 }
51
52 /* Update the inferior's debug register REGNUM from STATE. */
53
54 static void
55 x86_dr_low_set_addr (int regnum, CORE_ADDR addr)
56 {
57 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
58
59 /* Only update the threads of this process. */
60 for_each_thread (current_thread->id.pid (), update_debug_registers);
61 }
62
63 /* Update the inferior's DR7 debug control register from STATE. */
64
65 static void
66 x86_dr_low_set_control (unsigned long control)
67 {
68 /* Only update the threads of this process. */
69 for_each_thread (current_thread->id.pid (), update_debug_registers);
70 }
71
72 /* Return the current value of a DR register of the current thread's
73 context. */
74
75 static DWORD64
76 win32_get_current_dr (int dr)
77 {
78 windows_thread_info *th
79 = (windows_thread_info *) thread_target_data (current_thread);
80
81 win32_require_context (th);
82
83 #ifdef __x86_64__
84 #define RET_DR(DR) \
85 case DR: \
86 return th->wow64_context.Dr ## DR
87
88 if (wow64_process)
89 {
90 switch (dr)
91 {
92 RET_DR (0);
93 RET_DR (1);
94 RET_DR (2);
95 RET_DR (3);
96 RET_DR (6);
97 RET_DR (7);
98 }
99 }
100 else
101 #undef RET_DR
102 #endif
103 #define RET_DR(DR) \
104 case DR: \
105 return th->context.Dr ## DR
106
107 {
108 switch (dr)
109 {
110 RET_DR (0);
111 RET_DR (1);
112 RET_DR (2);
113 RET_DR (3);
114 RET_DR (6);
115 RET_DR (7);
116 }
117 }
118
119 #undef RET_DR
120
121 gdb_assert_not_reached ("unhandled dr");
122 }
123
124 static CORE_ADDR
125 x86_dr_low_get_addr (int regnum)
126 {
127 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
128
129 return win32_get_current_dr (regnum - DR_FIRSTADDR);
130 }
131
132 static unsigned long
133 x86_dr_low_get_control (void)
134 {
135 return win32_get_current_dr (7);
136 }
137
138 /* Get the value of the DR6 debug status register from the inferior
139 and record it in STATE. */
140
141 static unsigned long
142 x86_dr_low_get_status (void)
143 {
144 return win32_get_current_dr (6);
145 }
146
147 /* Low-level function vector. */
148 struct x86_dr_low_type x86_dr_low =
149 {
150 x86_dr_low_set_control,
151 x86_dr_low_set_addr,
152 x86_dr_low_get_addr,
153 x86_dr_low_get_status,
154 x86_dr_low_get_control,
155 sizeof (void *),
156 };
157
158 /* Breakpoint/watchpoint support. */
159
160 static int
161 i386_supports_z_point_type (char z_type)
162 {
163 switch (z_type)
164 {
165 case Z_PACKET_HW_BP:
166 case Z_PACKET_WRITE_WP:
167 case Z_PACKET_ACCESS_WP:
168 return 1;
169 default:
170 return 0;
171 }
172 }
173
174 static int
175 i386_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
176 int size, struct raw_breakpoint *bp)
177 {
178 switch (type)
179 {
180 case raw_bkpt_type_hw:
181 case raw_bkpt_type_write_wp:
182 case raw_bkpt_type_access_wp:
183 {
184 enum target_hw_bp_type hw_type
185 = raw_bkpt_type_to_target_hw_bp_type (type);
186
187 return x86_dr_insert_watchpoint (&debug_reg_state,
188 hw_type, addr, size);
189 }
190 default:
191 /* Unsupported. */
192 return 1;
193 }
194 }
195
196 static int
197 i386_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
198 int size, struct raw_breakpoint *bp)
199 {
200 switch (type)
201 {
202 case raw_bkpt_type_hw:
203 case raw_bkpt_type_write_wp:
204 case raw_bkpt_type_access_wp:
205 {
206 enum target_hw_bp_type hw_type
207 = raw_bkpt_type_to_target_hw_bp_type (type);
208
209 return x86_dr_remove_watchpoint (&debug_reg_state,
210 hw_type, addr, size);
211 }
212 default:
213 /* Unsupported. */
214 return 1;
215 }
216 }
217
218 static int
219 x86_stopped_by_watchpoint (void)
220 {
221 return x86_dr_stopped_by_watchpoint (&debug_reg_state);
222 }
223
224 static CORE_ADDR
225 x86_stopped_data_address (void)
226 {
227 CORE_ADDR addr;
228 if (x86_dr_stopped_data_address (&debug_reg_state, &addr))
229 return addr;
230 return 0;
231 }
232
233 static void
234 i386_initial_stuff (void)
235 {
236 x86_low_init_dregs (&debug_reg_state);
237 }
238
239 static void
240 i386_get_thread_context (windows_thread_info *th)
241 {
242 /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if
243 the system doesn't support extended registers. */
244 static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS;
245
246 again:
247 #ifdef __x86_64__
248 if (wow64_process)
249 th->wow64_context.ContextFlags = (CONTEXT_FULL
250 | CONTEXT_FLOATING_POINT
251 | CONTEXT_DEBUG_REGISTERS
252 | extended_registers);
253 else
254 #endif
255 th->context.ContextFlags = (CONTEXT_FULL
256 | CONTEXT_FLOATING_POINT
257 | CONTEXT_DEBUG_REGISTERS
258 | extended_registers);
259
260 BOOL ret;
261 #ifdef __x86_64__
262 if (wow64_process)
263 ret = win32_Wow64GetThreadContext (th->h, &th->wow64_context);
264 else
265 #endif
266 ret = GetThreadContext (th->h, &th->context);
267 if (!ret)
268 {
269 DWORD e = GetLastError ();
270
271 if (extended_registers && e == ERROR_INVALID_PARAMETER)
272 {
273 extended_registers = 0;
274 goto again;
275 }
276
277 error ("GetThreadContext failure %ld\n", (long) e);
278 }
279 }
280
281 static void
282 i386_prepare_to_resume (windows_thread_info *th)
283 {
284 if (th->debug_registers_changed)
285 {
286 struct x86_debug_reg_state *dr = &debug_reg_state;
287
288 win32_require_context (th);
289
290 #ifdef __x86_64__
291 if (wow64_process)
292 {
293 th->wow64_context.Dr0 = dr->dr_mirror[0];
294 th->wow64_context.Dr1 = dr->dr_mirror[1];
295 th->wow64_context.Dr2 = dr->dr_mirror[2];
296 th->wow64_context.Dr3 = dr->dr_mirror[3];
297 /* th->wow64_context.Dr6 = dr->dr_status_mirror;
298 FIXME: should we set dr6 also ?? */
299 th->wow64_context.Dr7 = dr->dr_control_mirror;
300 }
301 else
302 #endif
303 {
304 th->context.Dr0 = dr->dr_mirror[0];
305 th->context.Dr1 = dr->dr_mirror[1];
306 th->context.Dr2 = dr->dr_mirror[2];
307 th->context.Dr3 = dr->dr_mirror[3];
308 /* th->context.Dr6 = dr->dr_status_mirror;
309 FIXME: should we set dr6 also ?? */
310 th->context.Dr7 = dr->dr_control_mirror;
311 }
312
313 th->debug_registers_changed = false;
314 }
315 }
316
317 static void
318 i386_thread_added (windows_thread_info *th)
319 {
320 th->debug_registers_changed = true;
321 }
322
323 static void
324 i386_single_step (windows_thread_info *th)
325 {
326 #ifdef __x86_64__
327 if (wow64_process)
328 th->wow64_context.EFlags |= FLAG_TRACE_BIT;
329 else
330 #endif
331 th->context.EFlags |= FLAG_TRACE_BIT;
332 }
333
334 /* An array of offset mappings into a Win32 Context structure.
335 This is a one-to-one mapping which is indexed by gdb's register
336 numbers. It retrieves an offset into the context structure where
337 the 4 byte register is located.
338 An offset value of -1 indicates that Win32 does not provide this
339 register in it's CONTEXT structure. In this case regptr will return
340 a pointer into a dummy register. */
341 #ifdef __x86_64__
342 #define context_offset(x) (offsetof (WOW64_CONTEXT, x))
343 #else
344 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
345 #endif
346 static const int i386_mappings[] = {
347 context_offset (Eax),
348 context_offset (Ecx),
349 context_offset (Edx),
350 context_offset (Ebx),
351 context_offset (Esp),
352 context_offset (Ebp),
353 context_offset (Esi),
354 context_offset (Edi),
355 context_offset (Eip),
356 context_offset (EFlags),
357 context_offset (SegCs),
358 context_offset (SegSs),
359 context_offset (SegDs),
360 context_offset (SegEs),
361 context_offset (SegFs),
362 context_offset (SegGs),
363 context_offset (FloatSave.RegisterArea[0 * 10]),
364 context_offset (FloatSave.RegisterArea[1 * 10]),
365 context_offset (FloatSave.RegisterArea[2 * 10]),
366 context_offset (FloatSave.RegisterArea[3 * 10]),
367 context_offset (FloatSave.RegisterArea[4 * 10]),
368 context_offset (FloatSave.RegisterArea[5 * 10]),
369 context_offset (FloatSave.RegisterArea[6 * 10]),
370 context_offset (FloatSave.RegisterArea[7 * 10]),
371 context_offset (FloatSave.ControlWord),
372 context_offset (FloatSave.StatusWord),
373 context_offset (FloatSave.TagWord),
374 context_offset (FloatSave.ErrorSelector),
375 context_offset (FloatSave.ErrorOffset),
376 context_offset (FloatSave.DataSelector),
377 context_offset (FloatSave.DataOffset),
378 context_offset (FloatSave.ErrorSelector),
379 /* XMM0-7 */
380 context_offset (ExtendedRegisters[10 * 16]),
381 context_offset (ExtendedRegisters[11 * 16]),
382 context_offset (ExtendedRegisters[12 * 16]),
383 context_offset (ExtendedRegisters[13 * 16]),
384 context_offset (ExtendedRegisters[14 * 16]),
385 context_offset (ExtendedRegisters[15 * 16]),
386 context_offset (ExtendedRegisters[16 * 16]),
387 context_offset (ExtendedRegisters[17 * 16]),
388 /* MXCSR */
389 context_offset (ExtendedRegisters[24])
390 };
391 #undef context_offset
392
393 #ifdef __x86_64__
394
395 #define context_offset(x) (offsetof (CONTEXT, x))
396 static const int amd64_mappings[] =
397 {
398 context_offset (Rax),
399 context_offset (Rbx),
400 context_offset (Rcx),
401 context_offset (Rdx),
402 context_offset (Rsi),
403 context_offset (Rdi),
404 context_offset (Rbp),
405 context_offset (Rsp),
406 context_offset (R8),
407 context_offset (R9),
408 context_offset (R10),
409 context_offset (R11),
410 context_offset (R12),
411 context_offset (R13),
412 context_offset (R14),
413 context_offset (R15),
414 context_offset (Rip),
415 context_offset (EFlags),
416 context_offset (SegCs),
417 context_offset (SegSs),
418 context_offset (SegDs),
419 context_offset (SegEs),
420 context_offset (SegFs),
421 context_offset (SegGs),
422 context_offset (FloatSave.FloatRegisters[0]),
423 context_offset (FloatSave.FloatRegisters[1]),
424 context_offset (FloatSave.FloatRegisters[2]),
425 context_offset (FloatSave.FloatRegisters[3]),
426 context_offset (FloatSave.FloatRegisters[4]),
427 context_offset (FloatSave.FloatRegisters[5]),
428 context_offset (FloatSave.FloatRegisters[6]),
429 context_offset (FloatSave.FloatRegisters[7]),
430 context_offset (FloatSave.ControlWord),
431 context_offset (FloatSave.StatusWord),
432 context_offset (FloatSave.TagWord),
433 context_offset (FloatSave.ErrorSelector),
434 context_offset (FloatSave.ErrorOffset),
435 context_offset (FloatSave.DataSelector),
436 context_offset (FloatSave.DataOffset),
437 context_offset (FloatSave.ErrorSelector)
438 /* XMM0-7 */ ,
439 context_offset (Xmm0),
440 context_offset (Xmm1),
441 context_offset (Xmm2),
442 context_offset (Xmm3),
443 context_offset (Xmm4),
444 context_offset (Xmm5),
445 context_offset (Xmm6),
446 context_offset (Xmm7),
447 context_offset (Xmm8),
448 context_offset (Xmm9),
449 context_offset (Xmm10),
450 context_offset (Xmm11),
451 context_offset (Xmm12),
452 context_offset (Xmm13),
453 context_offset (Xmm14),
454 context_offset (Xmm15),
455 /* MXCSR */
456 context_offset (FloatSave.MxCsr)
457 };
458 #undef context_offset
459
460 #endif /* __x86_64__ */
461
462 /* Fetch register from gdbserver regcache data. */
463 static void
464 i386_fetch_inferior_register (struct regcache *regcache,
465 windows_thread_info *th, int r)
466 {
467 const int *mappings;
468 #ifdef __x86_64__
469 if (!wow64_process)
470 mappings = amd64_mappings;
471 else
472 #endif
473 mappings = i386_mappings;
474
475 char *context_offset;
476 #ifdef __x86_64__
477 if (wow64_process)
478 context_offset = (char *) &th->wow64_context + mappings[r];
479 else
480 #endif
481 context_offset = (char *) &th->context + mappings[r];
482
483 long l;
484 if (r == FCS_REGNUM)
485 {
486 l = *((long *) context_offset) & 0xffff;
487 supply_register (regcache, r, (char *) &l);
488 }
489 else if (r == FOP_REGNUM)
490 {
491 l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
492 supply_register (regcache, r, (char *) &l);
493 }
494 else
495 supply_register (regcache, r, context_offset);
496 }
497
498 /* Store a new register value into the thread context of TH. */
499 static void
500 i386_store_inferior_register (struct regcache *regcache,
501 windows_thread_info *th, int r)
502 {
503 const int *mappings;
504 #ifdef __x86_64__
505 if (!wow64_process)
506 mappings = amd64_mappings;
507 else
508 #endif
509 mappings = i386_mappings;
510
511 char *context_offset;
512 #ifdef __x86_64__
513 if (wow64_process)
514 context_offset = (char *) &th->wow64_context + mappings[r];
515 else
516 #endif
517 context_offset = (char *) &th->context + mappings[r];
518
519 collect_register (regcache, r, context_offset);
520 }
521
522 static const unsigned char i386_win32_breakpoint = 0xcc;
523 #define i386_win32_breakpoint_len 1
524
525 static void
526 i386_arch_setup (void)
527 {
528 struct target_desc *tdesc;
529
530 #ifdef __x86_64__
531 tdesc = amd64_create_target_description (X86_XSTATE_SSE_MASK, false,
532 false, false);
533 init_target_desc (tdesc, amd64_expedite_regs);
534 win32_tdesc = tdesc;
535 #endif
536
537 tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false);
538 init_target_desc (tdesc, i386_expedite_regs);
539 #ifdef __x86_64__
540 wow64_win32_tdesc = tdesc;
541 #else
542 win32_tdesc = tdesc;
543 #endif
544 }
545
546 /* Implement win32_target_ops "num_regs" method. */
547
548 static int
549 i386_win32_num_regs (void)
550 {
551 int num_regs;
552 #ifdef __x86_64__
553 if (!wow64_process)
554 num_regs = sizeof (amd64_mappings) / sizeof (amd64_mappings[0]);
555 else
556 #endif
557 num_regs = sizeof (i386_mappings) / sizeof (i386_mappings[0]);
558 return num_regs;
559 }
560
561 /* Implement win32_target_ops "get_pc" method. */
562
563 static CORE_ADDR
564 i386_win32_get_pc (struct regcache *regcache)
565 {
566 bool use_64bit = register_size (regcache->tdesc, 0) == 8;
567
568 if (use_64bit)
569 {
570 uint64_t pc;
571
572 collect_register_by_name (regcache, "rip", &pc);
573 return (CORE_ADDR) pc;
574 }
575 else
576 {
577 uint32_t pc;
578
579 collect_register_by_name (regcache, "eip", &pc);
580 return (CORE_ADDR) pc;
581 }
582 }
583
584 /* Implement win32_target_ops "set_pc" method. */
585
586 static void
587 i386_win32_set_pc (struct regcache *regcache, CORE_ADDR pc)
588 {
589 bool use_64bit = register_size (regcache->tdesc, 0) == 8;
590
591 if (use_64bit)
592 {
593 uint64_t newpc = pc;
594
595 supply_register_by_name (regcache, "rip", &newpc);
596 }
597 else
598 {
599 uint32_t newpc = pc;
600
601 supply_register_by_name (regcache, "eip", &newpc);
602 }
603 }
604
605 struct win32_target_ops the_low_target = {
606 i386_arch_setup,
607 i386_win32_num_regs,
608 i386_initial_stuff,
609 i386_get_thread_context,
610 i386_prepare_to_resume,
611 i386_thread_added,
612 i386_fetch_inferior_register,
613 i386_store_inferior_register,
614 i386_single_step,
615 &i386_win32_breakpoint,
616 i386_win32_breakpoint_len,
617 1,
618 i386_win32_get_pc,
619 i386_win32_set_pc,
620 i386_supports_z_point_type,
621 i386_insert_point,
622 i386_remove_point,
623 x86_stopped_by_watchpoint,
624 x86_stopped_data_address
625 };
This page took 0.041747 seconds and 4 git commands to generate.