GDB (xrefs)
Loading...
Searching...
No Matches
windows-nat.c
Go to the documentation of this file.
1/* Target-vector operations for controlling windows child processes, for GDB.
2
3 Copyright (C) 1995-2023 Free Software Foundation, Inc.
4
5 Contributed by Cygnus Solutions, A Red Hat Company.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22/* Originally by Steve Chamberlain, sac@cygnus.com */
23
24#include "defs.h"
25#include "frame.h"
26#include "inferior.h"
27#include "infrun.h"
28#include "target.h"
29#include "gdbcore.h"
30#include "command.h"
31#include "completer.h"
32#include "regcache.h"
33#include "top.h"
34#include <signal.h>
35#include <sys/types.h>
36#include <fcntl.h>
37#include <windows.h>
38#include <imagehlp.h>
39#ifdef __CYGWIN__
40#include <wchar.h>
41#include <sys/cygwin.h>
42#include <cygwin/version.h>
43#endif
44#include <algorithm>
45#include <vector>
46#include <queue>
47
48#include "filenames.h"
49#include "symfile.h"
50#include "objfiles.h"
51#include "gdb_bfd.h"
52#include "gdbsupport/gdb_obstack.h"
53#include "gdbthread.h"
54#include "gdbcmd.h"
55#include <unistd.h>
56#include "exec.h"
57#include "solist.h"
58#include "solib.h"
59#include "xml-support.h"
60#include "inttypes.h"
61
62#include "i386-tdep.h"
63#include "i387-tdep.h"
64
65#include "windows-tdep.h"
66#include "windows-nat.h"
67#include "x86-nat.h"
68#include "complaints.h"
69#include "inf-child.h"
70#include "gdbsupport/gdb_tilde_expand.h"
71#include "gdbsupport/pathstuff.h"
72#include "gdbsupport/gdb_wait.h"
73#include "nat/windows-nat.h"
74#include "gdbsupport/symbol.h"
75#include "ser-event.h"
76#include "inf-loop.h"
77
78using namespace windows_nat;
79
80/* Maintain a linked list of "so" information. */
82{
83 LPVOID load_addr = 0;
84 CORE_ADDR text_offset = 0;
85
86 /* Original name. */
87 std::string original_name;
88 /* Expanded form of the name. */
89 std::string name;
90};
91
93{
94 windows_thread_info *thread_rec (ptid_t ptid,
95 thread_disposition_type disposition) override;
96 int handle_output_debug_string (struct target_waitstatus *ourstatus) override;
97 void handle_load_dll (const char *dll_name, LPVOID base) override;
98 void handle_unload_dll () override;
99 bool handle_access_violation (const EXCEPTION_RECORD *rec) override;
100
101
102 int have_saved_context = 0; /* True if we've saved context from a
103 cygwin signal. */
104
105 uintptr_t dr[8] {};
106
108
109 std::vector<std::unique_ptr<windows_thread_info>> thread_list;
110
111 /* Counts of things. */
112 int saw_create = 0;
114#ifdef __x86_64__
115 void *wow64_dbgbreak = nullptr;
116#endif
117
118 /* This vector maps GDB's idea of a register's number into an offset
119 in the windows exception context vector.
120
121 It also contains the bit mask needed to load the register in question.
122
123 The contents of this table can only be computed by the units
124 that provide CPU-specific support for Windows native debugging.
125
126 One day we could read a reg, we could inspect the context we
127 already have loaded, if it doesn't have the bit set that we need,
128 we read that set of registers in using GetThreadContext. If the
129 context already contains what we need, we just unpack it. Then to
130 write a register, first we have to ensure that the context contains
131 the other regs of the group, and then we copy the info in and set
132 out bit. */
133
134 const int *mappings = nullptr;
135
136 /* The function to use in order to determine whether a register is
137 a segment register or not. */
139
140 std::vector<windows_solib> solibs;
141
142#ifdef __CYGWIN__
143 CONTEXT saved_context {}; /* Contains the saved context from a
144 cygwin signal. */
145
146 /* The starting and ending address of the cygwin1.dll text segment. */
147 CORE_ADDR cygwin_load_start = 0;
148 CORE_ADDR cygwin_load_end = 0;
149#endif /* __CYGWIN__ */
150};
151
152/* The current process. */
154
155#undef STARTUPINFO
156
157#ifndef __CYGWIN__
158# define __PMAX (MAX_PATH + 1)
159# define STARTUPINFO STARTUPINFOA
160#else
161# define __PMAX PATH_MAX
162# define STARTUPINFO STARTUPINFOW
163#endif
164
165/* If we're not using the old Cygwin header file set, define the
166 following which never should have been in the generic Win32 API
167 headers in the first place since they were our own invention... */
168#ifndef _GNU_H_WINDOWS_H
169enum
170 {
172 };
173#endif
174
175#ifndef CONTEXT_EXTENDED_REGISTERS
176/* This macro is only defined on ia32. It only makes sense on this target,
177 so define it as zero if not already defined. */
178#define CONTEXT_EXTENDED_REGISTERS 0
179#endif
180
181#define CONTEXT_DEBUGGER_DR CONTEXT_FULL | CONTEXT_FLOATING_POINT \
182 | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS \
183 | CONTEXT_EXTENDED_REGISTERS
184
185#define DR6_CLEAR_VALUE 0xffff0ff0
186
187/* The string sent by cygwin when it processes a signal.
188 FIXME: This should be in a cygwin include file. */
189#ifndef _CYGWIN_SIGNAL_STRING
190#define _CYGWIN_SIGNAL_STRING "cYgSiGw00f"
191#endif
192
193#define CHECK(x) check (x, __FILE__,__LINE__)
194#define DEBUG_EXEC(fmt, ...) \
195 debug_prefixed_printf_cond (debug_exec, "windows exec", fmt, ## __VA_ARGS__)
196#define DEBUG_EVENTS(fmt, ...) \
197 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
198 ## __VA_ARGS__)
199#define DEBUG_MEM(fmt, ...) \
200 debug_prefixed_printf_cond (debug_memory, "windows mem", fmt, \
201 ## __VA_ARGS__)
202#define DEBUG_EXCEPT(fmt, ...) \
203 debug_prefixed_printf_cond (debug_exceptions, "windows except", fmt, \
204 ## __VA_ARGS__)
205
206static void cygwin_set_dr (int i, CORE_ADDR addr);
207static void cygwin_set_dr7 (unsigned long val);
208static CORE_ADDR cygwin_get_dr (int i);
209static unsigned long cygwin_get_dr6 (void);
210static unsigned long cygwin_get_dr7 (void);
211
212/* User options. */
213static bool new_console = false;
214#ifdef __CYGWIN__
215static bool cygwin_exceptions = false;
216#endif
217static bool new_group = true;
218static bool debug_exec = false; /* show execution */
219static bool debug_events = false; /* show events from kernel */
220static bool debug_memory = false; /* show target memory accesses */
221static bool debug_exceptions = false; /* show target exceptions */
222static bool useshell = false; /* use shell for subprocesses */
223
224/* See windows_nat_target::resume to understand why this is commented
225 out. */
226#if 0
227/* This vector maps the target's idea of an exception (extracted
228 from the DEBUG_EVENT structure) to GDB's idea. */
229
230struct xlate_exception
231 {
232 DWORD them;
233 enum gdb_signal us;
234 };
235
236static const struct xlate_exception xlate[] =
237{
238 {EXCEPTION_ACCESS_VIOLATION, GDB_SIGNAL_SEGV},
239 {STATUS_STACK_OVERFLOW, GDB_SIGNAL_SEGV},
240 {EXCEPTION_BREAKPOINT, GDB_SIGNAL_TRAP},
241 {DBG_CONTROL_C, GDB_SIGNAL_INT},
242 {EXCEPTION_SINGLE_STEP, GDB_SIGNAL_TRAP},
243 {STATUS_FLOAT_DIVIDE_BY_ZERO, GDB_SIGNAL_FPE}
244};
245
246#endif /* 0 */
247
248struct windows_nat_target final : public x86_nat_target<inf_child_target>
249{
251
252 void close () override;
253
254 void attach (const char *, int) override;
255
256 bool attach_no_wait () override
257 { return true; }
258
259 void detach (inferior *, int) override;
260
261 void resume (ptid_t, int , enum gdb_signal) override;
262
263 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
264
265 void fetch_registers (struct regcache *, int) override;
266 void store_registers (struct regcache *, int) override;
267
274
276 {
277 return true;
278 }
279
281 const char *annex,
282 gdb_byte *readbuf,
283 const gdb_byte *writebuf,
284 ULONGEST offset, ULONGEST len,
285 ULONGEST *xfered_len) override;
286
287 void files_info () override;
288
289 void kill () override;
290
291 void create_inferior (const char *, const std::string &,
292 char **, int) override;
293
294 void mourn_inferior () override;
295
296 bool thread_alive (ptid_t ptid) override;
297
298 std::string pid_to_str (ptid_t) override;
299
300 void interrupt () override;
301 void pass_ctrlc () override;
302
303 const char *pid_to_exec_file (int pid) override;
304
305 ptid_t get_ada_task_ptid (long lwp, ULONGEST thread) override;
306
307 bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
308
309 const char *thread_name (struct thread_info *) override;
310
311 ptid_t get_windows_debug_event (int pid, struct target_waitstatus *ourstatus,
312 target_wait_flags options);
313
314 void do_initial_windows_stuff (DWORD pid, bool attaching);
315
317 {
319 }
320
321 bool can_async_p () override
322 {
323 return true;
324 }
325
326 bool is_async_p () override
327 {
328 return m_is_async;
329 }
330
331 void async (bool enable) override;
332
333 int async_wait_fd () override
334 {
336 }
337
338private:
339
340 windows_thread_info *add_thread (ptid_t ptid, HANDLE h, void *tlb,
341 bool main_thread_p);
342 void delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p);
343 DWORD fake_create_process ();
344
345 BOOL windows_continue (DWORD continue_status, int id, int killed,
346 bool last_call = false);
347
348 /* Helper function to start process_thread. */
349 static DWORD WINAPI process_thread_starter (LPVOID self);
350
351 /* This function implements the background thread that starts
352 inferiors and waits for events. */
353 void process_thread ();
354
355 /* Push FUNC onto the queue of requests for process_thread, and wait
356 until it has been called. On Windows, certain debugging
357 functions can only be called by the thread that started (or
358 attached to) the inferior. These are all done in the worker
359 thread, via calls to this method. If FUNC returns true,
360 process_thread will wait for debug events when FUNC returns. */
361 void do_synchronously (gdb::function_view<bool ()> func);
362
363 /* This waits for a debug event, dispatching to the worker thread as
364 needed. */
365 void wait_for_debug_event_main_thread (DEBUG_EVENT *event);
366
367 /* Queue used to send requests to process_thread. This is
368 implicitly locked. */
369 std::queue<gdb::function_view<bool ()>> m_queue;
370
371 /* Event used to signal process_thread that an item has been
372 pushed. */
374 /* Event used by process_thread to indicate that it has processed a
375 single function call. */
377
378 /* Serial event used to communicate wait event availability to the
379 main loop. */
380 serial_event *m_wait_event;
381
382 /* The last debug event, when M_WAIT_EVENT has been set. */
383 DEBUG_EVENT m_last_debug_event {};
384 /* True if a debug event is pending. */
385 std::atomic<bool> m_debug_event_pending { false };
386
387 /* True if currently in async mode. */
388 bool m_is_async = false;
389};
390
391static void
392check (BOOL ok, const char *file, int line)
393{
394 if (!ok)
395 {
396 unsigned err = (unsigned) GetLastError ();
397 gdb_printf ("error return %s:%d was %u: %s\n", file, line,
398 err, strwinerror (err));
399 }
400}
401
403 : m_pushed_event (CreateEvent (nullptr, false, false, nullptr)),
404 m_response_event (CreateEvent (nullptr, false, false, nullptr)),
405 m_wait_event (make_serial_event ())
406{
407 HANDLE bg_thread = CreateThread (nullptr, 64 * 1024,
408 process_thread_starter, this, 0, nullptr);
409 CloseHandle (bg_thread);
410}
411
412void
414{
415 if (enable == is_async_p ())
416 return;
417
418 if (enable)
419 add_file_handler (async_wait_fd (),
420 [] (int, gdb_client_data)
421 {
423 },
424 nullptr, "windows_nat_target");
425 else
426 delete_file_handler (async_wait_fd ());
427
429}
430
431/* A wrapper for WaitForSingleObject that issues a warning if
432 something unusual happens. */
433static void
434wait_for_single (HANDLE handle, DWORD howlong)
435{
436 while (true)
437 {
438 DWORD r = WaitForSingleObject (handle, howlong);
439 if (r == WAIT_OBJECT_0)
440 return;
441 if (r == WAIT_FAILED)
442 {
443 unsigned err = (unsigned) GetLastError ();
444 warning ("WaitForSingleObject failed (code %u): %s",
445 err, strwinerror (err));
446 }
447 else
448 warning ("unexpected result from WaitForSingleObject: %u",
449 (unsigned) r);
450 }
451}
452
453DWORD WINAPI
455{
456 ((windows_nat_target *) self)->process_thread ();
457 return 0;
458}
459
460void
462{
463 while (true)
464 {
466
467 gdb::function_view<bool ()> func = std::move (m_queue.front ());
468 m_queue.pop ();
469
470 bool should_wait = func ();
471 SetEvent (m_response_event);
472
473 if (should_wait)
474 {
476 {
479 }
481 }
482 }
483}
484
485void
486windows_nat_target::do_synchronously (gdb::function_view<bool ()> func)
487{
488 m_queue.emplace (std::move (func));
489 SetEvent (m_pushed_event);
491}
492
493void
495{
496 do_synchronously ([&] ()
497 {
499 {
500 *event = m_last_debug_event;
501 m_debug_event_pending = false;
503 }
504 else
505 wait_for_debug_event (event, INFINITE);
506 return false;
507 });
508}
509
510/* See nat/windows-nat.h. */
511
514 (ptid_t ptid, thread_disposition_type disposition)
515{
516 for (auto &th : thread_list)
517 if (th->tid == ptid.lwp ())
518 {
519 if (!th->suspended)
520 {
521 switch (disposition)
522 {
524 /* Nothing. */
525 break;
527 if (ptid.lwp () != current_event.dwThreadId)
528 th->suspend ();
529 th->reload_context = true;
530 break;
531 case DONT_SUSPEND:
532 th->reload_context = true;
533 th->suspended = -1;
534 break;
535 }
536 }
537 return th.get ();
538 }
539
540 return NULL;
541}
542
543/* Add a thread to the thread list.
544
545 PTID is the ptid of the thread to be added.
546 H is its Windows handle.
547 TLB is its thread local base.
548 MAIN_THREAD_P should be true if the thread to be added is
549 the main thread, false otherwise. */
550
552windows_nat_target::add_thread (ptid_t ptid, HANDLE h, void *tlb,
553 bool main_thread_p)
554{
556
557 gdb_assert (ptid.lwp () != 0);
558
560 return th;
561
562 CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
563#ifdef __x86_64__
564 /* For WOW64 processes, this is actually the pointer to the 64bit TIB,
565 and the 32bit TIB is exactly 2 pages after it. */
566 if (windows_process.wow64_process)
567 base += 0x2000;
568#endif
569 th = new windows_thread_info (ptid.lwp (), h, base);
570 windows_process.thread_list.emplace_back (th);
571
572 /* Add this new thread to the list of threads.
573
574 To be consistent with what's done on other platforms, we add
575 the main thread silently (in reality, this thread is really
576 more of a process to the user than a thread). */
577 if (main_thread_p)
578 add_thread_silent (this, ptid);
579 else
580 ::add_thread (this, ptid);
581
582 /* It's simplest to always set this and update the debug
583 registers. */
584 th->debug_registers_changed = true;
585
586 return th;
587}
588
589/* Clear out any old thread list and reinitialize it to a
590 pristine state. */
591static void
593{
594 DEBUG_EVENTS ("called");
596}
597
598/* Delete a thread from the list of threads.
599
600 PTID is the ptid of the thread to be deleted.
601 EXIT_CODE is the thread's exit code.
602 MAIN_THREAD_P should be true if the thread to be deleted is
603 the main thread, false otherwise. */
604
605void
606windows_nat_target::delete_thread (ptid_t ptid, DWORD exit_code,
607 bool main_thread_p)
608{
609 DWORD id;
610
611 gdb_assert (ptid.lwp () != 0);
612
613 id = ptid.lwp ();
614
615 /* Note that no notification was printed when the main thread was
616 created, and thus, unless in verbose mode, we should be symmetrical,
617 and avoid an exit notification for the main thread here as well. */
618
619 bool silent = (main_thread_p && !info_verbose);
620 thread_info *to_del = this->find_thread (ptid);
621 delete_thread_with_exit_code (to_del, exit_code, silent);
622
623 auto iter = std::find_if (windows_process.thread_list.begin (),
625 [=] (std::unique_ptr<windows_thread_info> &th)
626 {
627 return th->tid == id;
628 });
629
630 if (iter != windows_process.thread_list.end ())
631 windows_process.thread_list.erase (iter);
632}
633
634/* Fetches register number R from the given windows_thread_info,
635 and supplies its value to the given regcache.
636
637 This function assumes that R is non-negative. A failed assertion
638 is raised if that is not true.
639
640 This function assumes that TH->RELOAD_CONTEXT is not set, meaning
641 that the windows_thread_info has an up-to-date context. A failed
642 assertion is raised if that assumption is violated. */
643
644static void
646 windows_thread_info *th, int r)
647{
648 gdb_assert (r >= 0);
649 gdb_assert (!th->reload_context);
650
651 char *context_ptr = (char *) &th->context;
652#ifdef __x86_64__
653 if (windows_process.wow64_process)
654 context_ptr = (char *) &th->wow64_context;
655#endif
656
657 char *context_offset = context_ptr + windows_process.mappings[r];
658 struct gdbarch *gdbarch = regcache->arch ();
659 i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
660
661 gdb_assert (!gdbarch_read_pc_p (gdbarch));
662 gdb_assert (gdbarch_pc_regnum (gdbarch) >= 0);
663 gdb_assert (!gdbarch_write_pc_p (gdbarch));
664
665 if (r == I387_FISEG_REGNUM (tdep))
666 {
667 long l = *((long *) context_offset) & 0xffff;
668 regcache->raw_supply (r, (char *) &l);
669 }
670 else if (r == I387_FOP_REGNUM (tdep))
671 {
672 long l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
673 regcache->raw_supply (r, (char *) &l);
674 }
676 {
677 /* GDB treats segment registers as 32bit registers, but they are
678 in fact only 16 bits long. Make sure we do not read extra
679 bits from our source buffer. */
680 long l = *((long *) context_offset) & 0xffff;
681 regcache->raw_supply (r, (char *) &l);
682 }
683 else
684 {
686 && !th->pc_adjusted
687 && r == gdbarch_pc_regnum (gdbarch))
688 {
689 int size = register_size (gdbarch, r);
690 if (size == 4)
691 {
692 uint32_t value;
693 memcpy (&value, context_offset, size);
695 memcpy (context_offset, &value, size);
696 }
697 else
698 {
699 gdb_assert (size == 8);
700 uint64_t value;
701 memcpy (&value, context_offset, size);
703 memcpy (context_offset, &value, size);
704 }
705 /* Make sure we only rewrite the PC a single time. */
706 th->pc_adjusted = true;
707 }
709 }
710}
711
712void
714{
717
718 /* Check if TH exists. Windows sometimes uses a non-existent
719 thread id in its events. */
720 if (th == NULL)
721 return;
722
723 if (th->reload_context)
724 {
725#ifdef __CYGWIN__
727 {
728 /* Lie about where the program actually is stopped since
729 cygwin has informed us that we should consider the signal
730 to have occurred at another location which is stored in
731 "saved_context. */
732 memcpy (&th->context, &windows_process.saved_context,
733 __COPY_CONTEXT_SIZE);
735 }
736 else
737#endif
738#ifdef __x86_64__
739 if (windows_process.wow64_process)
740 {
741 th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR;
742 CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
743 /* Copy dr values from that thread.
744 But only if there were not modified since last stop.
745 PR gdb/2388 */
747 {
748 windows_process.dr[0] = th->wow64_context.Dr0;
749 windows_process.dr[1] = th->wow64_context.Dr1;
750 windows_process.dr[2] = th->wow64_context.Dr2;
751 windows_process.dr[3] = th->wow64_context.Dr3;
752 windows_process.dr[6] = th->wow64_context.Dr6;
753 windows_process.dr[7] = th->wow64_context.Dr7;
754 }
755 }
756 else
757#endif
758 {
759 th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
760 CHECK (GetThreadContext (th->h, &th->context));
761 /* Copy dr values from that thread.
762 But only if there were not modified since last stop.
763 PR gdb/2388 */
765 {
766 windows_process.dr[0] = th->context.Dr0;
767 windows_process.dr[1] = th->context.Dr1;
768 windows_process.dr[2] = th->context.Dr2;
769 windows_process.dr[3] = th->context.Dr3;
770 windows_process.dr[6] = th->context.Dr6;
771 windows_process.dr[7] = th->context.Dr7;
772 }
773 }
774 th->reload_context = false;
775 }
776
777 if (r < 0)
778 for (r = 0; r < gdbarch_num_regs (regcache->arch()); r++)
780 else
782}
783
784/* Collect the register number R from the given regcache, and store
785 its value into the corresponding area of the given thread's context.
786
787 This function assumes that R is non-negative. A failed assertion
788 assertion is raised if that is not true. */
789
790static void
792 windows_thread_info *th, int r)
793{
794 gdb_assert (r >= 0);
795
796 char *context_ptr = (char *) &th->context;
797#ifdef __x86_64__
798 if (windows_process.wow64_process)
799 context_ptr = (char *) &th->wow64_context;
800#endif
801
802 regcache->raw_collect (r, context_ptr + windows_process.mappings[r]);
803}
804
805/* Store a new register value into the context of the thread tied to
806 REGCACHE. */
807
808void
810{
813
814 /* Check if TH exists. Windows sometimes uses a non-existent
815 thread id in its events. */
816 if (th == NULL)
817 return;
818
819 if (r < 0)
820 for (r = 0; r < gdbarch_num_regs (regcache->arch ()); r++)
822 else
824}
825
826/* See nat/windows-nat.h. */
827
828static windows_solib *
829windows_make_so (const char *name, LPVOID load_addr)
830{
831#ifndef __CYGWIN__
832 char *p;
833 char buf[__PMAX];
834 char cwd[__PMAX];
835 WIN32_FIND_DATA w32_fd;
836 HANDLE h = FindFirstFile(name, &w32_fd);
837
838 if (h == INVALID_HANDLE_VALUE)
839 strcpy (buf, name);
840 else
841 {
842 FindClose (h);
843 strcpy (buf, name);
844 if (GetCurrentDirectory (MAX_PATH + 1, cwd))
845 {
846 p = strrchr (buf, '\\');
847 if (p)
848 p[1] = '\0';
849 SetCurrentDirectory (buf);
850 GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
851 SetCurrentDirectory (cwd);
852 }
853 }
854 if (strcasecmp (buf, "ntdll.dll") == 0)
855 {
856 GetSystemDirectory (buf, sizeof (buf));
857 strcat (buf, "\\ntdll.dll");
858 }
859#else
860 wchar_t buf[__PMAX];
861
862 buf[0] = 0;
863 if (access (name, F_OK) != 0)
864 {
865 if (strcasecmp (name, "ntdll.dll") == 0)
866 {
867 GetSystemDirectoryW (buf, sizeof (buf) / sizeof (wchar_t));
868 wcscat (buf, L"\\ntdll.dll");
869 }
870 }
871#endif
872 windows_process.solibs.emplace_back ();
873 windows_solib *so = &windows_process.solibs.back ();
874 so->load_addr = load_addr;
875 so->original_name = name;
876#ifndef __CYGWIN__
877 so->name = buf;
878#else
879 if (buf[0])
880 {
881 char cname[SO_NAME_MAX_PATH_SIZE];
882 cygwin_conv_path (CCP_WIN_W_TO_POSIX, buf, cname,
884 so->name = cname;
885 }
886 else
887 {
888 char *rname = realpath (name, NULL);
889 if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
890 {
891 so->name = rname;
892 free (rname);
893 }
894 else
895 {
896 warning (_("dll path for \"%s\" too long or inaccessible"), name);
897 so->name = so->original_name;
898 }
899 }
900 /* Record cygwin1.dll .text start/end. */
901 size_t len = sizeof ("/cygwin1.dll") - 1;
902 if (so->name.size () >= len
903 && strcasecmp (so->name.c_str () + so->name.size () - len,
904 "/cygwin1.dll") == 0)
905 {
906 asection *text = NULL;
907
908 gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->name.c_str(), "pei-i386"));
909
910 if (abfd == NULL)
911 return so;
912
913 if (bfd_check_format (abfd.get (), bfd_object))
914 text = bfd_get_section_by_name (abfd.get (), ".text");
915
916 if (!text)
917 return so;
918
919 /* The symbols in a dll are offset by 0x1000, which is the
920 offset from 0 of the first byte in an image - because of the
921 file header and the section alignment. */
922 windows_process.cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
923 load_addr + 0x1000);
924 windows_process.cygwin_load_end = windows_process.cygwin_load_start +
925 bfd_section_size (text);
926 }
927#endif
928
929 return so;
930}
931
932/* See nat/windows-nat.h. */
933
934void
935windows_per_inferior::handle_load_dll (const char *dll_name, LPVOID base)
936{
937 windows_solib *solib = windows_make_so (dll_name, base);
938 DEBUG_EVENTS ("Loading dll \"%s\" at %s.", solib->name.c_str (),
939 host_address_to_string (solib->load_addr));
940}
941
942/* See nat/windows-nat.h. */
943
944void
946{
947 LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
948
949 auto iter = std::remove_if (windows_process.solibs.begin (),
950 windows_process.solibs.end (),
951 [&] (windows_solib &lib)
952 {
953 if (lib.load_addr == lpBaseOfDll)
954 {
955 DEBUG_EVENTS ("Unloading dll \"%s\".", lib.name.c_str ());
956 return true;
957 }
958 return false;
959 });
960
961 if (iter != windows_process.solibs.end ())
962 {
963 windows_process.solibs.erase (iter, windows_process.solibs.end ());
964 return;
965 }
966
967 /* We did not find any DLL that was previously loaded at this address,
968 so register a complaint. We do not report an error, because we have
969 observed that this may be happening under some circumstances. For
970 instance, running 32bit applications on x64 Windows causes us to receive
971 4 mysterious UNLOAD_DLL_DEBUG_EVENTs during the startup phase (these
972 events are apparently caused by the WOW layer, the interface between
973 32bit and 64bit worlds). */
974 complaint (_("dll starting at %s not found."),
975 host_address_to_string (lpBaseOfDll));
976}
977
978/* Clear list of loaded DLLs. */
979static void
981{
982 windows_process.solibs.clear ();
983}
984
985static void
986signal_event_command (const char *args, int from_tty)
987{
988 uintptr_t event_id = 0;
989 char *endargs = NULL;
990
991 if (args == NULL)
992 error (_("signal-event requires an argument (integer event id)"));
993
994 event_id = strtoumax (args, &endargs, 10);
995
996 if ((errno == ERANGE) || (event_id == 0) || (event_id > UINTPTR_MAX) ||
997 ((HANDLE) event_id == INVALID_HANDLE_VALUE))
998 error (_("Failed to convert `%s' to event id"), args);
999
1000 SetEvent ((HANDLE) event_id);
1001 CloseHandle ((HANDLE) event_id);
1002}
1003
1004/* See nat/windows-nat.h. */
1005
1006int
1008 (struct target_waitstatus *ourstatus)
1009{
1010 int retval = 0;
1011
1012 gdb::unique_xmalloc_ptr<char> s
1014 ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
1015 1024));
1016 if (s == nullptr || !*(s.get ()))
1017 /* nothing to do */;
1018 else if (!startswith (s.get (), _CYGWIN_SIGNAL_STRING))
1019 {
1020#ifdef __CYGWIN__
1021 if (!startswith (s.get (), "cYg"))
1022#endif
1023 {
1024 char *p = strchr (s.get (), '\0');
1025
1026 if (p > s.get () && *--p == '\n')
1027 *p = '\0';
1028 warning (("%s"), s.get ());
1029 }
1030 }
1031#ifdef __CYGWIN__
1032 else
1033 {
1034 /* Got a cygwin signal marker. A cygwin signal is followed by
1035 the signal number itself and then optionally followed by the
1036 thread id and address to saved context within the DLL. If
1037 these are supplied, then the given thread is assumed to have
1038 issued the signal and the context from the thread is assumed
1039 to be stored at the given address in the inferior. Tell gdb
1040 to treat this like a real signal. */
1041 char *p;
1042 int sig = strtol (s.get () + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
1043 gdb_signal gotasig = gdb_signal_from_host (sig);
1044
1045 if (gotasig)
1046 {
1047 LPCVOID x;
1048 SIZE_T n;
1049
1050 ourstatus->set_stopped (gotasig);
1051 retval = strtoul (p, &p, 0);
1052 if (!retval)
1053 retval = current_event.dwThreadId;
1054 else if ((x = (LPCVOID) (uintptr_t) strtoull (p, NULL, 0))
1055 && ReadProcessMemory (handle, x,
1056 &saved_context,
1057 __COPY_CONTEXT_SIZE, &n)
1058 && n == __COPY_CONTEXT_SIZE)
1060 }
1061 }
1062#endif
1063
1064 return retval;
1065}
1066
1067static int
1068display_selector (HANDLE thread, DWORD sel)
1069{
1070 LDT_ENTRY info;
1071 BOOL ret;
1072#ifdef __x86_64__
1073 if (windows_process.wow64_process)
1074 ret = Wow64GetThreadSelectorEntry (thread, sel, &info);
1075 else
1076#endif
1077 ret = GetThreadSelectorEntry (thread, sel, &info);
1078 if (ret)
1079 {
1080 int base, limit;
1081 gdb_printf ("0x%03x: ", (unsigned) sel);
1082 if (!info.HighWord.Bits.Pres)
1083 {
1084 gdb_puts ("Segment not present\n");
1085 return 0;
1086 }
1087 base = (info.HighWord.Bits.BaseHi << 24) +
1088 (info.HighWord.Bits.BaseMid << 16)
1089 + info.BaseLow;
1090 limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow;
1091 if (info.HighWord.Bits.Granularity)
1092 limit = (limit << 12) | 0xfff;
1093 gdb_printf ("base=0x%08x limit=0x%08x", base, limit);
1094 if (info.HighWord.Bits.Default_Big)
1095 gdb_puts(" 32-bit ");
1096 else
1097 gdb_puts(" 16-bit ");
1098 switch ((info.HighWord.Bits.Type & 0xf) >> 1)
1099 {
1100 case 0:
1101 gdb_puts ("Data (Read-Only, Exp-up");
1102 break;
1103 case 1:
1104 gdb_puts ("Data (Read/Write, Exp-up");
1105 break;
1106 case 2:
1107 gdb_puts ("Unused segment (");
1108 break;
1109 case 3:
1110 gdb_puts ("Data (Read/Write, Exp-down");
1111 break;
1112 case 4:
1113 gdb_puts ("Code (Exec-Only, N.Conf");
1114 break;
1115 case 5:
1116 gdb_puts ("Code (Exec/Read, N.Conf");
1117 break;
1118 case 6:
1119 gdb_puts ("Code (Exec-Only, Conf");
1120 break;
1121 case 7:
1122 gdb_puts ("Code (Exec/Read, Conf");
1123 break;
1124 default:
1125 gdb_printf ("Unknown type 0x%lx",
1126 (unsigned long) info.HighWord.Bits.Type);
1127 }
1128 if ((info.HighWord.Bits.Type & 0x1) == 0)
1129 gdb_puts(", N.Acc");
1130 gdb_puts (")\n");
1131 if ((info.HighWord.Bits.Type & 0x10) == 0)
1132 gdb_puts("System selector ");
1133 gdb_printf ("Privilege level = %ld. ",
1134 (unsigned long) info.HighWord.Bits.Dpl);
1135 if (info.HighWord.Bits.Granularity)
1136 gdb_puts ("Page granular.\n");
1137 else
1138 gdb_puts ("Byte granular.\n");
1139 return 1;
1140 }
1141 else
1142 {
1143 DWORD err = GetLastError ();
1144 if (err == ERROR_NOT_SUPPORTED)
1145 gdb_printf ("Function not supported\n");
1146 else
1147 gdb_printf ("Invalid selector 0x%x.\n", (unsigned) sel);
1148 return 0;
1149 }
1150}
1151
1152static void
1153display_selectors (const char * args, int from_tty)
1154{
1155 if (inferior_ptid == null_ptid)
1156 {
1157 gdb_puts ("Impossible to display selectors now.\n");
1158 return;
1159 }
1160
1161 windows_thread_info *current_windows_thread
1163
1164 if (!args)
1165 {
1166#ifdef __x86_64__
1167 if (windows_process.wow64_process)
1168 {
1169 gdb_puts ("Selector $cs\n");
1170 display_selector (current_windows_thread->h,
1171 current_windows_thread->wow64_context.SegCs);
1172 gdb_puts ("Selector $ds\n");
1173 display_selector (current_windows_thread->h,
1174 current_windows_thread->wow64_context.SegDs);
1175 gdb_puts ("Selector $es\n");
1176 display_selector (current_windows_thread->h,
1177 current_windows_thread->wow64_context.SegEs);
1178 gdb_puts ("Selector $ss\n");
1179 display_selector (current_windows_thread->h,
1180 current_windows_thread->wow64_context.SegSs);
1181 gdb_puts ("Selector $fs\n");
1182 display_selector (current_windows_thread->h,
1183 current_windows_thread->wow64_context.SegFs);
1184 gdb_puts ("Selector $gs\n");
1185 display_selector (current_windows_thread->h,
1186 current_windows_thread->wow64_context.SegGs);
1187 }
1188 else
1189#endif
1190 {
1191 gdb_puts ("Selector $cs\n");
1192 display_selector (current_windows_thread->h,
1193 current_windows_thread->context.SegCs);
1194 gdb_puts ("Selector $ds\n");
1195 display_selector (current_windows_thread->h,
1196 current_windows_thread->context.SegDs);
1197 gdb_puts ("Selector $es\n");
1198 display_selector (current_windows_thread->h,
1199 current_windows_thread->context.SegEs);
1200 gdb_puts ("Selector $ss\n");
1201 display_selector (current_windows_thread->h,
1202 current_windows_thread->context.SegSs);
1203 gdb_puts ("Selector $fs\n");
1204 display_selector (current_windows_thread->h,
1205 current_windows_thread->context.SegFs);
1206 gdb_puts ("Selector $gs\n");
1207 display_selector (current_windows_thread->h,
1208 current_windows_thread->context.SegGs);
1209 }
1210 }
1211 else
1212 {
1213 int sel;
1214 sel = parse_and_eval_long (args);
1215 gdb_printf ("Selector \"%s\"\n",args);
1216 display_selector (current_windows_thread->h, sel);
1217 }
1218}
1219
1220/* See nat/windows-nat.h. */
1221
1222bool
1224 (const EXCEPTION_RECORD *rec)
1225{
1226#ifdef __CYGWIN__
1227 /* See if the access violation happened within the cygwin DLL
1228 itself. Cygwin uses a kind of exception handling to deal with
1229 passed-in invalid addresses. gdb should not treat these as real
1230 SEGVs since they will be silently handled by cygwin. A real SEGV
1231 will (theoretically) be caught by cygwin later in the process and
1232 will be sent as a cygwin-specific-signal. So, ignore SEGVs if
1233 they show up within the text segment of the DLL itself. */
1234 const char *fn;
1235 CORE_ADDR addr = (CORE_ADDR) (uintptr_t) rec->ExceptionAddress;
1236
1237 if ((!cygwin_exceptions && (addr >= cygwin_load_start
1238 && addr < cygwin_load_end))
1239 || (find_pc_partial_function (addr, &fn, NULL, NULL)
1240 && startswith (fn, "KERNEL32!IsBad")))
1241 return true;
1242#endif
1243 return false;
1244}
1245
1246/* Resume thread specified by ID, or all artificially suspended
1247 threads, if we are continuing execution. KILLED non-zero means we
1248 have killed the inferior, so we should ignore weird errors due to
1249 threads shutting down. LAST_CALL is true if we expect this to be
1250 the last call to continue the inferior -- we are either mourning it
1251 or detaching. */
1252BOOL
1253windows_nat_target::windows_continue (DWORD continue_status, int id,
1254 int killed, bool last_call)
1255{
1257
1259 {
1260 /* There's no need to really continue, because there's already
1261 another event pending. However, we do need to inform the
1262 event loop of this. */
1264 return TRUE;
1265 }
1266
1267 for (auto &th : windows_process.thread_list)
1268 if (id == -1 || id == (int) th->tid)
1269 {
1270#ifdef __x86_64__
1271 if (windows_process.wow64_process)
1272 {
1273 if (th->debug_registers_changed)
1274 {
1275 th->wow64_context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
1276 th->wow64_context.Dr0 = windows_process.dr[0];
1277 th->wow64_context.Dr1 = windows_process.dr[1];
1278 th->wow64_context.Dr2 = windows_process.dr[2];
1279 th->wow64_context.Dr3 = windows_process.dr[3];
1280 th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
1281 th->wow64_context.Dr7 = windows_process.dr[7];
1282 th->debug_registers_changed = false;
1283 }
1284 if (th->wow64_context.ContextFlags)
1285 {
1286 DWORD ec = 0;
1287
1288 if (GetExitCodeThread (th->h, &ec)
1289 && ec == STILL_ACTIVE)
1290 {
1292 &th->wow64_context);
1293
1294 if (!killed)
1295 CHECK (status);
1296 }
1297 th->wow64_context.ContextFlags = 0;
1298 }
1299 }
1300 else
1301#endif
1302 {
1303 if (th->debug_registers_changed)
1304 {
1305 th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
1306 th->context.Dr0 = windows_process.dr[0];
1307 th->context.Dr1 = windows_process.dr[1];
1308 th->context.Dr2 = windows_process.dr[2];
1309 th->context.Dr3 = windows_process.dr[3];
1310 th->context.Dr6 = DR6_CLEAR_VALUE;
1311 th->context.Dr7 = windows_process.dr[7];
1312 th->debug_registers_changed = false;
1313 }
1314 if (th->context.ContextFlags)
1315 {
1316 DWORD ec = 0;
1317
1318 if (GetExitCodeThread (th->h, &ec)
1319 && ec == STILL_ACTIVE)
1320 {
1321 BOOL status = SetThreadContext (th->h, &th->context);
1322
1323 if (!killed)
1324 CHECK (status);
1325 }
1326 th->context.ContextFlags = 0;
1327 }
1328 }
1329 th->resume ();
1330 }
1331 else
1332 {
1333 /* When single-stepping a specific thread, other threads must
1334 be suspended. */
1335 th->suspend ();
1336 }
1337
1338 gdb::optional<unsigned> err;
1339 do_synchronously ([&] ()
1340 {
1341 if (!continue_last_debug_event (continue_status, debug_events))
1342 err = (unsigned) GetLastError ();
1343 /* On the last call, do not block waiting for an event that will
1344 never come. */
1345 return !last_call;
1346 });
1347
1348 if (err.has_value ())
1349 error (_("Failed to resume program execution"
1350 " (ContinueDebugEvent failed, error %u: %s)"),
1351 *err, strwinerror (*err));
1352
1353 return TRUE;
1354}
1355
1356/* Called in pathological case where Windows fails to send a
1357 CREATE_PROCESS_DEBUG_EVENT after an attach. */
1358DWORD
1360{
1362 = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
1363 windows_process.current_event.dwProcessId);
1364 if (windows_process.handle != NULL)
1366 else
1367 {
1368 unsigned err = (unsigned) GetLastError ();
1369 error (_("OpenProcess call failed, GetLastError = %u: %s"),
1370 err, strwinerror (err));
1371 /* We can not debug anything in that case. */
1372 }
1373 add_thread (ptid_t (windows_process.current_event.dwProcessId, 0,
1374 windows_process.current_event.dwThreadId),
1375 windows_process.current_event.u.CreateThread.hThread,
1376 windows_process.current_event.u.CreateThread.lpThreadLocalBase,
1377 true /* main_thread_p */);
1378 return windows_process.current_event.dwThreadId;
1379}
1380
1381void
1382windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
1383{
1385 DWORD continue_status = DBG_CONTINUE;
1386
1387 /* A specific PTID means `step only this thread id'. */
1388 int resume_all = ptid == minus_one_ptid;
1389
1390 /* If we're continuing all threads, it's the current inferior that
1391 should be handled specially. */
1392 if (resume_all)
1393 ptid = inferior_ptid;
1394
1395 if (sig != GDB_SIGNAL_0)
1396 {
1397 if (windows_process.current_event.dwDebugEventCode
1398 != EXCEPTION_DEBUG_EVENT)
1399 {
1400 DEBUG_EXCEPT ("Cannot continue with signal %d here.", sig);
1401 }
1402 else if (sig == windows_process.last_sig)
1403 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1404 else
1405#if 0
1406/* This code does not seem to work, because
1407 the kernel does probably not consider changes in the ExceptionRecord
1408 structure when passing the exception to the inferior.
1409 Note that this seems possible in the exception handler itself. */
1410 {
1411 for (const xlate_exception &x : xlate)
1412 if (x.us == sig)
1413 {
1414 current_event.u.Exception.ExceptionRecord.ExceptionCode
1415 = x.them;
1416 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1417 break;
1418 }
1419 if (continue_status == DBG_CONTINUE)
1420 {
1421 DEBUG_EXCEPT ("Cannot continue with signal %d.", sig);
1422 }
1423 }
1424#endif
1425 DEBUG_EXCEPT ("Can only continue with received signal %d.",
1427 }
1428
1429 windows_process.last_sig = GDB_SIGNAL_0;
1430
1431 DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
1432 ptid.pid (), (unsigned) ptid.lwp (), step, sig);
1433
1434 /* Get context for currently selected thread. */
1436 if (th)
1437 {
1438#ifdef __x86_64__
1439 if (windows_process.wow64_process)
1440 {
1441 if (step)
1442 {
1443 /* Single step by setting t bit. */
1445 struct gdbarch *gdbarch = regcache->arch ();
1447 th->wow64_context.EFlags |= FLAG_TRACE_BIT;
1448 }
1449
1450 if (th->wow64_context.ContextFlags)
1451 {
1453 {
1454 th->wow64_context.Dr0 = windows_process.dr[0];
1455 th->wow64_context.Dr1 = windows_process.dr[1];
1456 th->wow64_context.Dr2 = windows_process.dr[2];
1457 th->wow64_context.Dr3 = windows_process.dr[3];
1458 th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
1459 th->wow64_context.Dr7 = windows_process.dr[7];
1460 th->debug_registers_changed = false;
1461 }
1462 CHECK (Wow64SetThreadContext (th->h, &th->wow64_context));
1463 th->wow64_context.ContextFlags = 0;
1464 }
1465 }
1466 else
1467#endif
1468 {
1469 if (step)
1470 {
1471 /* Single step by setting t bit. */
1473 struct gdbarch *gdbarch = regcache->arch ();
1475 th->context.EFlags |= FLAG_TRACE_BIT;
1476 }
1477
1478 if (th->context.ContextFlags)
1479 {
1481 {
1482 th->context.Dr0 = windows_process.dr[0];
1483 th->context.Dr1 = windows_process.dr[1];
1484 th->context.Dr2 = windows_process.dr[2];
1485 th->context.Dr3 = windows_process.dr[3];
1486 th->context.Dr6 = DR6_CLEAR_VALUE;
1487 th->context.Dr7 = windows_process.dr[7];
1488 th->debug_registers_changed = false;
1489 }
1490 CHECK (SetThreadContext (th->h, &th->context));
1491 th->context.ContextFlags = 0;
1492 }
1493 }
1494 }
1495
1496 /* Allow continuing with the same signal that interrupted us.
1497 Otherwise complain. */
1498
1499 if (resume_all)
1500 windows_continue (continue_status, -1, 0);
1501 else
1502 windows_continue (continue_status, ptid.lwp (), 0);
1503}
1504
1505/* Interrupt the inferior. */
1506
1507void
1509{
1510 DEBUG_EVENTS ("interrupt");
1511#ifdef __x86_64__
1512 if (windows_process.wow64_process)
1513 {
1514 /* Call DbgUiRemoteBreakin of the 32bit ntdll.dll in the target process.
1515 DebugBreakProcess would call the one of the 64bit ntdll.dll, which
1516 can't be correctly handled by gdb. */
1517 if (windows_process.wow64_dbgbreak == nullptr)
1518 {
1519 CORE_ADDR addr;
1520 if (!find_minimal_symbol_address ("ntdll!DbgUiRemoteBreakin",
1521 &addr, 0))
1522 windows_process.wow64_dbgbreak = (void *) addr;
1523 }
1524
1525 if (windows_process.wow64_dbgbreak != nullptr)
1526 {
1527 HANDLE thread = CreateRemoteThread (windows_process.handle, NULL,
1528 0, (LPTHREAD_START_ROUTINE)
1529 windows_process.wow64_dbgbreak,
1530 NULL, 0, NULL);
1531 if (thread)
1532 {
1533 CloseHandle (thread);
1534 return;
1535 }
1536 }
1537 }
1538 else
1539#endif
1541 return;
1542 warning (_("Could not interrupt program. "
1543 "Press Ctrl-c in the program console."));
1544}
1545
1546void
1551
1552/* Get the next event from the child. Returns the thread ptid. */
1553
1554ptid_t
1556 (int pid, struct target_waitstatus *ourstatus, target_wait_flags options)
1557{
1558 DWORD continue_status, event_code;
1559 DWORD thread_id = 0;
1560
1561 /* If there is a relevant pending stop, report it now. See the
1562 comment by the definition of "pending_stops" for details on why
1563 this is needed. */
1564 gdb::optional<pending_stop> stop
1566 if (stop.has_value ())
1567 {
1568 thread_id = stop->thread_id;
1569 *ourstatus = stop->status;
1570
1571 ptid_t ptid (windows_process.current_event.dwProcessId, thread_id);
1574 th->reload_context = true;
1575
1576 return ptid;
1577 }
1578
1579 windows_process.last_sig = GDB_SIGNAL_0;
1580 DEBUG_EVENT *current_event = &windows_process.current_event;
1581
1582 if ((options & TARGET_WNOHANG) != 0 && !m_debug_event_pending)
1583 {
1584 ourstatus->set_ignore ();
1585 return minus_one_ptid;
1586 }
1587
1589
1590 continue_status = DBG_CONTINUE;
1591
1592 event_code = windows_process.current_event.dwDebugEventCode;
1593 ourstatus->set_spurious ();
1595
1596 switch (event_code)
1597 {
1598 case CREATE_THREAD_DEBUG_EVENT:
1599 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1600 (unsigned) current_event->dwProcessId,
1601 (unsigned) current_event->dwThreadId,
1602 "CREATE_THREAD_DEBUG_EVENT");
1603 if (windows_process.saw_create != 1)
1604 {
1605 inferior *inf = find_inferior_pid (this, current_event->dwProcessId);
1606 if (!windows_process.saw_create && inf->attach_flag)
1607 {
1608 /* Kludge around a Windows bug where first event is a create
1609 thread event. Caused when attached process does not have
1610 a main thread. */
1611 thread_id = fake_create_process ();
1612 if (thread_id)
1614 }
1615 break;
1616 }
1617 /* Record the existence of this thread. */
1618 thread_id = current_event->dwThreadId;
1620 (ptid_t (current_event->dwProcessId, current_event->dwThreadId, 0),
1621 current_event->u.CreateThread.hThread,
1622 current_event->u.CreateThread.lpThreadLocalBase,
1623 false /* main_thread_p */);
1624
1625 break;
1626
1627 case EXIT_THREAD_DEBUG_EVENT:
1628 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1629 (unsigned) current_event->dwProcessId,
1630 (unsigned) current_event->dwThreadId,
1631 "EXIT_THREAD_DEBUG_EVENT");
1632 delete_thread (ptid_t (current_event->dwProcessId,
1633 current_event->dwThreadId, 0),
1634 current_event->u.ExitThread.dwExitCode,
1635 false /* main_thread_p */);
1636 break;
1637
1638 case CREATE_PROCESS_DEBUG_EVENT:
1639 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1640 (unsigned) current_event->dwProcessId,
1641 (unsigned) current_event->dwThreadId,
1642 "CREATE_PROCESS_DEBUG_EVENT");
1643 CloseHandle (current_event->u.CreateProcessInfo.hFile);
1644 if (++windows_process.saw_create != 1)
1645 break;
1646
1647 windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
1648 /* Add the main thread. */
1650 (ptid_t (current_event->dwProcessId,
1651 current_event->dwThreadId, 0),
1652 current_event->u.CreateProcessInfo.hThread,
1653 current_event->u.CreateProcessInfo.lpThreadLocalBase,
1654 true /* main_thread_p */);
1655 thread_id = current_event->dwThreadId;
1656 break;
1657
1658 case EXIT_PROCESS_DEBUG_EVENT:
1659 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1660 (unsigned) current_event->dwProcessId,
1661 (unsigned) current_event->dwThreadId,
1662 "EXIT_PROCESS_DEBUG_EVENT");
1664 {
1667 error (_("During startup program exited with code 0x%x."),
1668 (unsigned int) current_event->u.ExitProcess.dwExitCode);
1669 }
1670 else if (windows_process.saw_create == 1)
1671 {
1672 delete_thread (ptid_t (current_event->dwProcessId,
1673 current_event->dwThreadId, 0),
1674 0, true /* main_thread_p */);
1675 DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
1676 /* If the exit status looks like a fatal exception, but we
1677 don't recognize the exception's code, make the original
1678 exit status value available, to avoid losing
1679 information. */
1680 int exit_signal
1681 = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
1682 if (exit_signal == -1)
1683 ourstatus->set_exited (exit_status);
1684 else
1685 ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
1686
1687 thread_id = current_event->dwThreadId;
1688 }
1689 break;
1690
1691 case LOAD_DLL_DEBUG_EVENT:
1692 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1693 (unsigned) current_event->dwProcessId,
1694 (unsigned) current_event->dwThreadId,
1695 "LOAD_DLL_DEBUG_EVENT");
1696 CloseHandle (current_event->u.LoadDll.hFile);
1699 break;
1700 try
1701 {
1703 }
1704 catch (const gdb_exception &ex)
1705 {
1707 }
1708 ourstatus->set_loaded ();
1709 thread_id = current_event->dwThreadId;
1710 break;
1711
1712 case UNLOAD_DLL_DEBUG_EVENT:
1713 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1714 (unsigned) current_event->dwProcessId,
1715 (unsigned) current_event->dwThreadId,
1716 "UNLOAD_DLL_DEBUG_EVENT");
1719 break;
1720 try
1721 {
1723 }
1724 catch (const gdb_exception &ex)
1725 {
1727 }
1728 ourstatus->set_loaded ();
1729 thread_id = current_event->dwThreadId;
1730 break;
1731
1732 case EXCEPTION_DEBUG_EVENT:
1733 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1734 (unsigned) current_event->dwProcessId,
1735 (unsigned) current_event->dwThreadId,
1736 "EXCEPTION_DEBUG_EVENT");
1737 if (windows_process.saw_create != 1)
1738 break;
1740 {
1742 default:
1743 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1744 break;
1746 thread_id = current_event->dwThreadId;
1747 break;
1749 continue_status = DBG_CONTINUE;
1750 break;
1751 }
1752 break;
1753
1754 case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
1755 DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
1756 (unsigned) current_event->dwProcessId,
1757 (unsigned) current_event->dwThreadId,
1758 "OUTPUT_DEBUG_STRING_EVENT");
1759 if (windows_process.saw_create != 1)
1760 break;
1761 thread_id = windows_process.handle_output_debug_string (ourstatus);
1762 break;
1763
1764 default:
1765 if (windows_process.saw_create != 1)
1766 break;
1767 gdb_printf ("gdb: kernel event for pid=%u tid=0x%x\n",
1768 (unsigned) current_event->dwProcessId,
1769 (unsigned) current_event->dwThreadId);
1770 gdb_printf (" unknown event code %u\n",
1771 (unsigned) current_event->dwDebugEventCode);
1772 break;
1773 }
1774
1775 if (!thread_id || windows_process.saw_create != 1)
1776 {
1777 CHECK (windows_continue (continue_status,
1779 }
1782 {
1783 /* Pending stop. See the comment by the definition of
1784 "pending_stops" for details on why this is needed. */
1785 DEBUG_EVENTS ("get_windows_debug_event - "
1786 "unexpected stop in 0x%x (expecting 0x%x)",
1788
1789 if (current_event->dwDebugEventCode == EXCEPTION_DEBUG_EVENT
1790 && ((current_event->u.Exception.ExceptionRecord.ExceptionCode
1791 == EXCEPTION_BREAKPOINT)
1792 || (current_event->u.Exception.ExceptionRecord.ExceptionCode
1795 {
1796 ptid_t ptid = ptid_t (current_event->dwProcessId, thread_id, 0);
1800 th->pc_adjusted = false;
1801 }
1803 ({thread_id, *ourstatus, windows_process.current_event});
1804 thread_id = 0;
1805 CHECK (windows_continue (continue_status,
1807 }
1808
1809 if (thread_id == 0)
1810 return null_ptid;
1811 return ptid_t (windows_process.current_event.dwProcessId, thread_id, 0);
1812}
1813
1814/* Wait for interesting events to occur in the target process. */
1815ptid_t
1816windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
1817 target_wait_flags options)
1818{
1819 int pid = -1;
1820
1821 /* We loop when we get a non-standard exception rather than return
1822 with a SPURIOUS because resume can try and step or modify things,
1823 which needs a current_thread->h. But some of these exceptions mark
1824 the birth or death of threads, which mean that the current thread
1825 isn't necessarily what you think it is. */
1826
1827 while (1)
1828 {
1829 ptid_t result = get_windows_debug_event (pid, ourstatus, options);
1830
1831 if (result != null_ptid)
1832 {
1833 if (ourstatus->kind () != TARGET_WAITKIND_EXITED
1834 && ourstatus->kind () != TARGET_WAITKIND_SIGNALLED)
1835 {
1838
1839 if (th != nullptr)
1840 {
1842 if (windows_process.current_event.dwDebugEventCode
1843 == EXCEPTION_DEBUG_EVENT
1844 && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
1845 == EXCEPTION_BREAKPOINT)
1846 || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
1849 {
1851 th->pc_adjusted = false;
1852 }
1853 }
1854 }
1855
1856 return result;
1857 }
1858 else
1859 {
1860 int detach = 0;
1861
1862 if (deprecated_ui_loop_hook != NULL)
1864
1865 if (detach)
1866 kill ();
1867 }
1868 }
1869}
1870
1871void
1873{
1874 int i;
1875 struct inferior *inf;
1876
1877 windows_process.last_sig = GDB_SIGNAL_0;
1879 for (i = 0;
1880 i < sizeof (windows_process.dr) / sizeof (windows_process.dr[0]);
1881 i++)
1882 windows_process.dr[i] = 0;
1883#ifdef __CYGWIN__
1884 windows_process.cygwin_load_start = 0;
1885 windows_process.cygwin_load_end = 0;
1886#endif
1887 windows_process.current_event.dwProcessId = pid;
1888 memset (&windows_process.current_event, 0,
1890 inf = current_inferior ();
1891 if (!inf->target_is_pushed (this))
1892 inf->push_target (this);
1897
1898#ifdef __x86_64__
1899 windows_process.ignore_first_breakpoint
1900 = !attaching && windows_process.wow64_process;
1901
1902 if (!windows_process.wow64_process)
1903 {
1906 }
1907 else
1908#endif
1909 {
1912 }
1913
1915 inf->attach_flag = attaching;
1916
1919
1921
1922 ptid_t last_ptid;
1923
1924 while (1)
1925 {
1927
1928 last_ptid = this->wait (minus_one_ptid, &status, 0);
1929
1930 /* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread
1931 events. */
1932 if (status.kind () != TARGET_WAITKIND_LOADED
1933 && status.kind () != TARGET_WAITKIND_SPURIOUS)
1934 break;
1935
1936 this->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
1937 }
1938
1939 switch_to_thread (this->find_thread (last_ptid));
1940
1941 /* Now that the inferior has been started and all DLLs have been mapped,
1942 we can iterate over all DLLs and load them in.
1943
1944 We avoid doing it any earlier because, on certain versions of Windows,
1945 LOAD_DLL_DEBUG_EVENTs are sometimes not complete. In particular,
1946 we have seen on Windows 8.1 that the ntdll.dll load event does not
1947 include the DLL name, preventing us from creating an associated SO.
1948 A possible explanation is that ntdll.dll might be mapped before
1949 the SO info gets created by the Windows system -- ntdll.dll is
1950 the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs
1951 do not seem to suffer from that problem.
1952
1953 Rather than try to work around this sort of issue, it is much
1954 simpler to just ignore DLL load/unload events during the startup
1955 phase, and then process them all in one batch now. */
1957
1959 return;
1960}
1961
1962/* Try to set or remove a user privilege to the current process. Return -1
1963 if that fails, the previous setting of that privilege otherwise.
1964
1965 This code is copied from the Cygwin source code and rearranged to allow
1966 dynamically loading of the needed symbols from advapi32 which is only
1967 available on NT/2K/XP. */
1968static int
1969set_process_privilege (const char *privilege, BOOL enable)
1970{
1971 HANDLE token_hdl = NULL;
1972 LUID restore_priv;
1973 TOKEN_PRIVILEGES new_priv, orig_priv;
1974 int ret = -1;
1975 DWORD size;
1976
1977 if (!OpenProcessToken (GetCurrentProcess (),
1978 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
1979 &token_hdl))
1980 goto out;
1981
1982 if (!LookupPrivilegeValueA (NULL, privilege, &restore_priv))
1983 goto out;
1984
1985 new_priv.PrivilegeCount = 1;
1986 new_priv.Privileges[0].Luid = restore_priv;
1987 new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
1988
1989 if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv,
1990 sizeof orig_priv, &orig_priv, &size))
1991 goto out;
1992#if 0
1993 /* Disabled, otherwise every `attach' in an unprivileged user session
1994 would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
1995 windows_attach(). */
1996 /* AdjustTokenPrivileges returns TRUE even if the privilege could not
1997 be enabled. GetLastError () returns an correct error code, though. */
1998 if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
1999 goto out;
2000#endif
2001
2002 ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
2003
2004out:
2005 if (token_hdl)
2006 CloseHandle (token_hdl);
2007
2008 return ret;
2009}
2010
2011/* Attach to process PID, then initialize for debugging it. */
2012
2013void
2014windows_nat_target::attach (const char *args, int from_tty)
2015{
2016 DWORD pid;
2017
2018 pid = parse_pid_to_attach (args);
2019
2020 if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
2021 warning ("Failed to get SE_DEBUG_NAME privilege\n"
2022 "This can cause attach to fail on Windows NT/2K/XP");
2023
2026
2027 gdb::optional<unsigned> err;
2028 do_synchronously ([&] ()
2029 {
2030 BOOL ok = DebugActiveProcess (pid);
2031
2032#ifdef __CYGWIN__
2033 if (!ok)
2034 {
2035 /* Try fall back to Cygwin pid. */
2036 pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
2037
2038 if (pid > 0)
2039 ok = DebugActiveProcess (pid);
2040 }
2041#endif
2042
2043 if (!ok)
2044 err = (unsigned) GetLastError ();
2045
2046 return true;
2047 });
2048
2049 if (err.has_value ())
2050 error (_("Can't attach to process %u (error %u: %s)"),
2051 (unsigned) pid, *err, strwinerror (*err));
2052
2054
2055 target_announce_attach (from_tty, pid);
2056
2057#ifdef __x86_64__
2058 HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
2059 if (h != NULL)
2060 {
2061 BOOL wow64;
2062 if (IsWow64Process (h, &wow64))
2063 windows_process.wow64_process = wow64;
2064 CloseHandle (h);
2065 }
2066#endif
2067
2070}
2071
2072void
2074{
2075 windows_continue (DBG_CONTINUE, -1, 0, true);
2076
2077 gdb::optional<unsigned> err;
2078 do_synchronously ([&] ()
2079 {
2081 err = (unsigned) GetLastError ();
2082 else
2084 return false;
2085 });
2086
2087 if (err.has_value ())
2088 error (_("Can't detach process %u (error %u: %s)"),
2089 (unsigned) windows_process.current_event.dwProcessId,
2090 *err, strwinerror (*err));
2091
2092 target_announce_detach (from_tty);
2093
2097
2099}
2100
2101/* The pid_to_exec_file target_ops method for this platform. */
2102
2103const char *
2108
2109/* Print status information about what we're accessing. */
2110
2111void
2113{
2114 struct inferior *inf = current_inferior ();
2115
2116 gdb_printf ("\tUsing the running image of %s %s.\n",
2117 inf->attach_flag ? "attached" : "child",
2118 target_pid_to_str (ptid_t (inf->pid)).c_str ());
2119}
2120
2121/* Modify CreateProcess parameters for use of a new separate console.
2122 Parameters are:
2123 *FLAGS: DWORD parameter for general process creation flags.
2124 *SI: STARTUPINFO structure, for which the console window size and
2125 console buffer size is filled in if GDB is running in a console.
2126 to create the new console.
2127 The size of the used font is not available on all versions of
2128 Windows OS. Furthermore, the current font might not be the default
2129 font, but this is still better than before.
2130 If the windows and buffer sizes are computed,
2131 SI->DWFLAGS is changed so that this information is used
2132 by CreateProcess function. */
2133
2134static void
2136{
2137 HANDLE hconsole = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
2138 FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2139
2140 if (hconsole != INVALID_HANDLE_VALUE)
2141 {
2142 CONSOLE_SCREEN_BUFFER_INFO sbinfo;
2143 COORD font_size;
2144 CONSOLE_FONT_INFO cfi;
2145
2146 GetCurrentConsoleFont (hconsole, FALSE, &cfi);
2147 font_size = GetConsoleFontSize (hconsole, cfi.nFont);
2148 GetConsoleScreenBufferInfo(hconsole, &sbinfo);
2149 si->dwXSize = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
2150 si->dwYSize = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
2151 if (font_size.X)
2152 si->dwXSize *= font_size.X;
2153 else
2154 si->dwXSize *= 8;
2155 if (font_size.Y)
2156 si->dwYSize *= font_size.Y;
2157 else
2158 si->dwYSize *= 12;
2159 si->dwXCountChars = sbinfo.dwSize.X;
2160 si->dwYCountChars = sbinfo.dwSize.Y;
2161 si->dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS;
2162 }
2163 *flags |= CREATE_NEW_CONSOLE;
2164}
2165
2166#ifndef __CYGWIN__
2167/* Function called by qsort to sort environment strings. */
2168
2169static int
2170envvar_cmp (const void *a, const void *b)
2171{
2172 const char **p = (const char **) a;
2173 const char **q = (const char **) b;
2174 return strcasecmp (*p, *q);
2175}
2176#endif
2177
2178#ifdef __CYGWIN__
2179static void
2180clear_win32_environment (char **env)
2181{
2182 int i;
2183 size_t len;
2184 wchar_t *copy = NULL, *equalpos;
2185
2186 for (i = 0; env[i] && *env[i]; i++)
2187 {
2188 len = mbstowcs (NULL, env[i], 0) + 1;
2189 copy = (wchar_t *) xrealloc (copy, len * sizeof (wchar_t));
2190 mbstowcs (copy, env[i], len);
2191 equalpos = wcschr (copy, L'=');
2192 if (equalpos)
2193 *equalpos = L'\0';
2194 SetEnvironmentVariableW (copy, NULL);
2195 }
2196 xfree (copy);
2197}
2198#endif
2199
2200#ifndef __CYGWIN__
2201
2202/* Redirection of inferior I/O streams for native MS-Windows programs.
2203 Unlike on Unix, where this is handled by invoking the inferior via
2204 the shell, on MS-Windows we need to emulate the cmd.exe shell.
2205
2206 The official documentation of the cmd.exe redirection features is here:
2207
2208 http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx
2209
2210 (That page talks about Windows XP, but there's no newer
2211 documentation, so we assume later versions of cmd.exe didn't change
2212 anything.)
2213
2214 Caveat: the documentation on that page seems to include a few lies.
2215 For example, it describes strange constructs 1<&2 and 2<&1, which
2216 seem to work only when 1>&2 resp. 2>&1 would make sense, and so I
2217 think the cmd.exe parser of the redirection symbols simply doesn't
2218 care about the < vs > distinction in these cases. Therefore, the
2219 supported features are explicitly documented below.
2220
2221 The emulation below aims at supporting all the valid use cases
2222 supported by cmd.exe, which include:
2223
2224 < FILE redirect standard input from FILE
2225 0< FILE redirect standard input from FILE
2226 <&N redirect standard input from file descriptor N
2227 0<&N redirect standard input from file descriptor N
2228 > FILE redirect standard output to FILE
2229 >> FILE append standard output to FILE
2230 1>> FILE append standard output to FILE
2231 >&N redirect standard output to file descriptor N
2232 1>&N redirect standard output to file descriptor N
2233 >>&N append standard output to file descriptor N
2234 1>>&N append standard output to file descriptor N
2235 2> FILE redirect standard error to FILE
2236 2>> FILE append standard error to FILE
2237 2>&N redirect standard error to file descriptor N
2238 2>>&N append standard error to file descriptor N
2239
2240 Note that using N > 2 in the above construct is supported, but
2241 requires that the corresponding file descriptor be open by some
2242 means elsewhere or outside GDB. Also note that using ">&0" or
2243 "<&2" will generally fail, because the file descriptor redirected
2244 from is normally open in an incompatible mode (e.g., FD 0 is open
2245 for reading only). IOW, use of such tricks is not recommended;
2246 you are on your own.
2247
2248 We do NOT support redirection of file descriptors above 2, as in
2249 "3>SOME-FILE", because MinGW compiled programs don't (supporting
2250 that needs special handling in the startup code that MinGW
2251 doesn't have). Pipes are also not supported.
2252
2253 As for invalid use cases, where the redirection contains some
2254 error, the emulation below will detect that and produce some
2255 error and/or failure. But the behavior in those cases is not
2256 bug-for-bug compatible with what cmd.exe does in those cases.
2257 That's because what cmd.exe does then is not well defined, and
2258 seems to be a side effect of the cmd.exe parsing of the command
2259 line more than anything else. For example, try redirecting to an
2260 invalid file name, as in "> foo:bar".
2261
2262 There are also minor syntactic deviations from what cmd.exe does
2263 in some corner cases. For example, it doesn't support the likes
2264 of "> &foo" to mean redirect to file named literally "&foo"; we
2265 do support that here, because that, too, sounds like some issue
2266 with the cmd.exe parser. Another nicety is that we support
2267 redirection targets that use file names with forward slashes,
2268 something cmd.exe doesn't -- this comes in handy since GDB
2269 file-name completion can be used when typing the command line for
2270 the inferior. */
2271
2272/* Support routines for redirecting standard handles of the inferior. */
2273
2274/* Parse a single redirection spec, open/duplicate the specified
2275 file/fd, and assign the appropriate value to one of the 3 standard
2276 file descriptors. */
2277static int
2278redir_open (const char *redir_string, int *inp, int *out, int *err)
2279{
2280 int *fd, ref_fd = -2;
2281 int mode;
2282 const char *fname = redir_string + 1;
2283 int rc = *redir_string;
2284
2285 switch (rc)
2286 {
2287 case '0':
2288 fname++;
2289 /* FALLTHROUGH */
2290 case '<':
2291 fd = inp;
2292 mode = O_RDONLY;
2293 break;
2294 case '1': case '2':
2295 fname++;
2296 /* FALLTHROUGH */
2297 case '>':
2298 fd = (rc == '2') ? err : out;
2299 mode = O_WRONLY | O_CREAT;
2300 if (*fname == '>')
2301 {
2302 fname++;
2303 mode |= O_APPEND;
2304 }
2305 else
2306 mode |= O_TRUNC;
2307 break;
2308 default:
2309 return -1;
2310 }
2311
2312 if (*fname == '&' && '0' <= fname[1] && fname[1] <= '9')
2313 {
2314 /* A reference to a file descriptor. */
2315 char *fdtail;
2316 ref_fd = (int) strtol (fname + 1, &fdtail, 10);
2317 if (fdtail > fname + 1 && *fdtail == '\0')
2318 {
2319 /* Don't allow redirection when open modes are incompatible. */
2320 if ((ref_fd == 0 && (fd == out || fd == err))
2321 || ((ref_fd == 1 || ref_fd == 2) && fd == inp))
2322 {
2323 errno = EPERM;
2324 return -1;
2325 }
2326 if (ref_fd == 0)
2327 ref_fd = *inp;
2328 else if (ref_fd == 1)
2329 ref_fd = *out;
2330 else if (ref_fd == 2)
2331 ref_fd = *err;
2332 }
2333 else
2334 {
2335 errno = EBADF;
2336 return -1;
2337 }
2338 }
2339 else
2340 fname++; /* skip the separator space */
2341 /* If the descriptor is already open, close it. This allows
2342 multiple specs of redirections for the same stream, which is
2343 somewhat nonsensical, but still valid and supported by cmd.exe.
2344 (But cmd.exe only opens a single file in this case, the one
2345 specified by the last redirection spec on the command line.) */
2346 if (*fd >= 0)
2347 _close (*fd);
2348 if (ref_fd == -2)
2349 {
2350 *fd = _open (fname, mode, _S_IREAD | _S_IWRITE);
2351 if (*fd < 0)
2352 return -1;
2353 }
2354 else if (ref_fd == -1)
2355 *fd = -1; /* reset to default destination */
2356 else
2357 {
2358 *fd = _dup (ref_fd);
2359 if (*fd < 0)
2360 return -1;
2361 }
2362 /* _open just sets a flag for O_APPEND, which won't be passed to the
2363 inferior, so we need to actually move the file pointer. */
2364 if ((mode & O_APPEND) != 0)
2365 _lseek (*fd, 0L, SEEK_END);
2366 return 0;
2367}
2368
2369/* Canonicalize a single redirection spec and set up the corresponding
2370 file descriptor as specified. */
2371static int
2372redir_set_redirection (const char *s, int *inp, int *out, int *err)
2373{
2374 char buf[__PMAX + 2 + 5]; /* extra space for quotes & redirection string */
2375 char *d = buf;
2376 const char *start = s;
2377 int quote = 0;
2378
2379 *d++ = *s++; /* copy the 1st character, < or > or a digit */
2380 if ((*start == '>' || *start == '1' || *start == '2')
2381 && *s == '>')
2382 {
2383 *d++ = *s++;
2384 if (*s == '>' && *start != '>')
2385 *d++ = *s++;
2386 }
2387 else if (*start == '0' && *s == '<')
2388 *d++ = *s++;
2389 /* cmd.exe recognizes "&N" only immediately after the redirection symbol. */
2390 if (*s != '&')
2391 {
2392 while (isspace (*s)) /* skip whitespace before file name */
2393 s++;
2394 *d++ = ' '; /* separate file name with a single space */
2395 }
2396
2397 /* Copy the file name. */
2398 while (*s)
2399 {
2400 /* Remove quoting characters from the file name in buf[]. */
2401 if (*s == '"') /* could support '..' quoting here */
2402 {
2403 if (!quote)
2404 quote = *s++;
2405 else if (*s == quote)
2406 {
2407 quote = 0;
2408 s++;
2409 }
2410 else
2411 *d++ = *s++;
2412 }
2413 else if (*s == '\\')
2414 {
2415 if (s[1] == '"') /* could support '..' here */
2416 s++;
2417 *d++ = *s++;
2418 }
2419 else if (isspace (*s) && !quote)
2420 break;
2421 else
2422 *d++ = *s++;
2423 if (d - buf >= sizeof (buf) - 1)
2424 {
2425 errno = ENAMETOOLONG;
2426 return 0;
2427 }
2428 }
2429 *d = '\0';
2430
2431 /* Windows doesn't allow redirection characters in file names, so we
2432 can bail out early if they use them, or if there's no target file
2433 name after the redirection symbol. */
2434 if (d[-1] == '>' || d[-1] == '<')
2435 {
2436 errno = ENOENT;
2437 return 0;
2438 }
2439 if (redir_open (buf, inp, out, err) == 0)
2440 return s - start;
2441 return 0;
2442}
2443
2444/* Parse the command line for redirection specs and prepare the file
2445 descriptors for the 3 standard streams accordingly. */
2446static bool
2447redirect_inferior_handles (const char *cmd_orig, char *cmd,
2448 int *inp, int *out, int *err)
2449{
2450 const char *s = cmd_orig;
2451 char *d = cmd;
2452 int quote = 0;
2453 bool retval = false;
2454
2455 while (isspace (*s))
2456 *d++ = *s++;
2457
2458 while (*s)
2459 {
2460 if (*s == '"') /* could also support '..' quoting here */
2461 {
2462 if (!quote)
2463 quote = *s;
2464 else if (*s == quote)
2465 quote = 0;
2466 }
2467 else if (*s == '\\')
2468 {
2469 if (s[1] == '"') /* escaped quote char */
2470 s++;
2471 }
2472 else if (!quote)
2473 {
2474 /* Process a single redirection candidate. */
2475 if (*s == '<' || *s == '>'
2476 || ((*s == '1' || *s == '2') && s[1] == '>')
2477 || (*s == '0' && s[1] == '<'))
2478 {
2479 int skip = redir_set_redirection (s, inp, out, err);
2480
2481 if (skip <= 0)
2482 return false;
2483 retval = true;
2484 s += skip;
2485 }
2486 }
2487 if (*s)
2488 *d++ = *s++;
2489 }
2490 *d = '\0';
2491 return retval;
2492}
2493#endif /* !__CYGWIN__ */
2494
2495/* Start an inferior windows child process and sets inferior_ptid to its pid.
2496 EXEC_FILE is the file to run.
2497 ALLARGS is a string containing the arguments to the program.
2498 ENV is the environment vector to pass. Errors reported with error(). */
2499
2500void
2502 const std::string &origallargs,
2503 char **in_env, int from_tty)
2504{
2505 STARTUPINFO si;
2506#ifdef __CYGWIN__
2507 wchar_t real_path[__PMAX];
2508 wchar_t shell[__PMAX]; /* Path to shell */
2509 wchar_t infcwd[__PMAX];
2510 const char *sh;
2511 wchar_t *toexec;
2512 wchar_t *cygallargs;
2513 wchar_t *args;
2514 char **old_env = NULL;
2515 PWCHAR w32_env;
2516 size_t len;
2517 int tty;
2518 int ostdin, ostdout, ostderr;
2519#else /* !__CYGWIN__ */
2520 char shell[__PMAX]; /* Path to shell */
2521 const char *toexec;
2522 char *args, *allargs_copy;
2523 size_t args_len, allargs_len;
2524 int fd_inp = -1, fd_out = -1, fd_err = -1;
2525 HANDLE tty = INVALID_HANDLE_VALUE;
2526 bool redirected = false;
2527 char *w32env;
2528 char *temp;
2529 size_t envlen;
2530 int i;
2531 size_t envsize;
2532 char **env;
2533#endif /* !__CYGWIN__ */
2534 const char *allargs = origallargs.c_str ();
2535 PROCESS_INFORMATION pi;
2536 gdb::optional<unsigned> ret;
2537 DWORD flags = 0;
2538 const std::string &inferior_tty = current_inferior ()->tty ();
2539
2540 if (!exec_file)
2541 error (_("No executable specified, use `target exec'."));
2542
2543 const char *inferior_cwd = current_inferior ()->cwd ().c_str ();
2544 std::string expanded_infcwd;
2545 if (*inferior_cwd == '\0')
2546 inferior_cwd = nullptr;
2547 else
2548 {
2549 expanded_infcwd = gdb_tilde_expand (inferior_cwd);
2550 /* Mirror slashes on inferior's cwd. */
2551 std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
2552 '/', '\\');
2553 inferior_cwd = expanded_infcwd.c_str ();
2554 }
2555
2556 memset (&si, 0, sizeof (si));
2557 si.cb = sizeof (si);
2558
2559 if (new_group)
2560 flags |= CREATE_NEW_PROCESS_GROUP;
2561
2562 if (new_console)
2564
2565#ifdef __CYGWIN__
2566 if (!useshell)
2567 {
2568 flags |= DEBUG_ONLY_THIS_PROCESS;
2569 if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, exec_file, real_path,
2570 __PMAX * sizeof (wchar_t)) < 0)
2571 error (_("Error starting executable: %d"), errno);
2572 toexec = real_path;
2573 len = mbstowcs (NULL, allargs, 0) + 1;
2574 if (len == (size_t) -1)
2575 error (_("Error starting executable: %d"), errno);
2576 cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
2577 mbstowcs (cygallargs, allargs, len);
2578 }
2579 else
2580 {
2581 sh = get_shell ();
2582 if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, sh, shell, __PMAX) < 0)
2583 error (_("Error starting executable via shell: %d"), errno);
2584 len = sizeof (L" -c 'exec '") + mbstowcs (NULL, exec_file, 0)
2585 + mbstowcs (NULL, allargs, 0) + 2;
2586 cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
2587 swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
2588 toexec = shell;
2589 flags |= DEBUG_PROCESS;
2590 }
2591
2592 if (inferior_cwd != NULL
2593 && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
2594 infcwd, strlen (inferior_cwd)) < 0)
2595 error (_("Error converting inferior cwd: %d"), errno);
2596
2597 args = (wchar_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
2598 * sizeof (wchar_t));
2599 wcscpy (args, toexec);
2600 wcscat (args, L" ");
2601 wcscat (args, cygallargs);
2602
2603#ifdef CW_CVT_ENV_TO_WINENV
2604 /* First try to create a direct Win32 copy of the POSIX environment. */
2605 w32_env = (PWCHAR) cygwin_internal (CW_CVT_ENV_TO_WINENV, in_env);
2606 if (w32_env != (PWCHAR) -1)
2607 flags |= CREATE_UNICODE_ENVIRONMENT;
2608 else
2609 /* If that fails, fall back to old method tweaking GDB's environment. */
2610#endif /* CW_CVT_ENV_TO_WINENV */
2611 {
2612 /* Reset all Win32 environment variables to avoid leftover on next run. */
2613 clear_win32_environment (environ);
2614 /* Prepare the environment vars for CreateProcess. */
2615 old_env = environ;
2616 environ = in_env;
2617 cygwin_internal (CW_SYNC_WINENV);
2618 w32_env = NULL;
2619 }
2620
2621 if (inferior_tty.empty ())
2622 tty = ostdin = ostdout = ostderr = -1;
2623 else
2624 {
2625 tty = open (inferior_tty.c_str (), O_RDWR | O_NOCTTY);
2626 if (tty < 0)
2627 {
2628 warning_filename_and_errno (inferior_tty.c_str (), errno);
2629 ostdin = ostdout = ostderr = -1;
2630 }
2631 else
2632 {
2633 ostdin = dup (0);
2634 ostdout = dup (1);
2635 ostderr = dup (2);
2636 dup2 (tty, 0);
2637 dup2 (tty, 1);
2638 dup2 (tty, 2);
2639 }
2640 }
2641
2643 do_synchronously ([&] ()
2644 {
2645 if (!create_process (nullptr, args, flags, w32_env,
2646 inferior_cwd != nullptr ? infcwd : nullptr,
2648 &si, &pi))
2649 ret = (unsigned) GetLastError ();
2650 return true;
2651 });
2652
2653 if (w32_env)
2654 /* Just free the Win32 environment, if it could be created. */
2655 free (w32_env);
2656 else
2657 {
2658 /* Reset all environment variables to avoid leftover on next run. */
2659 clear_win32_environment (in_env);
2660 /* Restore normal GDB environment variables. */
2661 environ = old_env;
2662 cygwin_internal (CW_SYNC_WINENV);
2663 }
2664
2665 if (tty >= 0)
2666 {
2667 ::close (tty);
2668 dup2 (ostdin, 0);
2669 dup2 (ostdout, 1);
2670 dup2 (ostderr, 2);
2671 ::close (ostdin);
2672 ::close (ostdout);
2673 ::close (ostderr);
2674 }
2675#else /* !__CYGWIN__ */
2676 allargs_len = strlen (allargs);
2677 allargs_copy = strcpy ((char *) alloca (allargs_len + 1), allargs);
2678 if (strpbrk (allargs_copy, "<>") != NULL)
2679 {
2680 int e = errno;
2681 errno = 0;
2682 redirected =
2683 redirect_inferior_handles (allargs, allargs_copy,
2684 &fd_inp, &fd_out, &fd_err);
2685 if (errno)
2686 warning (_("Error in redirection: %s."), safe_strerror (errno));
2687 else
2688 errno = e;
2689 allargs_len = strlen (allargs_copy);
2690 }
2691 /* If not all the standard streams are redirected by the command
2692 line, use INFERIOR_TTY for those which aren't. */
2693 if (!inferior_tty.empty ()
2694 && !(fd_inp >= 0 && fd_out >= 0 && fd_err >= 0))
2695 {
2696 SECURITY_ATTRIBUTES sa;
2697 sa.nLength = sizeof(sa);
2698 sa.lpSecurityDescriptor = 0;
2699 sa.bInheritHandle = TRUE;
2700 tty = CreateFileA (inferior_tty.c_str (), GENERIC_READ | GENERIC_WRITE,
2701 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
2702 if (tty == INVALID_HANDLE_VALUE)
2703 {
2704 unsigned err = (unsigned) GetLastError ();
2705 warning (_("Warning: Failed to open TTY %s, error %#x: %s"),
2706 inferior_tty.c_str (), err, strwinerror (err));
2707 }
2708 }
2709 if (redirected || tty != INVALID_HANDLE_VALUE)
2710 {
2711 if (fd_inp >= 0)
2712 si.hStdInput = (HANDLE) _get_osfhandle (fd_inp);
2713 else if (tty != INVALID_HANDLE_VALUE)
2714 si.hStdInput = tty;
2715 else
2716 si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
2717 if (fd_out >= 0)
2718 si.hStdOutput = (HANDLE) _get_osfhandle (fd_out);
2719 else if (tty != INVALID_HANDLE_VALUE)
2720 si.hStdOutput = tty;
2721 else
2722 si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
2723 if (fd_err >= 0)
2724 si.hStdError = (HANDLE) _get_osfhandle (fd_err);
2725 else if (tty != INVALID_HANDLE_VALUE)
2726 si.hStdError = tty;
2727 else
2728 si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
2729 si.dwFlags |= STARTF_USESTDHANDLES;
2730 }
2731
2732 toexec = exec_file;
2733 /* Build the command line, a space-separated list of tokens where
2734 the first token is the name of the module to be executed.
2735 To avoid ambiguities introduced by spaces in the module name,
2736 we quote it. */
2737 args_len = strlen (toexec) + 2 /* quotes */ + allargs_len + 2;
2738 args = (char *) alloca (args_len);
2739 xsnprintf (args, args_len, "\"%s\" %s", toexec, allargs_copy);
2740
2741 flags |= DEBUG_ONLY_THIS_PROCESS;
2742
2743 /* CreateProcess takes the environment list as a null terminated set of
2744 strings (i.e. two nulls terminate the list). */
2745
2746 /* Get total size for env strings. */
2747 for (envlen = 0, i = 0; in_env[i] && *in_env[i]; i++)
2748 envlen += strlen (in_env[i]) + 1;
2749
2750 envsize = sizeof (in_env[0]) * (i + 1);
2751 env = (char **) alloca (envsize);
2752 memcpy (env, in_env, envsize);
2753 /* Windows programs expect the environment block to be sorted. */
2754 qsort (env, i, sizeof (char *), envvar_cmp);
2755
2756 w32env = (char *) alloca (envlen + 1);
2757
2758 /* Copy env strings into new buffer. */
2759 for (temp = w32env, i = 0; env[i] && *env[i]; i++)
2760 {
2761 strcpy (temp, env[i]);
2762 temp += strlen (temp) + 1;
2763 }
2764
2765 /* Final nil string to terminate new env. */
2766 *temp = 0;
2767
2769 do_synchronously ([&] ()
2770 {
2771 if (!create_process (nullptr, /* image */
2772 args, /* command line */
2773 flags, /* start flags */
2774 w32env, /* environment */
2775 inferior_cwd, /* current directory */
2777 &si,
2778 &pi))
2779 ret = (unsigned) GetLastError ();
2780 return true;
2781 });
2782 if (tty != INVALID_HANDLE_VALUE)
2783 CloseHandle (tty);
2784 if (fd_inp >= 0)
2785 _close (fd_inp);
2786 if (fd_out >= 0)
2787 _close (fd_out);
2788 if (fd_err >= 0)
2789 _close (fd_err);
2790#endif /* !__CYGWIN__ */
2791
2792 if (ret.has_value ())
2793 error (_("Error creating process %s, (error %u: %s)"),
2794 exec_file, *ret, strwinerror (*ret));
2795
2796#ifdef __x86_64__
2797 BOOL wow64;
2798 if (IsWow64Process (pi.hProcess, &wow64))
2799 windows_process.wow64_process = wow64;
2800#endif
2801
2802 CloseHandle (pi.hThread);
2803 CloseHandle (pi.hProcess);
2804
2805 if (useshell && shell[0] != '\0')
2807 else
2809
2810 do_initial_windows_stuff (pi.dwProcessId, 0);
2811
2812 /* windows_continue (DBG_CONTINUE, -1, 0); */
2813}
2814
2815void
2817{
2818 (void) windows_continue (DBG_CONTINUE, -1, 0, true);
2821 {
2822 CHECK (CloseHandle (windows_process.handle));
2824 }
2825 windows_process.siginfo_er.ExceptionCode = 0;
2827}
2828
2829/* Helper for windows_xfer_partial that handles memory transfers.
2830 Arguments are like target_xfer_partial. */
2831
2832static enum target_xfer_status
2833windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
2834 ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
2835{
2836 SIZE_T done = 0;
2837 BOOL success;
2838 DWORD lasterror = 0;
2839
2840 if (writebuf != NULL)
2841 {
2842 DEBUG_MEM ("write target memory, %s bytes at %s",
2843 pulongest (len), core_addr_to_string (memaddr));
2844 success = WriteProcessMemory (windows_process.handle,
2845 (LPVOID) (uintptr_t) memaddr, writebuf,
2846 len, &done);
2847 if (!success)
2848 lasterror = GetLastError ();
2849 FlushInstructionCache (windows_process.handle,
2850 (LPCVOID) (uintptr_t) memaddr, len);
2851 }
2852 else
2853 {
2854 DEBUG_MEM ("read target memory, %s bytes at %s",
2855 pulongest (len), core_addr_to_string (memaddr));
2856 success = ReadProcessMemory (windows_process.handle,
2857 (LPCVOID) (uintptr_t) memaddr, readbuf,
2858 len, &done);
2859 if (!success)
2860 lasterror = GetLastError ();
2861 }
2862 *xfered_len = (ULONGEST) done;
2863 if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
2864 return TARGET_XFER_OK;
2865 else
2866 return success ? TARGET_XFER_OK : TARGET_XFER_E_IO;
2867}
2868
2869void
2871{
2872 CHECK (TerminateProcess (windows_process.handle, 0));
2873
2874 for (;;)
2875 {
2876 if (!windows_continue (DBG_CONTINUE, -1, 1))
2877 break;
2879 if (windows_process.current_event.dwDebugEventCode
2880 == EXIT_PROCESS_DEBUG_EVENT)
2881 break;
2882 }
2883
2884 target_mourn_inferior (inferior_ptid); /* Or just windows_mourn_inferior? */
2885}
2886
2887void
2889{
2890 DEBUG_EVENTS ("inferior_ptid=%d\n", inferior_ptid.pid ());
2891 async (false);
2892}
2893
2894/* Convert pid to printable format. */
2895std::string
2897{
2898 if (ptid.lwp () != 0)
2899 return string_printf ("Thread %d.0x%lx", ptid.pid (), ptid.lwp ());
2900
2901 return normal_pid_to_str (ptid);
2902}
2903
2904static enum target_xfer_status
2906 enum target_object object, const char *annex,
2907 gdb_byte *readbuf, const gdb_byte *writebuf,
2908 ULONGEST offset, ULONGEST len,
2909 ULONGEST *xfered_len)
2910{
2911 auto_obstack obstack;
2912 const char *buf;
2913 LONGEST len_avail;
2914
2915 if (writebuf)
2916 return TARGET_XFER_E_IO;
2917
2918 obstack_grow_str (&obstack, "<library-list>\n");
2920 windows_xfer_shared_library (so.name.c_str (),
2921 (CORE_ADDR) (uintptr_t) so.load_addr,
2922 &so.text_offset,
2923 target_gdbarch (), &obstack);
2924 obstack_grow_str0 (&obstack, "</library-list>\n");
2925
2926 buf = (const char *) obstack_finish (&obstack);
2927 len_avail = strlen (buf);
2928 if (offset >= len_avail)
2929 len= 0;
2930 else
2931 {
2932 if (len > len_avail - offset)
2933 len = len_avail - offset;
2934 memcpy (readbuf, buf + offset, len);
2935 }
2936
2937 *xfered_len = (ULONGEST) len;
2938 return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
2939}
2940
2941/* Helper for windows_nat_target::xfer_partial that handles signal info. */
2942
2943static enum target_xfer_status
2944windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
2945 ULONGEST *xfered_len)
2946{
2947 char *buf = (char *) &windows_process.siginfo_er;
2948 size_t bufsize = sizeof (windows_process.siginfo_er);
2949
2950#ifdef __x86_64__
2951 EXCEPTION_RECORD32 er32;
2952 if (windows_process.wow64_process)
2953 {
2954 buf = (char *) &er32;
2955 bufsize = sizeof (er32);
2956
2957 er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
2958 er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
2959 er32.ExceptionRecord
2960 = (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
2961 er32.ExceptionAddress
2962 = (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
2963 er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
2964 int i;
2965 for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
2966 er32.ExceptionInformation[i]
2967 = windows_process.siginfo_er.ExceptionInformation[i];
2968 }
2969#endif
2970
2971 if (windows_process.siginfo_er.ExceptionCode == 0)
2972 return TARGET_XFER_E_IO;
2973
2974 if (readbuf == nullptr)
2975 return TARGET_XFER_E_IO;
2976
2977 if (offset > bufsize)
2978 return TARGET_XFER_E_IO;
2979
2980 if (offset + len > bufsize)
2981 len = bufsize - offset;
2982
2983 memcpy (readbuf, buf + offset, len);
2984 *xfered_len = len;
2985
2986 return TARGET_XFER_OK;
2987}
2988
2991 const char *annex, gdb_byte *readbuf,
2992 const gdb_byte *writebuf, ULONGEST offset,
2993 ULONGEST len, ULONGEST *xfered_len)
2994{
2995 switch (object)
2996 {
2998 return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
2999
3001 return windows_xfer_shared_libraries (this, object, annex, readbuf,
3002 writebuf, offset, len, xfered_len);
3003
3005 return windows_xfer_siginfo (readbuf, offset, len, xfered_len);
3006
3007 default:
3008 if (beneath () == NULL)
3009 {
3010 /* This can happen when requesting the transfer of unsupported
3011 objects before a program has been started (and therefore
3012 with the current_target having no target beneath). */
3013 return TARGET_XFER_E_IO;
3014 }
3015 return beneath ()->xfer_partial (object, annex,
3016 readbuf, writebuf, offset, len,
3017 xfered_len);
3018 }
3019}
3020
3021/* Provide thread local base, i.e. Thread Information Block address.
3022 Returns 1 if ptid is found and sets *ADDR to thread_local_base. */
3023
3024bool
3025windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
3026{
3028
3030 if (th == NULL)
3031 return false;
3032
3033 if (addr != NULL)
3034 *addr = th->thread_local_base;
3035
3036 return true;
3037}
3038
3039ptid_t
3040windows_nat_target::get_ada_task_ptid (long lwp, ULONGEST thread)
3041{
3042 return ptid_t (inferior_ptid.pid (), lwp, 0);
3043}
3044
3045/* Implementation of the to_thread_name method. */
3046
3047const char *
3055
3056
3058void
3060{
3066
3067 /* x86_dr_low.debug_register_length field is set by
3068 calling x86_set_debug_register_length function
3069 in processor windows specific native file. */
3070
3071 /* The target is not a global specifically to avoid a C++ "static
3072 initializer fiasco" situation. */
3074
3075#ifdef __CYGWIN__
3076 cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
3077#endif
3078
3079 add_com ("signal-event", class_run, signal_event_command, _("\
3080Signal a crashed process with event ID, to allow its debugging.\n\
3081This command is needed in support of setting up GDB as JIT debugger on \
3082MS-Windows. The command should be invoked from the GDB command line using \
3083the '-ex' command-line option. The ID of the event that blocks the \
3084crashed process will be supplied by the Windows JIT debugging mechanism."));
3085
3086#ifdef __CYGWIN__
3088Set use of shell to start subprocess."), _("\
3089Show use of shell to start subprocess."), NULL,
3090 NULL,
3091 NULL, /* FIXME: i18n: */
3092 &setlist, &showlist);
3093
3094 add_setshow_boolean_cmd ("cygwin-exceptions", class_support,
3095 &cygwin_exceptions, _("\
3096Break when an exception is detected in the Cygwin DLL itself."), _("\
3097Show whether gdb breaks on exceptions in the Cygwin DLL itself."), NULL,
3098 NULL,
3099 NULL, /* FIXME: i18n: */
3100 &setlist, &showlist);
3101#endif
3102
3103 add_setshow_boolean_cmd ("new-console", class_support, &new_console, _("\
3104Set creation of new console when creating child process."), _("\
3105Show creation of new console when creating child process."), NULL,
3106 NULL,
3107 NULL, /* FIXME: i18n: */
3108 &setlist, &showlist);
3109
3110 add_setshow_boolean_cmd ("new-group", class_support, &new_group, _("\
3111Set creation of new group when creating child process."), _("\
3112Show creation of new group when creating child process."), NULL,
3113 NULL,
3114 NULL, /* FIXME: i18n: */
3115 &setlist, &showlist);
3116
3118Set whether to display execution in child process."), _("\
3119Show whether to display execution in child process."), NULL,
3120 NULL,
3121 NULL, /* FIXME: i18n: */
3122 &setlist, &showlist);
3123
3124 add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\
3125Set whether to display kernel events in child process."), _("\
3126Show whether to display kernel events in child process."), NULL,
3127 NULL,
3128 NULL, /* FIXME: i18n: */
3129 &setlist, &showlist);
3130
3131 add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\
3132Set whether to display memory accesses in child process."), _("\
3133Show whether to display memory accesses in child process."), NULL,
3134 NULL,
3135 NULL, /* FIXME: i18n: */
3136 &setlist, &showlist);
3137
3138 add_setshow_boolean_cmd ("debugexceptions", class_support,
3139 &debug_exceptions, _("\
3140Set whether to display kernel exceptions in child process."), _("\
3141Show whether to display kernel exceptions in child process."), NULL,
3142 NULL,
3143 NULL, /* FIXME: i18n: */
3144 &setlist, &showlist);
3145
3147
3148 add_cmd ("selector", class_info, display_selectors,
3149 _("Display selectors infos."),
3151
3152 if (!initialize_loadable ())
3153 {
3154 /* This will probably fail on Windows 9x/Me. Let the user know
3155 that we're missing some functionality. */
3156 warning(_("\
3157cannot automatically find executable file or library to read symbols.\n\
3158Use \"file\" or \"dll\" command to load executable/libraries directly."));
3159 }
3160}
3161
3162/* Hardware watchpoint support, adapted from go32-nat.c code. */
3163
3164/* Pass the address ADDR to the inferior in the I'th debug register.
3165 Here we just store the address in dr array, the registers will be
3166 actually set up when windows_continue is called. */
3167static void
3168cygwin_set_dr (int i, CORE_ADDR addr)
3169{
3170 if (i < 0 || i > 3)
3171 internal_error (_("Invalid register %d in cygwin_set_dr.\n"), i);
3172 windows_process.dr[i] = addr;
3173
3174 for (auto &th : windows_process.thread_list)
3175 th->debug_registers_changed = true;
3176}
3177
3178/* Pass the value VAL to the inferior in the DR7 debug control
3179 register. Here we just store the address in D_REGS, the watchpoint
3180 will be actually set up in windows_wait. */
3181static void
3182cygwin_set_dr7 (unsigned long val)
3183{
3184 windows_process.dr[7] = (CORE_ADDR) val;
3185
3186 for (auto &th : windows_process.thread_list)
3187 th->debug_registers_changed = true;
3188}
3189
3190/* Get the value of debug register I from the inferior. */
3191
3192static CORE_ADDR
3194{
3195 return windows_process.dr[i];
3196}
3197
3198/* Get the value of the DR6 debug status register from the inferior.
3199 Here we just return the value stored in dr[6]
3200 by the last call to thread_rec for current_event.dwThreadId id. */
3201static unsigned long
3203{
3204 return (unsigned long) windows_process.dr[6];
3205}
3206
3207/* Get the value of the DR7 debug status register from the inferior.
3208 Here we just return the value stored in dr[7] by the last call to
3209 thread_rec for current_event.dwThreadId id. */
3210
3211static unsigned long
3213{
3214 return (unsigned long) windows_process.dr[7];
3215}
3216
3217/* Determine if the thread referenced by "ptid" is alive
3218 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
3219 it means that the thread has died. Otherwise it is assumed to be alive. */
3220
3221bool
3223{
3224 gdb_assert (ptid.lwp () != 0);
3225
3228 return WaitForSingleObject (th->h, 0) != WAIT_OBJECT_0;
3229}
3230
3232void
3234{
3235 char *homedir;
3236 if (inhibit_gdbinit)
3237 return;
3238
3239 homedir = getenv ("HOME");
3240 if (homedir)
3241 {
3242 char *p;
3243 char *oldini = (char *) alloca (strlen (homedir) +
3244 sizeof ("gdb.ini") + 1);
3245 strcpy (oldini, homedir);
3246 p = strchr (oldini, '\0');
3247 if (p > oldini && !IS_DIR_SEPARATOR (p[-1]))
3248 *p++ = '/';
3249 strcpy (p, "gdb.ini");
3250 if (access (oldini, 0) == 0)
3251 {
3252 int len = strlen (oldini);
3253 char *newini = (char *) alloca (len + 2);
3254
3255 xsnprintf (newini, len + 2, "%.*s.gdbinit",
3256 (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
3257 warning (_("obsolete '%s' found. Rename to '%s'."), oldini, newini);
3258 }
3259 }
3260}
const char *const name
#define qsort
Definition ada-exp.c:3129
void xfree(void *)
void * xrealloc(void *ptr, size_t size)
Definition alloc.c:65
const int amd64_mappings[]
#define context_offset(x)
int amd64_windows_segment_register_p(int regnum)
struct gdbarch * target_gdbarch(void)
bool find_pc_partial_function(CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr, const struct block **block)
Definition blockframe.c:373
void disable_breakpoints_in_shlibs(void)
void mourn_inferior() override
Definition inf-child.c:190
void maybe_unpush_target()
Definition inf-child.c:199
const std::string & cwd() const
Definition inferior.h:550
const std::string & tty()
Definition inferior.c:163
thread_info * find_thread(ptid_t ptid)
gdbarch * arch() const
Definition regcache.c:231
void raw_collect(int regnum, void *buf) const override
Definition regcache.c:1127
void raw_supply(int regnum, const void *buf) override
Definition regcache.c:1062
ptid_t ptid() const
Definition regcache.h:408
static void inferior()
Definition target.c:952
static void init()
Definition target.c:942
static void ours()
Definition target.c:1070
ptid_t ptid
Definition gdbthread.h:259
struct cmd_list_element * showlist
Definition cli-cmds.c:127
struct cmd_list_element * setlist
Definition cli-cmds.c:119
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
Definition cli-decode.c:233
struct cmd_list_element * add_com(const char *name, enum command_class theclass, cmd_simple_func_ftype *fun, const char *doc)
set_show_commands add_setshow_boolean_cmd(const char *name, enum command_class theclass, bool *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition cli-decode.c:809
@ class_support
Definition command.h:58
@ class_run
Definition command.h:54
@ class_info
Definition command.h:59
#define complaint(FMT,...)
Definition complaints.h:47
#define BOOL
bool info_verbose
Definition top.c:1941
int(* deprecated_ui_loop_hook)(int signo)
Definition top.c:209
LONGEST parse_and_eval_long(const char *exp)
Definition eval.c:62
void exception_print(struct ui_file *file, const struct gdb_exception &e)
Definition exceptions.c:106
char ** environ
gdb_bfd_ref_ptr gdb_bfd_open(const char *name, const char *target, int fd, bool warn_if_slow)
Definition gdb_bfd.c:473
gdb::ref_ptr< struct bfd, gdb_bfd_ref_policy > gdb_bfd_ref_ptr
Definition gdb_bfd.h:79
int gdbarch_pc_regnum(struct gdbarch *gdbarch)
Definition gdbarch.c:2054
bool gdbarch_read_pc_p(struct gdbarch *gdbarch)
Definition gdbarch.c:1793
int gdbarch_num_regs(struct gdbarch *gdbarch)
Definition gdbarch.c:1930
int gdbarch_ps_regnum(struct gdbarch *gdbarch)
Definition gdbarch.c:2071
CORE_ADDR gdbarch_decr_pc_after_break(struct gdbarch *gdbarch)
Definition gdbarch.c:2903
bool gdbarch_write_pc_p(struct gdbarch *gdbarch)
Definition gdbarch.c:1817
struct thread_info * add_thread_silent(process_stratum_target *targ, ptid_t ptid)
Definition thread.c:296
void delete_thread_with_exit_code(thread_info *thread, ULONGEST exit_code, bool silent=false)
Definition thread.c:518
void switch_to_thread(struct thread_info *thr)
Definition thread.c:1360
void switch_to_no_thread()
Definition thread.c:1345
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t err
Definition gnu-nat.c:1789
mach_port_t kern_return_t mach_port_t mach_msg_type_name_t msgportsPoly mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition gnu-nat.c:1861
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
Definition gnu-nat.c:1791
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int status
Definition gnu-nat.c:1790
size_t size
Definition go32-nat.c:239
const int i386_mappings[]
int i386_windows_segment_register_p(int regnum)
#define I387_FOP_REGNUM(tdep)
Definition i387-tdep.h:65
#define I387_FISEG_REGNUM(tdep)
Definition i387-tdep.h:61
@ L
Definition ia64-tdep.c:85
void add_inf_child_target(inf_child_target *target)
Definition inf-child.c:418
void inferior_event_handler(enum inferior_event_type event_type)
Definition inf-loop.c:37
ptid_t inferior_ptid
Definition infcmd.c:74
void inferior_appeared(struct inferior *inf, int pid)
Definition inferior.c:363
struct inferior * find_inferior_pid(process_stratum_target *targ, int pid)
Definition inferior.c:389
void detach_inferior(inferior *inf)
Definition inferior.c:340
struct inferior * current_inferior(void)
Definition inferior.c:55
#define O_NOCTTY
Definition inflow.c:44
void clear_proceed_status(int step)
Definition infrun.c:2924
bool disable_randomization
Definition infrun.c:197
void init_wait_for_inferior(void)
Definition infrun.c:3639
int find_minimal_symbol_address(const char *name, CORE_ADDR *addr, struct objfile *objfile)
Definition minsyms.c:489
info(Component c)
Definition gdbarch.py:41
GetCurrentConsoleFont_ftype * GetCurrentConsoleFont
Definition windows-nat.c:57
BOOL create_process(const char *image, char *command_line, DWORD flags, void *environment, const char *cur_dir, bool no_randomization, STARTUPINFOA *startup_info, PROCESS_INFORMATION *process_info)
DebugActiveProcessStop_ftype * DebugActiveProcessStop
Definition windows-nat.c:45
bool initialize_loadable()
DebugBreakProcess_ftype * DebugBreakProcess
Definition windows-nat.c:46
BOOL wait_for_debug_event(DEBUG_EVENT *event, DWORD timeout)
LookupPrivilegeValueA_ftype * LookupPrivilegeValueA
Definition windows-nat.c:55
OpenProcessToken_ftype * OpenProcessToken
Definition windows-nat.c:56
GetConsoleFontSize_ftype * GetConsoleFontSize
Definition windows-nat.c:58
AdjustTokenPrivileges_ftype * AdjustTokenPrivileges
Definition windows-nat.c:44
DebugSetProcessKillOnExit_ftype * DebugSetProcessKillOnExit
Definition windows-nat.c:47
@ HANDLE_EXCEPTION_IGNORED
@ HANDLE_EXCEPTION_HANDLED
@ HANDLE_EXCEPTION_UNHANDLED
@ DONT_INVALIDATE_CONTEXT
BOOL continue_last_debug_event(DWORD continue_status, bool debug_events)
bool disable_randomization_available()
#define Wow64GetThreadSelectorEntry
#define Wow64SetThreadContext
#define Wow64GetThreadContext
#define STATUS_WX86_BREAKPOINT
Definition windows-nat.h:29
int value
Definition py-param.c:79
int register_size(struct gdbarch *gdbarch, int regnum)
Definition regcache.c:170
struct regcache * get_current_regcache(void)
Definition regcache.c:429
void(* func)(remote_target *remote, char *)
void serial_event_set(struct serial_event *event)
Definition ser-event.c:180
void serial_event_clear(struct serial_event *event)
Definition ser-event.c:201
struct serial_event * make_serial_event(void)
Definition ser-event.c:162
int serial_event_fd(struct serial_event *event)
Definition ser-event.c:170
#define enable()
Definition ser-go32.c:239
#define SO_NAME_MAX_PATH_SIZE
Definition solist.h:22
Definition gnu-nat.c:153
pid_t pid
Definition gnu-nat.c:165
target_ops * beneath() const
Definition target.c:3041
virtual enum target_xfer_status xfer_partial(enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) TARGET_DEFAULT_RETURN(TARGET_XFER_E_IO)
virtual gdb::array_view< const_gdb_byte > virtual thread_info_to_thread_handle(struct thread_info *) TARGET_DEFAULT_RETURN(gdb voi stop)(ptid_t) TARGET_DEFAULT_IGNORE()
Definition target.h:689
target_waitstatus & set_exited(int exit_status)
Definition waitstatus.h:222
target_waitstatus & set_spurious()
Definition waitstatus.h:300
target_waitstatus & set_signalled(gdb_signal sig)
Definition waitstatus.h:238
target_waitstatus & set_stopped(gdb_signal sig)
Definition waitstatus.h:230
target_waitstatus & set_loaded()
Definition waitstatus.h:246
target_waitstatus & set_ignore()
Definition waitstatus.h:307
target_waitkind kind() const
Definition waitstatus.h:345
Definition value.h:130
bool matching_pending_stop(bool debug_events)
gdb::optional< pending_stop > fetch_pending_stop(bool debug_events)
handle_exception_result handle_exception(struct target_waitstatus *ourstatus, bool debug_exceptions)
std::vector< pending_stop > pending_stops
BOOL windows_continue(DWORD continue_status, int id, int killed, bool last_call=false)
void wait_for_debug_event_main_thread(DEBUG_EVENT *event)
void do_synchronously(gdb::function_view< bool()> func)
static DWORD WINAPI process_thread_starter(LPVOID self)
void do_initial_windows_stuff(DWORD pid, bool attaching)
windows_thread_info * add_thread(ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
DWORD fake_create_process()
bool attach_no_wait() override
serial_event * m_wait_event
void resume(ptid_t, int, enum gdb_signal) override
bool can_async_p() override
std::queue< gdb::function_view< bool()> > m_queue
ptid_t wait(ptid_t, struct target_waitstatus *, target_wait_flags) override
ptid_t get_windows_debug_event(int pid, struct target_waitstatus *ourstatus, target_wait_flags options)
const char * pid_to_exec_file(int pid) override
bool supports_disable_randomization() override
int async_wait_fd() override
void async(bool enable) override
void close() override
void store_registers(struct regcache *, int) override
bool get_tib_address(ptid_t ptid, CORE_ADDR *addr) override
bool thread_alive(ptid_t ptid) override
void detach(inferior *, int) override
void interrupt() override
void create_inferior(const char *, const std::string &, char **, int) override
void files_info() override
bool stopped_by_sw_breakpoint() override
const char * thread_name(struct thread_info *) override
enum target_xfer_status xfer_partial(enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) override
std::atomic< bool > m_debug_event_pending
DEBUG_EVENT m_last_debug_event
void pass_ctrlc() override
bool is_async_p() override
void kill() override
ptid_t get_ada_task_ptid(long lwp, ULONGEST thread) override
void mourn_inferior() override
void delete_thread(ptid_t ptid, DWORD exit_code, bool main_thread_p)
std::string pid_to_str(ptid_t) override
void fetch_registers(struct regcache *, int) override
void attach(const char *, int) override
bool supports_stopped_by_sw_breakpoint() override
std::vector< windows_solib > solibs
bool handle_access_violation(const EXCEPTION_RECORD *rec) override
segment_register_p_ftype * segment_register_p
void handle_unload_dll() override
windows_thread_info * thread_rec(ptid_t ptid, thread_disposition_type disposition) override
void handle_load_dll(const char *dll_name, LPVOID base) override
int handle_output_debug_string(struct target_waitstatus *ourstatus) override
std::vector< std::unique_ptr< windows_thread_info > > thread_list
std::string original_name
Definition windows-nat.c:87
CORE_ADDR text_offset
Definition windows-nat.c:84
LPVOID load_addr
Definition windows-nat.c:83
std::string name
Definition windows-nat.c:89
void(* set_addr)(int, CORE_ADDR)
Definition x86-dregs.h:49
unsigned long(* get_control)(void)
Definition x86-dregs.h:61
unsigned long(* get_status)(void)
Definition x86-dregs.h:57
void(* set_control)(unsigned long)
Definition x86-dregs.h:45
CORE_ADDR(* get_addr)(int)
Definition x86-dregs.h:53
int target_read_string(CORE_ADDR addr, int len, int width, unsigned int fetchlimit, gdb::unique_xmalloc_ptr< gdb_byte > *buffer, int *bytes_read)
Definition target.c:65
void target_announce_detach(int from_tty)
Definition target.c:3622
void target_announce_attach(int from_tty, int pid)
Definition target.c:3643
std::string target_pid_to_str(ptid_t ptid)
Definition target.c:2623
std::string normal_pid_to_str(ptid_t ptid)
Definition target.c:3693
void target_mourn_inferior(ptid_t ptid)
Definition target.c:2758
@ INF_REG_EVENT
Definition target.h:134
target_xfer_status
Definition target.h:219
@ TARGET_XFER_E_IO
Definition target.h:232
@ TARGET_XFER_EOF
Definition target.h:224
@ TARGET_XFER_OK
Definition target.h:221
target_object
Definition target.h:143
@ TARGET_OBJECT_SIGNAL_INFO
Definition target.h:187
@ TARGET_OBJECT_MEMORY
Definition target.h:147
@ TARGET_OBJECT_LIBRARIES
Definition target.h:176
int inhibit_gdbinit
Definition top.c:129
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886
void gdb_puts(const char *linebuffer, struct ui_file *stream)
Definition utils.c:1809
void warning_filename_and_errno(const char *filename, int saved_errno)
Definition utils.c:625
int parse_pid_to_attach(const char *args)
Definition utils.c:3331
#define gdb_stderr
Definition utils.h:187
@ TARGET_WNOHANG
Definition wait.h:32
@ TARGET_WAITKIND_SPURIOUS
Definition waitstatus.h:78
@ TARGET_WAITKIND_LOADED
Definition waitstatus.h:44
@ TARGET_WAITKIND_SIGNALLED
Definition waitstatus.h:40
@ TARGET_WAITKIND_EXITED
Definition waitstatus.h:32
static unsigned long cygwin_get_dr7(void)
#define DEBUG_EVENTS(fmt,...)
static bool new_group
static windows_per_inferior windows_process
static enum target_xfer_status windows_xfer_memory(gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
static bool useshell
static int envvar_cmp(const void *a, const void *b)
static int redir_open(const char *redir_string, int *inp, int *out, int *err)
static bool new_console
static void display_selectors(const char *args, int from_tty)
static void signal_event_command(const char *args, int from_tty)
static int set_process_privilege(const char *privilege, BOOL enable)
static bool debug_exceptions
static void cygwin_set_dr7(unsigned long val)
static void windows_fetch_one_register(struct regcache *regcache, windows_thread_info *th, int r)
static bool debug_memory
@ FLAG_TRACE_BIT
void _initialize_windows_nat()
static unsigned long cygwin_get_dr6(void)
static enum target_xfer_status windows_xfer_shared_libraries(struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
#define DEBUG_EXEC(fmt,...)
static bool redirect_inferior_handles(const char *cmd_orig, char *cmd, int *inp, int *out, int *err)
#define CHECK(x)
static bool debug_exec
#define DEBUG_MEM(fmt,...)
static int display_selector(HANDLE thread, DWORD sel)
void _initialize_check_for_gdb_ini()
static void windows_init_thread_list(void)
static int redir_set_redirection(const char *s, int *inp, int *out, int *err)
#define STARTUPINFO
#define DEBUG_EXCEPT(fmt,...)
static void windows_clear_solib(void)
#define __PMAX
#define CONTEXT_DEBUGGER_DR
static void windows_store_one_register(const struct regcache *regcache, windows_thread_info *th, int r)
static CORE_ADDR cygwin_get_dr(int i)
#define DR6_CLEAR_VALUE
static enum target_xfer_status windows_xfer_siginfo(gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
static void cygwin_set_dr(int i, CORE_ADDR addr)
static void check(BOOL ok, const char *file, int line)
static void windows_set_console_info(STARTUPINFO *si, DWORD *flags)
static bool debug_events
static void wait_for_single(HANDLE handle, DWORD howlong)
#define _CYGWIN_SIGNAL_STRING
static windows_solib * windows_make_so(const char *name, LPVOID load_addr)
int segment_register_p_ftype(int regnum)
Definition windows-nat.h:23
void windows_xfer_shared_library(const char *so_name, CORE_ADDR load_addr, CORE_ADDR *text_offset_cached, struct gdbarch *gdbarch, struct obstack *obstack)
void init_w32_command_list(void)
struct cmd_list_element * info_w32_cmdlist
#define nullptr
Definition x86-cpuid.h:28
struct x86_dr_low_type x86_dr_low
Definition x86-nat.c:39
void x86_cleanup_dregs(void)
Definition x86-nat.c:81