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