GDBserver
win32-low.c
Go to the documentation of this file.
1 /* Low level interface to Windows debugging, for gdbserver.
2  Copyright (C) 2006-2018 Free Software Foundation, Inc.
3 
4  Contributed by Leo Zayas. Based on "win32-nat.c" from GDB.
5 
6  This file is part of GDB.
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 
21 #include "server.h"
22 #include "regcache.h"
23 #include "gdb/fileio.h"
24 #include "mem-break.h"
25 #include "win32-low.h"
26 #include "gdbthread.h"
27 #include "dll.h"
28 #include "hostio.h"
29 #include <windows.h>
30 #include <winnt.h>
31 #include <imagehlp.h>
32 #include <tlhelp32.h>
33 #include <psapi.h>
34 #include <process.h>
35 #include "gdb_tilde_expand.h"
36 #include "common-inferior.h"
37 
38 #ifndef USE_WIN32API
39 #include <sys/cygwin.h>
40 #endif
41 
42 #define OUTMSG(X) do { printf X; fflush (stderr); } while (0)
43 
44 #define OUTMSG2(X) \
45  do \
46  { \
47  if (debug_threads) \
48  { \
49  printf X; \
50  fflush (stderr); \
51  } \
52  } while (0)
53 
54 #ifndef _T
55 #define _T(x) TEXT (x)
56 #endif
57 
58 #ifndef COUNTOF
59 #define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
60 #endif
61 
62 #ifdef _WIN32_WCE
63 # define GETPROCADDRESS(DLL, PROC) \
64  ((winapi_ ## PROC) GetProcAddress (DLL, TEXT (#PROC)))
65 #else
66 # define GETPROCADDRESS(DLL, PROC) \
67  ((winapi_ ## PROC) GetProcAddress (DLL, #PROC))
68 #endif
69 
70 int using_threads = 1;
71 
72 /* Globals. */
73 static int attaching = 0;
74 static HANDLE current_process_handle = NULL;
75 static DWORD current_process_id = 0;
76 static DWORD main_thread_id = 0;
77 static enum gdb_signal last_sig = GDB_SIGNAL_0;
78 
79 /* The current debug event from WaitForDebugEvent. */
80 static DEBUG_EVENT current_event;
81 
82 /* A status that hasn't been reported to the core yet, and so
83  win32_wait should return it next, instead of fetching the next
84  debug event off the win32 API. */
85 static struct target_waitstatus cached_status;
86 
87 /* Non zero if an interrupt request is to be satisfied by suspending
88  all threads. */
89 static int soft_interrupt_requested = 0;
90 
91 /* Non zero if the inferior is stopped in a simulated breakpoint done
92  by suspending all the threads. */
93 static int faked_breakpoint = 0;
94 
95 const struct target_desc *win32_tdesc;
96 
97 #define NUM_REGS (the_low_target.num_regs)
98 
99 typedef BOOL (WINAPI *winapi_DebugActiveProcessStop) (DWORD dwProcessId);
100 typedef BOOL (WINAPI *winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
101 typedef BOOL (WINAPI *winapi_DebugBreakProcess) (HANDLE);
102 typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
103 
104 static ptid_t win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus,
105  int options);
106 static void win32_resume (struct thread_resume *resume_info, size_t n);
107 #ifndef _WIN32_WCE
108 static void win32_add_all_dlls (void);
109 #endif
110 
111 /* Get the thread ID from the current selected inferior (the current
112  thread). */
113 static ptid_t
115 {
116  return current_ptid;
117 }
118 
119 /* The current debug event from WaitForDebugEvent. */
120 static ptid_t
121 debug_event_ptid (DEBUG_EVENT *event)
122 {
123  return ptid_build (event->dwProcessId, event->dwThreadId, 0);
124 }
125 
126 /* Get the thread context of the thread associated with TH. */
127 
128 static void
130 {
131  memset (&th->context, 0, sizeof (CONTEXT));
132  (*the_low_target.get_thread_context) (th);
133 #ifdef _WIN32_WCE
134  memcpy (&th->base_context, &th->context, sizeof (CONTEXT));
135 #endif
136 }
137 
138 /* Set the thread context of the thread associated with TH. */
139 
140 static void
142 {
143 #ifdef _WIN32_WCE
144  /* Calling SuspendThread on a thread that is running kernel code
145  will report that the suspending was successful, but in fact, that
146  will often not be true. In those cases, the context returned by
147  GetThreadContext will not be correct by the time the thread
148  stops, hence we can't set that context back into the thread when
149  resuming - it will most likelly crash the inferior.
150  Unfortunately, there is no way to know when the thread will
151  really stop. To work around it, we'll only write the context
152  back to the thread when either the user or GDB explicitly change
153  it between stopping and resuming. */
154  if (memcmp (&th->context, &th->base_context, sizeof (CONTEXT)) != 0)
155 #endif
156  SetThreadContext (th->h, &th->context);
157 }
158 
159 /* Set the thread context of the thread associated with TH. */
160 
161 static void
163 {
164  if (the_low_target.prepare_to_resume != NULL)
166 }
167 
168 /* See win32-low.h. */
169 
170 void
172 {
173  if (th->context.ContextFlags == 0)
174  {
175  if (!th->suspended)
176  {
177  if (SuspendThread (th->h) == (DWORD) -1)
178  {
179  DWORD err = GetLastError ();
180  OUTMSG (("warning: SuspendThread failed in thread_rec, "
181  "(error %d): %s\n", (int) err, strwinerror (err)));
182  }
183  else
184  th->suspended = 1;
185  }
186 
188  }
189 }
190 
191 /* Find a thread record given a thread id. If GET_CONTEXT is set then
192  also retrieve the context for this thread. */
193 static win32_thread_info *
194 thread_rec (ptid_t ptid, int get_context)
195 {
196  thread_info *thread = find_thread_ptid (ptid);
197  if (thread == NULL)
198  return NULL;
199 
201  if (get_context)
203  return th;
204 }
205 
206 /* Add a thread to the thread list. */
207 static win32_thread_info *
208 child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
209 {
210  win32_thread_info *th;
211  ptid_t ptid = ptid_build (pid, tid, 0);
212 
213  if ((th = thread_rec (ptid, FALSE)))
214  return th;
215 
216  th = XCNEW (win32_thread_info);
217  th->tid = tid;
218  th->h = h;
219  th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
220 
221  add_thread (ptid, th);
222 
223  if (the_low_target.thread_added != NULL)
224  (*the_low_target.thread_added) (th);
225 
226  return th;
227 }
228 
229 /* Delete a thread from the list of threads. */
230 static void
232 {
234 
235  remove_thread (thread);
236  CloseHandle (th->h);
237  free (th);
238 }
239 
240 /* Delete a thread from the list of threads. */
241 static void
242 child_delete_thread (DWORD pid, DWORD tid)
243 {
244  /* If the last thread is exiting, just return. */
245  if (all_threads.size () == 1)
246  return;
247 
248  thread_info *thread = find_thread_ptid (ptid_t (pid, tid));
249  if (thread == NULL)
250  return;
251 
252  delete_thread_info (thread);
253 }
254 
255 /* These watchpoint related wrapper functions simply pass on the function call
256  if the low target has registered a corresponding function. */
257 
258 static int
260 {
261  return (the_low_target.supports_z_point_type != NULL
263 }
264 
265 static int
267  int size, struct raw_breakpoint *bp)
268 {
269  if (the_low_target.insert_point != NULL)
270  return the_low_target.insert_point (type, addr, size, bp);
271  else
272  /* Unsupported (see target.h). */
273  return 1;
274 }
275 
276 static int
278  int size, struct raw_breakpoint *bp)
279 {
280  if (the_low_target.remove_point != NULL)
281  return the_low_target.remove_point (type, addr, size, bp);
282  else
283  /* Unsupported (see target.h). */
284  return 1;
285 }
286 
287 static int
289 {
292  else
293  return 0;
294 }
295 
296 static CORE_ADDR
298 {
301  else
302  return 0;
303 }
304 
305 
306 /* Transfer memory from/to the debugged process. */
307 static int
308 child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
309  int write, struct target_ops *target)
310 {
311  BOOL success;
312  SIZE_T done = 0;
313  DWORD lasterror = 0;
314  uintptr_t addr = (uintptr_t) memaddr;
315 
316  if (write)
317  {
318  success = WriteProcessMemory (current_process_handle, (LPVOID) addr,
319  (LPCVOID) our, len, &done);
320  if (!success)
321  lasterror = GetLastError ();
322  FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
323  }
324  else
325  {
326  success = ReadProcessMemory (current_process_handle, (LPCVOID) addr,
327  (LPVOID) our, len, &done);
328  if (!success)
329  lasterror = GetLastError ();
330  }
331  if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
332  return done;
333  else
334  return success ? done : -1;
335 }
336 
337 /* Clear out any old thread list and reinitialize it to a pristine
338  state. */
339 static void
341 {
343 }
344 
345 /* Zero during the child initialization phase, and nonzero otherwise. */
346 
348 
349 static void
350 do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
351 {
352  struct process_info *proc;
353 
354  last_sig = GDB_SIGNAL_0;
355 
356  current_process_handle = proch;
358  main_thread_id = 0;
359 
361  faked_breakpoint = 0;
362 
363  memset (&current_event, 0, sizeof (current_event));
364 
365  proc = add_process (pid, attached);
366  proc->tdesc = win32_tdesc;
369 
370  if (the_low_target.initial_stuff != NULL)
371  (*the_low_target.initial_stuff) ();
372 
373  cached_status.kind = TARGET_WAITKIND_IGNORE;
374 
375  /* Flush all currently pending debug events (thread and dll list) up
376  to the initial breakpoint. */
377  while (1)
378  {
379  struct target_waitstatus status;
380 
381  win32_wait (minus_one_ptid, &status, 0);
382 
383  /* Note win32_wait doesn't return thread events. */
384  if (status.kind != TARGET_WAITKIND_LOADED)
385  {
386  cached_status = status;
387  break;
388  }
389 
390  {
391  struct thread_resume resume;
392 
393  resume.thread = minus_one_ptid;
394  resume.kind = resume_continue;
395  resume.sig = 0;
396 
397  win32_resume (&resume, 1);
398  }
399  }
400 
401 #ifndef _WIN32_WCE
402  /* Now that the inferior has been started and all DLLs have been mapped,
403  we can iterate over all DLLs and load them in.
404 
405  We avoid doing it any earlier because, on certain versions of Windows,
406  LOAD_DLL_DEBUG_EVENTs are sometimes not complete. In particular,
407  we have seen on Windows 8.1 that the ntdll.dll load event does not
408  include the DLL name, preventing us from creating an associated SO.
409  A possible explanation is that ntdll.dll might be mapped before
410  the SO info gets created by the Windows system -- ntdll.dll is
411  the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs
412  do not seem to suffer from that problem.
413 
414  Rather than try to work around this sort of issue, it is much
415  simpler to just ignore DLL load/unload events during the startup
416  phase, and then process them all in one batch now. */
418 #endif
419 
421 }
422 
423 /* Resume all artificially suspended threads if we are continuing
424  execution. */
425 static void
427 {
429 
430  if (thread_id == -1 || thread_id == th->tid)
431  {
433 
434  if (th->suspended)
435  {
436  if (th->context.ContextFlags)
437  {
439  th->context.ContextFlags = 0;
440  }
441 
442  if (ResumeThread (th->h) == (DWORD) -1)
443  {
444  DWORD err = GetLastError ();
445  OUTMSG (("warning: ResumeThread failed in continue_one_thread, "
446  "(error %d): %s\n", (int) err, strwinerror (err)));
447  }
448  th->suspended = 0;
449  }
450  }
451 }
452 
453 static BOOL
454 child_continue (DWORD continue_status, int thread_id)
455 {
456  /* The inferior will only continue after the ContinueDebugEvent
457  call. */
459  {
460  continue_one_thread (thread, thread_id);
461  });
462  faked_breakpoint = 0;
463 
464  if (!ContinueDebugEvent (current_event.dwProcessId,
465  current_event.dwThreadId,
466  continue_status))
467  return FALSE;
468 
469  return TRUE;
470 }
471 
472 /* Fetch register(s) from the current thread context. */
473 static void
475 {
476  int regno;
478  if (r == -1 || r > NUM_REGS)
480  else
481  for (regno = 0; regno < r; regno++)
482  (*the_low_target.fetch_inferior_register) (regcache, th, regno);
483 }
484 
485 /* Store a new register value into the current thread context. We don't
486  change the program's context until later, when we resume it. */
487 static void
489 {
490  int regno;
492  if (r == -1 || r == 0 || r > NUM_REGS)
494  else
495  for (regno = 0; regno < r; regno++)
496  (*the_low_target.store_inferior_register) (regcache, th, regno);
497 }
498 
499 /* Map the Windows error number in ERROR to a locale-dependent error
500  message string and return a pointer to it. Typically, the values
501  for ERROR come from GetLastError.
502 
503  The string pointed to shall not be modified by the application,
504  but may be overwritten by a subsequent call to strwinerror
505 
506  The strwinerror function does not change the current setting
507  of GetLastError. */
508 
509 char *
511 {
512  static char buf[1024];
513  TCHAR *msgbuf;
514  DWORD lasterr = GetLastError ();
515  DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
516  | FORMAT_MESSAGE_ALLOCATE_BUFFER,
517  NULL,
518  error,
519  0, /* Default language */
520  (LPTSTR) &msgbuf,
521  0,
522  NULL);
523  if (chars != 0)
524  {
525  /* If there is an \r\n appended, zap it. */
526  if (chars >= 2
527  && msgbuf[chars - 2] == '\r'
528  && msgbuf[chars - 1] == '\n')
529  {
530  chars -= 2;
531  msgbuf[chars] = 0;
532  }
533 
534  if (chars > ((COUNTOF (buf)) - 1))
535  {
536  chars = COUNTOF (buf) - 1;
537  msgbuf [chars] = 0;
538  }
539 
540 #ifdef UNICODE
541  wcstombs (buf, msgbuf, chars + 1);
542 #else
543  strncpy (buf, msgbuf, chars + 1);
544 #endif
545  LocalFree (msgbuf);
546  }
547  else
548  sprintf (buf, "unknown win32 error (%u)", (unsigned) error);
549 
550  SetLastError (lasterr);
551  return buf;
552 }
553 
554 static BOOL
555 create_process (const char *program, char *args,
556  DWORD flags, PROCESS_INFORMATION *pi)
557 {
558  const char *inferior_cwd = get_inferior_cwd ();
559  std::string expanded_infcwd = gdb_tilde_expand (inferior_cwd);
560  BOOL ret;
561 
562 #ifdef _WIN32_WCE
563  wchar_t *p, *wprogram, *wargs, *wcwd = NULL;
564  size_t argslen;
565 
566  wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
567  mbstowcs (wprogram, program, strlen (program) + 1);
568 
569  for (p = wprogram; *p; ++p)
570  if (L'/' == *p)
571  *p = L'\\';
572 
573  argslen = strlen (args);
574  wargs = alloca ((argslen + 1) * sizeof (wchar_t));
575  mbstowcs (wargs, args, argslen + 1);
576 
577  if (inferior_cwd != NULL)
578  {
579  std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
580  '/', '\\');
581  wcwd = alloca ((expanded_infcwd.size () + 1) * sizeof (wchar_t));
582  if (mbstowcs (wcwd, expanded_infcwd.c_str (),
583  expanded_infcwd.size () + 1) == NULL)
584  {
585  error (_("\
586 Could not convert the expanded inferior cwd to wide-char."));
587  }
588  }
589 
590  ret = CreateProcessW (wprogram, /* image name */
591  wargs, /* command line */
592  NULL, /* security, not supported */
593  NULL, /* thread, not supported */
594  FALSE, /* inherit handles, not supported */
595  flags, /* start flags */
596  NULL, /* environment, not supported */
597  wcwd, /* current directory */
598  NULL, /* start info, not supported */
599  pi); /* proc info */
600 #else
601  STARTUPINFOA si = { sizeof (STARTUPINFOA) };
602 
603  ret = CreateProcessA (program, /* image name */
604  args, /* command line */
605  NULL, /* security */
606  NULL, /* thread */
607  TRUE, /* inherit handles */
608  flags, /* start flags */
609  NULL, /* environment */
610  expanded_infcwd.c_str (), /* current directory */
611  &si, /* start info */
612  pi); /* proc info */
613 #endif
614 
615  return ret;
616 }
617 
618 /* Start a new process.
619  PROGRAM is the program name.
620  PROGRAM_ARGS is the vector containing the inferior's args.
621  Returns the new PID on success, -1 on failure. Registers the new
622  process with the process list. */
623 static int
624 win32_create_inferior (const char *program,
625  const std::vector<char *> &program_args)
626 {
627 #ifndef USE_WIN32API
628  char real_path[PATH_MAX];
629  char *orig_path, *new_path, *path_ptr;
630 #endif
631  BOOL ret;
632  DWORD flags;
633  int argslen;
634  int argc;
635  PROCESS_INFORMATION pi;
636  DWORD err;
637  std::string str_program_args = stringify_argv (program_args);
638  char *args = (char *) str_program_args.c_str ();
639 
640  /* win32_wait needs to know we're not attaching. */
641  attaching = 0;
642 
643  if (!program)
644  error ("No executable specified, specify executable to debug.\n");
645 
646  flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
647 
648 #ifndef USE_WIN32API
649  orig_path = NULL;
650  path_ptr = getenv ("PATH");
651  if (path_ptr)
652  {
653  int size = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, NULL, 0);
654  orig_path = (char *) alloca (strlen (path_ptr) + 1);
655  new_path = (char *) alloca (size);
656  strcpy (orig_path, path_ptr);
657  cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, new_path, size);
658  setenv ("PATH", new_path, 1);
659  }
660  cygwin_conv_path (CCP_POSIX_TO_WIN_A, program, real_path, PATH_MAX);
661  program = real_path;
662 #endif
663 
664  OUTMSG2 (("Command line is \"%s\"\n", args));
665 
666 #ifdef CREATE_NEW_PROCESS_GROUP
667  flags |= CREATE_NEW_PROCESS_GROUP;
668 #endif
669 
670  ret = create_process (program, args, flags, &pi);
671  err = GetLastError ();
672  if (!ret && err == ERROR_FILE_NOT_FOUND)
673  {
674  char *exename = (char *) alloca (strlen (program) + 5);
675  strcat (strcpy (exename, program), ".exe");
676  ret = create_process (exename, args, flags, &pi);
677  err = GetLastError ();
678  }
679 
680 #ifndef USE_WIN32API
681  if (orig_path)
682  setenv ("PATH", orig_path, 1);
683 #endif
684 
685  if (!ret)
686  {
687  error ("Error creating process \"%s%s\", (error %d): %s\n",
688  program, args, (int) err, strwinerror (err));
689  }
690  else
691  {
692  OUTMSG2 (("Process created: %s\n", (char *) args));
693  }
694 
695 #ifndef _WIN32_WCE
696  /* On Windows CE this handle can't be closed. The OS reuses
697  it in the debug events, while the 9x/NT versions of Windows
698  probably use a DuplicateHandle'd one. */
699  CloseHandle (pi.hThread);
700 #endif
701 
702  do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
703 
704  return current_process_id;
705 }
706 
707 /* Attach to a running process.
708  PID is the process ID to attach to, specified by the user
709  or a higher layer. */
710 static int
711 win32_attach (unsigned long pid)
712 {
713  HANDLE h;
714  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
715  DWORD err;
716 #ifdef _WIN32_WCE
717  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
718 #else
719  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
720 #endif
721  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
722 
723  h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
724  if (h != NULL)
725  {
726  if (DebugActiveProcess (pid))
727  {
728  if (DebugSetProcessKillOnExit != NULL)
729  DebugSetProcessKillOnExit (FALSE);
730 
731  /* win32_wait needs to know we're attaching. */
732  attaching = 1;
733  do_initial_child_stuff (h, pid, 1);
734  return 0;
735  }
736 
737  CloseHandle (h);
738  }
739 
740  err = GetLastError ();
741  error ("Attach to process failed (error %d): %s\n",
742  (int) err, strwinerror (err));
743 }
744 
745 /* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
746 static void
748 {
749 #define READ_BUFFER_LEN 1024
750  CORE_ADDR addr;
751  char s[READ_BUFFER_LEN + 1] = { 0 };
752  DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
753 
754  if (nbytes == 0)
755  return;
756 
757  if (nbytes > READ_BUFFER_LEN)
758  nbytes = READ_BUFFER_LEN;
759 
760  addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
761 
762  if (current_event.u.DebugString.fUnicode)
763  {
764  /* The event tells us how many bytes, not chars, even
765  in Unicode. */
766  WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
767  if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
768  return;
769  wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
770  }
771  else
772  {
773  if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
774  return;
775  }
776 
777  if (!startswith (s, "cYg"))
778  {
779  if (!server_waiting)
780  {
781  OUTMSG2(("%s", s));
782  return;
783  }
784 
785  monitor_output (s);
786  }
787 #undef READ_BUFFER_LEN
788 }
789 
790 static void
792 {
793  if (current_process_handle != NULL)
794  CloseHandle (current_process_handle);
795 
797  clear_inferiors ();
798 }
799 
800 /* Kill all inferiors. */
801 static int
802 win32_kill (int pid)
803 {
804  struct process_info *process;
805 
806  if (current_process_handle == NULL)
807  return -1;
808 
809  TerminateProcess (current_process_handle, 0);
810  for (;;)
811  {
812  if (!child_continue (DBG_CONTINUE, -1))
813  break;
814  if (!WaitForDebugEvent (&current_event, INFINITE))
815  break;
816  if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
817  break;
818  else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
820  }
821 
823 
824  process = find_process_pid (pid);
825  remove_process (process);
826  return 0;
827 }
828 
829 /* Detach from inferior PID. */
830 static int
832 {
833  struct process_info *process;
834  winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
835  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
836 #ifdef _WIN32_WCE
837  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
838 #else
839  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
840 #endif
841  DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
842  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
843 
844  if (DebugSetProcessKillOnExit == NULL
845  || DebugActiveProcessStop == NULL)
846  return -1;
847 
848  {
849  struct thread_resume resume;
850  resume.thread = minus_one_ptid;
851  resume.kind = resume_continue;
852  resume.sig = 0;
853  win32_resume (&resume, 1);
854  }
855 
856  if (!DebugActiveProcessStop (current_process_id))
857  return -1;
858 
859  DebugSetProcessKillOnExit (FALSE);
860  process = find_process_pid (pid);
861  remove_process (process);
862 
864  return 0;
865 }
866 
867 static void
868 win32_mourn (struct process_info *process)
869 {
870  remove_process (process);
871 }
872 
873 /* Wait for inferiors to end. */
874 static void
875 win32_join (int pid)
876 {
877  HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
878  if (h != NULL)
879  {
880  WaitForSingleObject (h, INFINITE);
881  CloseHandle (h);
882  }
883 }
884 
885 /* Return 1 iff the thread with thread ID TID is alive. */
886 static int
888 {
889  /* Our thread list is reliable; don't bother to poll target
890  threads. */
891  return find_thread_ptid (ptid) != NULL;
892 }
893 
894 /* Resume the inferior process. RESUME_INFO describes how we want
895  to resume. */
896 static void
897 win32_resume (struct thread_resume *resume_info, size_t n)
898 {
899  DWORD tid;
900  enum gdb_signal sig;
901  int step;
902  win32_thread_info *th;
903  DWORD continue_status = DBG_CONTINUE;
904  ptid_t ptid;
905 
906  /* This handles the very limited set of resume packets that GDB can
907  currently produce. */
908 
909  if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
910  tid = -1;
911  else if (n > 1)
912  tid = -1;
913  else
914  /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
915  the Windows resume code do the right thing for thread switching. */
916  tid = current_event.dwThreadId;
917 
918  if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
919  {
920  sig = gdb_signal_from_host (resume_info[0].sig);
921  step = resume_info[0].kind == resume_step;
922  }
923  else
924  {
925  sig = GDB_SIGNAL_0;
926  step = 0;
927  }
928 
929  if (sig != GDB_SIGNAL_0)
930  {
931  if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
932  {
933  OUTMSG (("Cannot continue with signal %s here.\n",
935  }
936  else if (sig == last_sig)
937  continue_status = DBG_EXCEPTION_NOT_HANDLED;
938  else
939  OUTMSG (("Can only continue with received signal %s.\n",
941  }
942 
943  last_sig = GDB_SIGNAL_0;
944 
945  /* Get context for the currently selected thread. */
947  th = thread_rec (ptid, FALSE);
948  if (th)
949  {
951 
952  if (th->context.ContextFlags)
953  {
954  /* Move register values from the inferior into the thread
955  context structure. */
957 
958  if (step)
959  {
960  if (the_low_target.single_step != NULL)
961  (*the_low_target.single_step) (th);
962  else
963  error ("Single stepping is not supported "
964  "in this configuration.\n");
965  }
966 
968  th->context.ContextFlags = 0;
969  }
970  }
971 
972  /* Allow continuing with the same signal that interrupted us.
973  Otherwise complain. */
974 
975  child_continue (continue_status, tid);
976 }
977 
978 static void
979 win32_add_one_solib (const char *name, CORE_ADDR load_addr)
980 {
981  char buf[MAX_PATH + 1];
982  char buf2[MAX_PATH + 1];
983 
984 #ifdef _WIN32_WCE
985  WIN32_FIND_DATA w32_fd;
986  WCHAR wname[MAX_PATH + 1];
987  mbstowcs (wname, name, MAX_PATH);
988  HANDLE h = FindFirstFile (wname, &w32_fd);
989 #else
990  WIN32_FIND_DATAA w32_fd;
991  HANDLE h = FindFirstFileA (name, &w32_fd);
992 #endif
993 
994  /* The symbols in a dll are offset by 0x1000, which is the
995  offset from 0 of the first byte in an image - because
996  of the file header and the section alignment. */
997  load_addr += 0x1000;
998 
999  if (h == INVALID_HANDLE_VALUE)
1000  strcpy (buf, name);
1001  else
1002  {
1003  FindClose (h);
1004  strcpy (buf, name);
1005 #ifndef _WIN32_WCE
1006  {
1007  char cwd[MAX_PATH + 1];
1008  char *p;
1009  if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
1010  {
1011  p = strrchr (buf, '\\');
1012  if (p)
1013  p[1] = '\0';
1014  SetCurrentDirectoryA (buf);
1015  GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
1016  SetCurrentDirectoryA (cwd);
1017  }
1018  }
1019 #endif
1020  }
1021 
1022 #ifndef _WIN32_WCE
1023  if (strcasecmp (buf, "ntdll.dll") == 0)
1024  {
1025  GetSystemDirectoryA (buf, sizeof (buf));
1026  strcat (buf, "\\ntdll.dll");
1027  }
1028 #endif
1029 
1030 #ifdef __CYGWIN__
1031  cygwin_conv_path (CCP_WIN_A_TO_POSIX, buf, buf2, sizeof (buf2));
1032 #else
1033  strcpy (buf2, buf);
1034 #endif
1035 
1036  loaded_dll (buf2, load_addr);
1037 }
1038 
1039 static char *
1040 get_image_name (HANDLE h, void *address, int unicode)
1041 {
1042  static char buf[(2 * MAX_PATH) + 1];
1043  DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
1044  char *address_ptr;
1045  int len = 0;
1046  char b[2];
1047  SIZE_T done;
1048 
1049  /* Attempt to read the name of the dll that was detected.
1050  This is documented to work only when actively debugging
1051  a program. It will not work for attached processes. */
1052  if (address == NULL)
1053  return NULL;
1054 
1055 #ifdef _WIN32_WCE
1056  /* Windows CE reports the address of the image name,
1057  instead of an address of a pointer into the image name. */
1058  address_ptr = address;
1059 #else
1060  /* See if we could read the address of a string, and that the
1061  address isn't null. */
1062  if (!ReadProcessMemory (h, address, &address_ptr,
1063  sizeof (address_ptr), &done)
1064  || done != sizeof (address_ptr)
1065  || !address_ptr)
1066  return NULL;
1067 #endif
1068 
1069  /* Find the length of the string */
1070  while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
1071  && (b[0] != 0 || b[size - 1] != 0) && done == size)
1072  continue;
1073 
1074  if (!unicode)
1075  ReadProcessMemory (h, address_ptr, buf, len, &done);
1076  else
1077  {
1078  WCHAR *unicode_address = XALLOCAVEC (WCHAR, len);
1079  ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
1080  &done);
1081 
1082  WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
1083  }
1084 
1085  return buf;
1086 }
1087 
1088 typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
1089  DWORD, LPDWORD);
1090 typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
1091  LPMODULEINFO, DWORD);
1092 typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
1093  LPSTR, DWORD);
1094 
1098 
1099 static BOOL
1101 {
1102  static int psapi_loaded = 0;
1103  static HMODULE dll = NULL;
1104 
1105  if (!psapi_loaded)
1106  {
1107  psapi_loaded = 1;
1108  dll = LoadLibrary (TEXT("psapi.dll"));
1109  if (!dll)
1110  return FALSE;
1112  GETPROCADDRESS (dll, EnumProcessModules);
1114  GETPROCADDRESS (dll, GetModuleInformation);
1116  GETPROCADDRESS (dll, GetModuleFileNameExA);
1117  }
1118 
1119  return (win32_EnumProcessModules != NULL
1120  && win32_GetModuleInformation != NULL
1121  && win32_GetModuleFileNameExA != NULL);
1122 }
1123 
1124 #ifndef _WIN32_WCE
1125 
1126 /* Iterate over all DLLs currently mapped by our inferior, and
1127  add them to our list of solibs. */
1128 
1129 static void
1131 {
1132  size_t i;
1133  HMODULE dh_buf[1];
1134  HMODULE *DllHandle = dh_buf;
1135  DWORD cbNeeded;
1136  BOOL ok;
1137 
1138  if (!load_psapi ())
1139  return;
1140 
1141  cbNeeded = 0;
1142  ok = (*win32_EnumProcessModules) (current_process_handle,
1143  DllHandle,
1144  sizeof (HMODULE),
1145  &cbNeeded);
1146 
1147  if (!ok || !cbNeeded)
1148  return;
1149 
1150  DllHandle = (HMODULE *) alloca (cbNeeded);
1151  if (!DllHandle)
1152  return;
1153 
1154  ok = (*win32_EnumProcessModules) (current_process_handle,
1155  DllHandle,
1156  cbNeeded,
1157  &cbNeeded);
1158  if (!ok)
1159  return;
1160 
1161  for (i = 1; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
1162  {
1163  MODULEINFO mi;
1164  char dll_name[MAX_PATH];
1165 
1167  DllHandle[i],
1168  &mi,
1169  sizeof (mi)))
1170  continue;
1172  DllHandle[i],
1173  dll_name,
1174  MAX_PATH) == 0)
1175  continue;
1176  win32_add_one_solib (dll_name, (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll);
1177  }
1178 }
1179 #endif
1180 
1181 typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
1182 typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
1183 typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
1184 
1185 /* Handle a DLL load event.
1186 
1187  This function assumes that this event did not occur during inferior
1188  initialization, where their event info may be incomplete (see
1189  do_initial_child_stuff and win32_add_all_dlls for more info on
1190  how we handle DLL loading during that phase). */
1191 
1192 static void
1194 {
1195  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1196  char *dll_name;
1197 
1199  event->lpImageName, event->fUnicode);
1200  if (!dll_name)
1201  return;
1202 
1203  win32_add_one_solib (dll_name, (CORE_ADDR) (uintptr_t) event->lpBaseOfDll);
1204 }
1205 
1206 /* Handle a DLL unload event.
1207 
1208  This function assumes that this event did not occur during inferior
1209  initialization, where their event info may be incomplete (see
1210  do_initial_child_stuff and win32_add_one_solib for more info
1211  on how we handle DLL loading during that phase). */
1212 
1213 static void
1215 {
1216  CORE_ADDR load_addr =
1217  (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
1218 
1219  /* The symbols in a dll are offset by 0x1000, which is the
1220  offset from 0 of the first byte in an image - because
1221  of the file header and the section alignment. */
1222  load_addr += 0x1000;
1223  unloaded_dll (NULL, load_addr);
1224 }
1225 
1226 static void
1227 handle_exception (struct target_waitstatus *ourstatus)
1228 {
1229  DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1230 
1231  ourstatus->kind = TARGET_WAITKIND_STOPPED;
1232 
1233  switch (code)
1234  {
1235  case EXCEPTION_ACCESS_VIOLATION:
1236  OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
1237  ourstatus->value.sig = GDB_SIGNAL_SEGV;
1238  break;
1239  case STATUS_STACK_OVERFLOW:
1240  OUTMSG2 (("STATUS_STACK_OVERFLOW"));
1241  ourstatus->value.sig = GDB_SIGNAL_SEGV;
1242  break;
1243  case STATUS_FLOAT_DENORMAL_OPERAND:
1244  OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
1245  ourstatus->value.sig = GDB_SIGNAL_FPE;
1246  break;
1247  case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1248  OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
1249  ourstatus->value.sig = GDB_SIGNAL_FPE;
1250  break;
1251  case STATUS_FLOAT_INEXACT_RESULT:
1252  OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
1253  ourstatus->value.sig = GDB_SIGNAL_FPE;
1254  break;
1255  case STATUS_FLOAT_INVALID_OPERATION:
1256  OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
1257  ourstatus->value.sig = GDB_SIGNAL_FPE;
1258  break;
1259  case STATUS_FLOAT_OVERFLOW:
1260  OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
1261  ourstatus->value.sig = GDB_SIGNAL_FPE;
1262  break;
1263  case STATUS_FLOAT_STACK_CHECK:
1264  OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
1265  ourstatus->value.sig = GDB_SIGNAL_FPE;
1266  break;
1267  case STATUS_FLOAT_UNDERFLOW:
1268  OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
1269  ourstatus->value.sig = GDB_SIGNAL_FPE;
1270  break;
1271  case STATUS_FLOAT_DIVIDE_BY_ZERO:
1272  OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
1273  ourstatus->value.sig = GDB_SIGNAL_FPE;
1274  break;
1275  case STATUS_INTEGER_DIVIDE_BY_ZERO:
1276  OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
1277  ourstatus->value.sig = GDB_SIGNAL_FPE;
1278  break;
1279  case STATUS_INTEGER_OVERFLOW:
1280  OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
1281  ourstatus->value.sig = GDB_SIGNAL_FPE;
1282  break;
1283  case EXCEPTION_BREAKPOINT:
1284  OUTMSG2 (("EXCEPTION_BREAKPOINT"));
1285  ourstatus->value.sig = GDB_SIGNAL_TRAP;
1286 #ifdef _WIN32_WCE
1287  /* Remove the initial breakpoint. */
1289  .u.Exception.ExceptionRecord.ExceptionAddress);
1290 #endif
1291  break;
1292  case DBG_CONTROL_C:
1293  OUTMSG2 (("DBG_CONTROL_C"));
1294  ourstatus->value.sig = GDB_SIGNAL_INT;
1295  break;
1296  case DBG_CONTROL_BREAK:
1297  OUTMSG2 (("DBG_CONTROL_BREAK"));
1298  ourstatus->value.sig = GDB_SIGNAL_INT;
1299  break;
1300  case EXCEPTION_SINGLE_STEP:
1301  OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
1302  ourstatus->value.sig = GDB_SIGNAL_TRAP;
1303  break;
1304  case EXCEPTION_ILLEGAL_INSTRUCTION:
1305  OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
1306  ourstatus->value.sig = GDB_SIGNAL_ILL;
1307  break;
1308  case EXCEPTION_PRIV_INSTRUCTION:
1309  OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
1310  ourstatus->value.sig = GDB_SIGNAL_ILL;
1311  break;
1312  case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1313  OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
1314  ourstatus->value.sig = GDB_SIGNAL_ILL;
1315  break;
1316  default:
1317  if (current_event.u.Exception.dwFirstChance)
1318  {
1319  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1320  return;
1321  }
1322  OUTMSG2 (("gdbserver: unknown target exception 0x%08x at 0x%s",
1323  (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
1324  phex_nz ((uintptr_t) current_event.u.Exception.ExceptionRecord.
1325  ExceptionAddress, sizeof (uintptr_t))));
1326  ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
1327  break;
1328  }
1329  OUTMSG2 (("\n"));
1330  last_sig = ourstatus->value.sig;
1331 }
1332 
1333 
1334 static void
1336 {
1338 
1339  if (!th->suspended)
1340  {
1341  if (SuspendThread (th->h) == (DWORD) -1)
1342  {
1343  DWORD err = GetLastError ();
1344  OUTMSG (("warning: SuspendThread failed in suspend_one_thread, "
1345  "(error %d): %s\n", (int) err, strwinerror (err)));
1346  }
1347  else
1348  th->suspended = 1;
1349  }
1350 }
1351 
1352 static void
1354 {
1355  OUTMSG2(("fake_breakpoint_event\n"));
1356 
1357  faked_breakpoint = 1;
1358 
1359  memset (&current_event, 0, sizeof (current_event));
1360  current_event.dwThreadId = main_thread_id;
1361  current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
1362  current_event.u.Exception.ExceptionRecord.ExceptionCode
1363  = EXCEPTION_BREAKPOINT;
1364 
1366 }
1367 
1368 #ifdef _WIN32_WCE
1369 static int
1370 auto_delete_breakpoint (CORE_ADDR stop_pc)
1371 {
1372  return 1;
1373 }
1374 #endif
1375 
1376 /* Get the next event from the child. */
1377 
1378 static int
1379 get_child_debug_event (struct target_waitstatus *ourstatus)
1380 {
1381  ptid_t ptid;
1382 
1383  last_sig = GDB_SIGNAL_0;
1384  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1385 
1386  /* Check if GDB sent us an interrupt request. */
1388 
1390  {
1393  goto gotevent;
1394  }
1395 
1396 #ifndef _WIN32_WCE
1397  attaching = 0;
1398 #else
1399  if (attaching)
1400  {
1401  /* WinCE doesn't set an initial breakpoint automatically. To
1402  stop the inferior, we flush all currently pending debug
1403  events -- the thread list and the dll list are always
1404  reported immediatelly without delay, then, we suspend all
1405  threads and pretend we saw a trap at the current PC of the
1406  main thread.
1407 
1408  Contrary to desktop Windows, Windows CE *does* report the dll
1409  names on LOAD_DLL_DEBUG_EVENTs resulting from a
1410  DebugActiveProcess call. This limits the way we can detect
1411  if all the dlls have already been reported. If we get a real
1412  debug event before leaving attaching, the worst that will
1413  happen is the user will see a spurious breakpoint. */
1414 
1415  current_event.dwDebugEventCode = 0;
1416  if (!WaitForDebugEvent (&current_event, 0))
1417  {
1418  OUTMSG2(("no attach events left\n"));
1420  attaching = 0;
1421  }
1422  else
1423  OUTMSG2(("got attach event\n"));
1424  }
1425  else
1426 #endif
1427  {
1428  /* Keep the wait time low enough for confortable remote
1429  interruption, but high enough so gdbserver doesn't become a
1430  bottleneck. */
1431  if (!WaitForDebugEvent (&current_event, 250))
1432  {
1433  DWORD e = GetLastError();
1434 
1435  if (e == ERROR_PIPE_NOT_CONNECTED)
1436  {
1437  /* This will happen if the loader fails to succesfully
1438  load the application, e.g., if the main executable
1439  tries to pull in a non-existing export from a
1440  DLL. */
1441  ourstatus->kind = TARGET_WAITKIND_EXITED;
1442  ourstatus->value.integer = 1;
1443  return 1;
1444  }
1445 
1446  return 0;
1447  }
1448  }
1449 
1450  gotevent:
1451 
1452  switch (current_event.dwDebugEventCode)
1453  {
1454  case CREATE_THREAD_DEBUG_EVENT:
1455  OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
1456  "for pid=%u tid=%x)\n",
1457  (unsigned) current_event.dwProcessId,
1458  (unsigned) current_event.dwThreadId));
1459 
1460  /* Record the existence of this thread. */
1461  child_add_thread (current_event.dwProcessId,
1462  current_event.dwThreadId,
1463  current_event.u.CreateThread.hThread,
1464  current_event.u.CreateThread.lpThreadLocalBase);
1465  break;
1466 
1467  case EXIT_THREAD_DEBUG_EVENT:
1468  OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
1469  "for pid=%u tid=%x\n",
1470  (unsigned) current_event.dwProcessId,
1471  (unsigned) current_event.dwThreadId));
1472  child_delete_thread (current_event.dwProcessId,
1473  current_event.dwThreadId);
1474 
1476  return 1;
1477 
1478  case CREATE_PROCESS_DEBUG_EVENT:
1479  OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
1480  "for pid=%u tid=%x\n",
1481  (unsigned) current_event.dwProcessId,
1482  (unsigned) current_event.dwThreadId));
1483  CloseHandle (current_event.u.CreateProcessInfo.hFile);
1484 
1485  current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1486  main_thread_id = current_event.dwThreadId;
1487 
1488  /* Add the main thread. */
1489  child_add_thread (current_event.dwProcessId,
1491  current_event.u.CreateProcessInfo.hThread,
1492  current_event.u.CreateProcessInfo.lpThreadLocalBase);
1493 
1494 #ifdef _WIN32_WCE
1495  if (!attaching)
1496  {
1497  /* Windows CE doesn't set the initial breakpoint
1498  automatically like the desktop versions of Windows do.
1499  We add it explicitly here. It will be removed as soon as
1500  it is hit. */
1502  .CreateProcessInfo.lpStartAddress,
1503  auto_delete_breakpoint);
1504  }
1505 #endif
1506  break;
1507 
1508  case EXIT_PROCESS_DEBUG_EVENT:
1509  OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
1510  "for pid=%u tid=%x\n",
1511  (unsigned) current_event.dwProcessId,
1512  (unsigned) current_event.dwThreadId));
1513  ourstatus->kind = TARGET_WAITKIND_EXITED;
1514  ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1515  child_continue (DBG_CONTINUE, -1);
1516  CloseHandle (current_process_handle);
1517  current_process_handle = NULL;
1518  break;
1519 
1520  case LOAD_DLL_DEBUG_EVENT:
1521  OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
1522  "for pid=%u tid=%x\n",
1523  (unsigned) current_event.dwProcessId,
1524  (unsigned) current_event.dwThreadId));
1525  CloseHandle (current_event.u.LoadDll.hFile);
1527  break;
1528  handle_load_dll ();
1529 
1530  ourstatus->kind = TARGET_WAITKIND_LOADED;
1531  ourstatus->value.sig = GDB_SIGNAL_TRAP;
1532  break;
1533 
1534  case UNLOAD_DLL_DEBUG_EVENT:
1535  OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
1536  "for pid=%u tid=%x\n",
1537  (unsigned) current_event.dwProcessId,
1538  (unsigned) current_event.dwThreadId));
1540  break;
1541  handle_unload_dll ();
1542  ourstatus->kind = TARGET_WAITKIND_LOADED;
1543  ourstatus->value.sig = GDB_SIGNAL_TRAP;
1544  break;
1545 
1546  case EXCEPTION_DEBUG_EVENT:
1547  OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
1548  "for pid=%u tid=%x\n",
1549  (unsigned) current_event.dwProcessId,
1550  (unsigned) current_event.dwThreadId));
1551  handle_exception (ourstatus);
1552  break;
1553 
1554  case OUTPUT_DEBUG_STRING_EVENT:
1555  /* A message from the kernel (or Cygwin). */
1556  OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
1557  "for pid=%u tid=%x\n",
1558  (unsigned) current_event.dwProcessId,
1559  (unsigned) current_event.dwThreadId));
1561  break;
1562 
1563  default:
1564  OUTMSG2 (("gdbserver: kernel event unknown "
1565  "for pid=%u tid=%x code=%x\n",
1566  (unsigned) current_event.dwProcessId,
1567  (unsigned) current_event.dwThreadId,
1568  (unsigned) current_event.dwDebugEventCode));
1569  break;
1570  }
1571 
1572  ptid = debug_event_ptid (&current_event);
1574  return 1;
1575 }
1576 
1577 /* Wait for the inferior process to change state.
1578  STATUS will be filled in with a response code to send to GDB.
1579  Returns the signal which caused the process to stop. */
1580 static ptid_t
1581 win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
1582 {
1583  struct regcache *regcache;
1584 
1585  if (cached_status.kind != TARGET_WAITKIND_IGNORE)
1586  {
1587  /* The core always does a wait after creating the inferior, and
1588  do_initial_child_stuff already ran the inferior to the
1589  initial breakpoint (or an exit, if creating the process
1590  fails). Report it now. */
1591  *ourstatus = cached_status;
1592  cached_status.kind = TARGET_WAITKIND_IGNORE;
1593  return debug_event_ptid (&current_event);
1594  }
1595 
1596  while (1)
1597  {
1598  if (!get_child_debug_event (ourstatus))
1599  continue;
1600 
1601  switch (ourstatus->kind)
1602  {
1603  case TARGET_WAITKIND_EXITED:
1604  OUTMSG2 (("Child exited with retcode = %x\n",
1605  ourstatus->value.integer));
1607  return pid_to_ptid (current_event.dwProcessId);
1608  case TARGET_WAITKIND_STOPPED:
1609  case TARGET_WAITKIND_LOADED:
1610  OUTMSG2 (("Child Stopped with signal = %d \n",
1611  ourstatus->value.sig));
1612 
1615  return debug_event_ptid (&current_event);
1616  default:
1617  OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
1618  /* fall-through */
1619  case TARGET_WAITKIND_SPURIOUS:
1620  /* do nothing, just continue */
1621  child_continue (DBG_CONTINUE, -1);
1622  break;
1623  }
1624  }
1625 }
1626 
1627 /* Fetch registers from the inferior process.
1628  If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1629 static void
1631 {
1633 }
1634 
1635 /* Store registers to the inferior process.
1636  If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1637 static void
1639 {
1641 }
1642 
1643 /* Read memory from the inferior process. This should generally be
1644  called through read_inferior_memory, which handles breakpoint shadowing.
1645  Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1646 static int
1647 win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
1648 {
1649  return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
1650 }
1651 
1652 /* Write memory to the inferior process. This should generally be
1653  called through write_inferior_memory, which handles breakpoint shadowing.
1654  Write LEN bytes from the buffer at MYADDR to MEMADDR.
1655  Returns 0 on success and errno on failure. */
1656 static int
1657 win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
1658  int len)
1659 {
1660  return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1661 }
1662 
1663 /* Send an interrupt request to the inferior process. */
1664 static void
1666 {
1667  winapi_DebugBreakProcess DebugBreakProcess;
1668  winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
1669 
1670 #ifdef _WIN32_WCE
1671  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
1672 #else
1673  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
1674 #endif
1675 
1676  GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
1677 
1678  if (GenerateConsoleCtrlEvent != NULL
1679  && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
1680  return;
1681 
1682  /* GenerateConsoleCtrlEvent can fail if process id being debugged is
1683  not a process group id.
1684  Fallback to XP/Vista 'DebugBreakProcess', which generates a
1685  breakpoint exception in the interior process. */
1686 
1687  DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
1688 
1689  if (DebugBreakProcess != NULL
1690  && DebugBreakProcess (current_process_handle))
1691  return;
1692 
1693  /* Last resort, suspend all threads manually. */
1695 }
1696 
1697 #ifdef _WIN32_WCE
1698 int
1699 win32_error_to_fileio_error (DWORD err)
1700 {
1701  switch (err)
1702  {
1703  case ERROR_BAD_PATHNAME:
1704  case ERROR_FILE_NOT_FOUND:
1705  case ERROR_INVALID_NAME:
1706  case ERROR_PATH_NOT_FOUND:
1707  return FILEIO_ENOENT;
1708  case ERROR_CRC:
1709  case ERROR_IO_DEVICE:
1710  case ERROR_OPEN_FAILED:
1711  return FILEIO_EIO;
1712  case ERROR_INVALID_HANDLE:
1713  return FILEIO_EBADF;
1714  case ERROR_ACCESS_DENIED:
1715  case ERROR_SHARING_VIOLATION:
1716  return FILEIO_EACCES;
1717  case ERROR_NOACCESS:
1718  return FILEIO_EFAULT;
1719  case ERROR_BUSY:
1720  return FILEIO_EBUSY;
1721  case ERROR_ALREADY_EXISTS:
1722  case ERROR_FILE_EXISTS:
1723  return FILEIO_EEXIST;
1724  case ERROR_BAD_DEVICE:
1725  return FILEIO_ENODEV;
1726  case ERROR_DIRECTORY:
1727  return FILEIO_ENOTDIR;
1728  case ERROR_FILENAME_EXCED_RANGE:
1729  case ERROR_INVALID_DATA:
1730  case ERROR_INVALID_PARAMETER:
1731  case ERROR_NEGATIVE_SEEK:
1732  return FILEIO_EINVAL;
1733  case ERROR_TOO_MANY_OPEN_FILES:
1734  return FILEIO_EMFILE;
1735  case ERROR_HANDLE_DISK_FULL:
1736  case ERROR_DISK_FULL:
1737  return FILEIO_ENOSPC;
1738  case ERROR_WRITE_PROTECT:
1739  return FILEIO_EROFS;
1740  case ERROR_NOT_SUPPORTED:
1741  return FILEIO_ENOSYS;
1742  }
1743 
1744  return FILEIO_EUNKNOWN;
1745 }
1746 
1747 static void
1748 wince_hostio_last_error (char *buf)
1749 {
1750  DWORD winerr = GetLastError ();
1751  int fileio_err = win32_error_to_fileio_error (winerr);
1752  sprintf (buf, "F-1,%x", fileio_err);
1753 }
1754 #endif
1755 
1756 /* Write Windows OS Thread Information Block address. */
1757 
1758 static int
1760 {
1761  win32_thread_info *th;
1762  th = thread_rec (ptid, 0);
1763  if (th == NULL)
1764  return 0;
1765  if (addr != NULL)
1766  *addr = th->thread_local_base;
1767  return 1;
1768 }
1769 
1770 /* Implementation of the target_ops method "sw_breakpoint_from_kind". */
1771 
1772 static const gdb_byte *
1773 win32_sw_breakpoint_from_kind (int kind, int *size)
1774 {
1775  *size = the_low_target.breakpoint_len;
1776  return the_low_target.breakpoint;
1777 }
1778 
1779 static struct target_ops win32_target_ops = {
1781  NULL, /* post_create_inferior */
1782  win32_attach,
1783  win32_kill,
1784  win32_detach,
1785  win32_mourn,
1786  win32_join,
1788  win32_resume,
1789  win32_wait,
1792  NULL, /* prepare_to_access_memory */
1793  NULL, /* done_accessing_memory */
1796  NULL, /* lookup_symbols */
1798  NULL, /* read_auxv */
1802  NULL, /* stopped_by_sw_breakpoint */
1803  NULL, /* supports_stopped_by_sw_breakpoint */
1804  NULL, /* stopped_by_hw_breakpoint */
1805  NULL, /* supports_stopped_by_hw_breakpoint */
1809  NULL, /* read_offsets */
1810  NULL, /* get_tls_address */
1811  NULL, /* qxfer_spu */
1812 #ifdef _WIN32_WCE
1813  wince_hostio_last_error,
1814 #else
1816 #endif
1817  NULL, /* qxfer_osdata */
1818  NULL, /* qxfer_siginfo */
1819  NULL, /* supports_non_stop */
1820  NULL, /* async */
1821  NULL, /* start_non_stop */
1822  NULL, /* supports_multi_process */
1823  NULL, /* supports_fork_events */
1824  NULL, /* supports_vfork_events */
1825  NULL, /* supports_exec_events */
1826  NULL, /* handle_new_gdb_connection */
1827  NULL, /* handle_monitor_command */
1828  NULL, /* core_of_thread */
1829  NULL, /* read_loadmap */
1830  NULL, /* process_qsupported */
1831  NULL, /* supports_tracepoints */
1832  NULL, /* read_pc */
1833  NULL, /* write_pc */
1834  NULL, /* thread_stopped */
1836  NULL, /* pause_all */
1837  NULL, /* unpause_all */
1838  NULL, /* stabilize_threads */
1839  NULL, /* install_fast_tracepoint_jump_pad */
1840  NULL, /* emit_ops */
1841  NULL, /* supports_disable_randomization */
1842  NULL, /* get_min_fast_tracepoint_insn_len */
1843  NULL, /* qxfer_libraries_svr4 */
1844  NULL, /* support_agent */
1845  NULL, /* support_btrace */
1846  NULL, /* enable_btrace */
1847  NULL, /* disable_btrace */
1848  NULL, /* read_btrace */
1849  NULL, /* read_btrace_conf */
1850  NULL, /* supports_range_stepping */
1851  NULL, /* pid_to_exec_file */
1852  NULL, /* multifs_open */
1853  NULL, /* multifs_unlink */
1854  NULL, /* multifs_readlink */
1855  NULL, /* breakpoint_kind_from_pc */
1857 };
1858 
1859 /* Initialize the Win32 backend. */
1860 void
1862 {
1865 }
const char * string
Definition: signals.c:50
static winapi_GetModuleInformation win32_GetModuleInformation
Definition: win32-low.c:1096
static int win32_detach(int pid)
Definition: win32-low.c:831
struct thread_info * current_thread
Definition: inferiors.c:28
int target_can_do_hardware_single_step(void)
Definition: target.c:340
#define OUTMSG2(X)
Definition: win32-low.c:44
static DEBUG_EVENT current_event
Definition: win32-low.c:80
void monitor_output(const char *msg)
struct process_info * add_process(int pid, int attached)
Definition: inferiors.c:140
struct thread_info * find_thread_ptid(ptid_t ptid)
Definition: inferiors.c:64
static void win32_add_all_dlls(void)
Definition: win32-low.c:1130
CORE_ADDR thread_local_base
Definition: win32-low.h:38
static ptid_t debug_event_ptid(DEBUG_EVENT *event)
Definition: win32-low.c:121
static int attaching
Definition: win32-low.c:73
bfd_vma CORE_ADDR
Definition: common-types.h:41
std::string stringify_argv(const std::vector< char *> &args)
Definition: common-utils.c:392
int(* supports_z_point_type)(char z_type)
Definition: linux-low.h:165
static void child_delete_thread(DWORD pid, DWORD tid)
Definition: win32-low.c:242
static void win32_request_interrupt(void)
Definition: win32-low.c:1665
static void win32_store_inferior_registers(struct regcache *regcache, int regno)
Definition: win32-low.c:1638
int server_waiting
Definition: server.c:80
void * memset(T *s, int c, size_t n)=delete
static void suspend_one_thread(thread_info *thread)
Definition: win32-low.c:1335
char * strwinerror(DWORD error)
Definition: win32-low.c:510
static BOOL load_psapi(void)
Definition: win32-low.c:1100
static void handle_exception(struct target_waitstatus *ourstatus)
Definition: win32-low.c:1227
static char * get_image_name(HANDLE h, void *address, int unicode)
Definition: win32-low.c:1040
static DWORD current_process_id
Definition: win32-low.c:75
static int win32_write_inferior_memory(CORE_ADDR memaddr, const unsigned char *myaddr, int len)
Definition: win32-low.c:1657
BOOL(WINAPI * winapi_Module32Next)(HANDLE, LPMODULEENTRY32)
Definition: win32-low.c:1183
HANDLE(WINAPI * winapi_CreateToolhelp32Snapshot)(DWORD, DWORD)
Definition: win32-low.c:1181
const char * name
Definition: tracepoint.c:180
static void win32_clear_inferiors(void)
Definition: win32-low.c:791
int(* stopped_by_watchpoint)(void)
Definition: linux-low.h:171
struct linux_target_ops the_low_target
#define _(String)
Definition: gdb_locale.h:35
static int soft_interrupt_requested
Definition: win32-low.c:89
static void for_each_thread(Func func)
Definition: gdbthread.h:142
static int child_initialization_done
Definition: win32-low.c:347
int attached
Definition: inferiors.h:45
static void win32_fetch_inferior_registers(struct regcache *regcache, int regno)
Definition: win32-low.c:1630
static void win32_prepare_to_resume(win32_thread_info *th)
Definition: win32-low.c:162
const struct target_desc * tdesc
Definition: inferiors.h:67
void win32_require_context(win32_thread_info *th)
Definition: win32-low.c:171
int using_threads
Definition: win32-low.c:70
static void fake_breakpoint_event(void)
Definition: win32-low.c:1353
ptid_t ptid_build(int pid, long lwp, long tid)
Definition: ptid.c:31
static void handle_load_dll(void)
Definition: win32-low.c:1193
static void child_fetch_inferior_registers(struct regcache *regcache, int r)
Definition: win32-low.c:474
static int faked_breakpoint
Definition: win32-low.c:93
#define _T(x)
Definition: win32-low.c:55
BOOL(WINAPI * winapi_Module32First)(HANDLE, LPMODULEENTRY32)
Definition: win32-low.c:1182
static int win32_attach(unsigned long pid)
Definition: win32-low.c:711
BOOL(WINAPI * winapi_GenerateConsoleCtrlEvent)(DWORD, DWORD)
Definition: win32-low.c:102
static void handle_unload_dll(void)
Definition: win32-low.c:1214
static void delete_thread_info(thread_info *thread)
Definition: win32-low.c:231
raw_bkpt_type
Definition: mem-break.h:41
void * thread_target_data(struct thread_info *thread)
Definition: inferiors.c:111
BOOL(WINAPI * winapi_DebugSetProcessKillOnExit)(BOOL KillOnExit)
Definition: win32-low.c:100
void regcache_invalidate(void)
Definition: regcache.c:108
#define NUM_REGS
Definition: win32-low.c:97
void initialize_low(void)
Definition: win32-low.c:1861
process_info * find_process_pid(int pid)
Definition: inferiors.c:164
enum resume_kind kind
Definition: target.h:47
static winapi_EnumProcessModules win32_EnumProcessModules
Definition: win32-low.c:1095
Definition: ptid.h:35
static void win32_get_thread_context(win32_thread_info *th)
Definition: win32-low.c:129
int read_inferior_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
Definition: target.c:120
static void handle_output_debug_string(void)
Definition: win32-low.c:747
ptid_t pid_to_ptid(int pid)
Definition: ptid.c:39
#define current_ptid
Definition: gdbthread.h:201
static void win32_set_thread_context(win32_thread_info *th)
Definition: win32-low.c:141
static int win32_remove_point(enum raw_bkpt_type type, CORE_ADDR addr, int size, struct raw_breakpoint *bp)
Definition: win32-low.c:277
void free(T *ptr)=delete
enum gdb_signal gdb_signal_from_host(int)
Definition: signals.c:116
void unloaded_dll(const char *name, CORE_ADDR base_addr)
Definition: dll.c:41
static int child_xfer_memory(CORE_ADDR memaddr, char *our, int len, int write, struct target_ops *target)
Definition: win32-low.c:308
static int win32_supports_z_point_type(char z_type)
Definition: win32-low.c:259
static int win32_read_inferior_memory(CORE_ADDR memaddr, unsigned char *myaddr, int len)
Definition: win32-low.c:1647
static int startswith(const char *string, const char *pattern)
Definition: common-utils.h:107
CORE_ADDR(* stopped_data_address)(void)
Definition: linux-low.h:172
void check_breakpoints(CORE_ADDR stop_pc)
Definition: mem-break.c:1728
void remove_process(struct process_info *process)
Definition: inferiors.c:154
void set_target_ops(struct target_ops *target)
Definition: target.c:299
static win32_thread_info * thread_rec(ptid_t ptid, int get_context)
Definition: win32-low.c:194
static ptid_t win32_wait(ptid_t ptid, struct target_waitstatus *ourstatus, int options)
Definition: win32-low.c:1581
BOOL(WINAPI * winapi_GetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD)
Definition: win32-low.c:1090
static ptid_t current_thread_ptid(void)
Definition: win32-low.c:114
DWORD(WINAPI * winapi_GetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD)
Definition: win32-low.c:1092
static void child_init_thread_list(void)
Definition: win32-low.c:340
static struct target_waitstatus cached_status
Definition: win32-low.c:85
static BOOL create_process(const char *program, char *args, DWORD flags, PROCESS_INFORMATION *pi)
Definition: win32-low.c:555
static int win32_insert_point(enum raw_bkpt_type type, CORE_ADDR addr, int size, struct raw_breakpoint *bp)
Definition: win32-low.c:266
int(* insert_point)(enum raw_bkpt_type type, CORE_ADDR addr, int size, struct raw_breakpoint *bp)
Definition: linux-low.h:166
static int win32_kill(int pid)
Definition: win32-low.c:802
struct thread_info * get_first_thread(void)
Definition: inferiors.c:55
int(* remove_point)(enum raw_bkpt_type type, CORE_ADDR addr, int size, struct raw_breakpoint *bp)
Definition: linux-low.h:168
#define GETPROCADDRESS(DLL, PROC)
Definition: win32-low.c:66
static int win32_create_inferior(const char *program, const std::vector< char *> &program_args)
Definition: win32-low.c:624
static int win32_thread_alive(ptid_t ptid)
Definition: win32-low.c:887
void(* prepare_to_resume)(struct lwp_info *)
Definition: linux-low.h:209
bfd_byte gdb_byte
Definition: common-types.h:38
#define READ_BUFFER_LEN
static enum gdb_signal last_sig
Definition: win32-low.c:77
static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA
Definition: win32-low.c:1097
static int win32_stopped_by_watchpoint(void)
Definition: win32-low.c:288
static void do_initial_child_stuff(HANDLE proch, DWORD pid, int attached)
Definition: win32-low.c:350
static CORE_ADDR win32_stopped_data_address(void)
Definition: win32-low.c:297
ptid_t thread
Definition: target.h:44
std::list< thread_info * > all_threads
Definition: inferiors.c:26
static void win32_mourn(struct process_info *process)
Definition: win32-low.c:868
#define XCNEW(T)
Definition: poison.h:121
void * alloca(size_t)
static void resume(struct thread_resume *actions, size_t n)
Definition: server.c:2841
static int get_child_debug_event(struct target_waitstatus *ourstatus)
Definition: win32-low.c:1379
static win32_thread_info * child_add_thread(DWORD pid, DWORD tid, HANDLE h, void *tlb)
Definition: win32-low.c:208
static DWORD main_thread_id
Definition: win32-low.c:76
BOOL(WINAPI * winapi_EnumProcessModules)(HANDLE, HMODULE *, DWORD, LPDWORD)
Definition: win32-low.c:1088
std::string gdb_tilde_expand(const char *dir)
Definition: buffer.h:23
void hostio_last_error_from_errno(char *buf)
Definition: hostio-errno.c:28
const struct target_desc * win32_tdesc
Definition: win32-low.c:95
struct regcache * get_thread_regcache(struct thread_info *thread, int fetch)
Definition: regcache.c:27
#define COUNTOF(STR)
Definition: win32-low.c:59
CONTEXT context
Definition: win32-low.h:49
void remove_thread(struct thread_info *thread)
Definition: inferiors.c:98
static void win32_add_one_solib(const char *name, CORE_ADDR load_addr)
Definition: win32-low.c:979
int ptid_equal(const ptid_t &ptid1, const ptid_t &ptid2)
Definition: ptid.c:71
const char * get_inferior_cwd()
Definition: inferiors.c:240
struct breakpoint * set_breakpoint_at(CORE_ADDR where, int(*handler)(CORE_ADDR))
Definition: mem-break.c:868
const char * gdb_signal_to_string(enum gdb_signal)
Definition: signals.c:68
#define OUTMSG(X)
Definition: win32-low.c:42
static void win32_resume(struct thread_resume *resume_info, size_t n)
Definition: win32-low.c:897
void loaded_dll(const char *name, CORE_ADDR base_addr)
Definition: dll.c:32
void(* arch_setup)(void)
Definition: linux-low.h:131
static const gdb_byte * win32_sw_breakpoint_from_kind(int kind, int *size)
Definition: win32-low.c:1773
static std::vector< char * > program_args
Definition: server.c:112
void check_remote_input_interrupt_request(void)
Definition: remote-utils.c:745
struct thread_info * add_thread(ptid_t ptid, void *target_data)
Definition: inferiors.c:34
BOOL(WINAPI * winapi_DebugActiveProcessStop)(DWORD dwProcessId)
Definition: win32-low.c:99
void clear_inferiors(void)
Definition: inferiors.c:129
static void win32_join(int pid)
Definition: win32-low.c:875
void error(const char *fmt,...)
Definition: errors.c:38
static HANDLE current_process_handle
Definition: win32-low.c:74
ptid_t minus_one_ptid
Definition: ptid.c:26
static void child_store_inferior_registers(struct regcache *regcache, int r)
Definition: win32-low.c:488
BOOL(WINAPI * winapi_DebugBreakProcess)(HANDLE)
Definition: win32-low.c:101
static void continue_one_thread(thread_info *thread, int thread_id)
Definition: win32-low.c:426
static BOOL child_continue(DWORD continue_status, int thread_id)
Definition: win32-low.c:454
static int win32_get_tib_address(ptid_t ptid, CORE_ADDR *addr)
Definition: win32-low.c:1759