1130803Smarcel/* Target-vector operations for controlling win32 child processes, for GDB.
2130803Smarcel
3130803Smarcel   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free
4130803Smarcel   Software Foundation, Inc.
5130803Smarcel
6130803Smarcel   Contributed by Cygnus Solutions, A Red Hat Company.
7130803Smarcel
8130803Smarcel   This file is part of GDB.
9130803Smarcel
10130803Smarcel   This program is free software; you can redistribute it and/or modify
11130803Smarcel   it under the terms of the GNU General Public License as published by
12130803Smarcel   the Free Software Foundation; either version 2 of the License, or
13130803Smarcel   (at your option) any later version.
14130803Smarcel
15130803Smarcel   This program is distributed in the hope that it will be useful,
16130803Smarcel   but WITHOUT ANY WARRANTY; without eve nthe implied warranty of
17130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18130803Smarcel   GNU General Public License for more details.
19130803Smarcel
20130803Smarcel   You should have received a copy of the GNU General Public License
21130803Smarcel   along with this program; if not, write to the Free Software
22130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
23130803Smarcel   Boston, MA 02111-1307, USA.  */
24130803Smarcel
25130803Smarcel/* Originally by Steve Chamberlain, sac@cygnus.com */
26130803Smarcel
27130803Smarcel/* We assume we're being built with and will be used for cygwin.  */
28130803Smarcel
29130803Smarcel#include "defs.h"
30130803Smarcel#include "frame.h"		/* required by inferior.h */
31130803Smarcel#include "inferior.h"
32130803Smarcel#include "target.h"
33130803Smarcel#include "gdbcore.h"
34130803Smarcel#include "command.h"
35130803Smarcel#include "completer.h"
36130803Smarcel#include "regcache.h"
37130803Smarcel#include "top.h"
38130803Smarcel#include <signal.h>
39130803Smarcel#include <sys/types.h>
40130803Smarcel#include <fcntl.h>
41130803Smarcel#include <stdlib.h>
42130803Smarcel#include <windows.h>
43130803Smarcel#include <imagehlp.h>
44130803Smarcel#include <sys/cygwin.h>
45130803Smarcel
46130803Smarcel#include "buildsym.h"
47130803Smarcel#include "symfile.h"
48130803Smarcel#include "objfiles.h"
49130803Smarcel#include "gdb_string.h"
50130803Smarcel#include "gdbthread.h"
51130803Smarcel#include "gdbcmd.h"
52130803Smarcel#include <sys/param.h>
53130803Smarcel#include <unistd.h>
54130803Smarcel#include "exec.h"
55130803Smarcel
56130803Smarcel#include "i386-tdep.h"
57130803Smarcel#include "i387-tdep.h"
58130803Smarcel
59130803Smarcel/* The ui's event loop. */
60130803Smarcelextern int (*ui_loop_hook) (int signo);
61130803Smarcel
62130803Smarcel/* If we're not using the old Cygwin header file set, define the
63130803Smarcel   following which never should have been in the generic Win32 API
64130803Smarcel   headers in the first place since they were our own invention... */
65130803Smarcel#ifndef _GNU_H_WINDOWS_H
66130803Smarcelenum
67130803Smarcel  {
68130803Smarcel    FLAG_TRACE_BIT = 0x100,
69130803Smarcel    CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
70130803Smarcel  };
71130803Smarcel#endif
72130803Smarcel#include <sys/procfs.h>
73130803Smarcel#include <psapi.h>
74130803Smarcel
75130803Smarcel#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
76130803Smarcel	| CONTEXT_EXTENDED_REGISTERS
77130803Smarcel
78130803Smarcelstatic unsigned dr[8];
79130803Smarcelstatic int debug_registers_changed;
80130803Smarcelstatic int debug_registers_used;
81130803Smarcel
82130803Smarcel/* The string sent by cygwin when it processes a signal.
83130803Smarcel   FIXME: This should be in a cygwin include file. */
84130803Smarcel#define CYGWIN_SIGNAL_STRING "cygwin: signal"
85130803Smarcel
86130803Smarcel#define CHECK(x)	check (x, __FILE__,__LINE__)
87130803Smarcel#define DEBUG_EXEC(x)	if (debug_exec)		printf_unfiltered x
88130803Smarcel#define DEBUG_EVENTS(x)	if (debug_events)	printf_unfiltered x
89130803Smarcel#define DEBUG_MEM(x)	if (debug_memory)	printf_unfiltered x
90130803Smarcel#define DEBUG_EXCEPT(x)	if (debug_exceptions)	printf_unfiltered x
91130803Smarcel
92130803Smarcel/* Forward declaration */
93130803Smarcelextern struct target_ops child_ops;
94130803Smarcel
95130803Smarcelstatic void child_stop (void);
96130803Smarcelstatic int win32_child_thread_alive (ptid_t);
97130803Smarcelvoid child_kill_inferior (void);
98130803Smarcel
99130803Smarcelstatic enum target_signal last_sig = TARGET_SIGNAL_0;
100130803Smarcel/* Set if a signal was received from the debugged process */
101130803Smarcel
102130803Smarcel/* Thread information structure used to track information that is
103130803Smarcel   not available in gdb's thread structure. */
104130803Smarceltypedef struct thread_info_struct
105130803Smarcel  {
106130803Smarcel    struct thread_info_struct *next;
107130803Smarcel    DWORD id;
108130803Smarcel    HANDLE h;
109130803Smarcel    char *name;
110130803Smarcel    int suspend_count;
111130803Smarcel    int reload_context;
112130803Smarcel    CONTEXT context;
113130803Smarcel    STACKFRAME sf;
114130803Smarcel  }
115130803Smarcelthread_info;
116130803Smarcel
117130803Smarcelstatic thread_info thread_head;
118130803Smarcel
119130803Smarcel/* The process and thread handles for the above context. */
120130803Smarcel
121130803Smarcelstatic DEBUG_EVENT current_event;	/* The current debug event from
122130803Smarcel					   WaitForDebugEvent */
123130803Smarcelstatic HANDLE current_process_handle;	/* Currently executing process */
124130803Smarcelstatic thread_info *current_thread;	/* Info on currently selected thread */
125130803Smarcelstatic DWORD main_thread_id;		/* Thread ID of the main thread */
126130803Smarcel
127130803Smarcel/* Counts of things. */
128130803Smarcelstatic int exception_count = 0;
129130803Smarcelstatic int event_count = 0;
130130803Smarcelstatic int saw_create;
131130803Smarcel
132130803Smarcel/* User options. */
133130803Smarcelstatic int new_console = 0;
134130803Smarcelstatic int new_group = 1;
135130803Smarcelstatic int debug_exec = 0;		/* show execution */
136130803Smarcelstatic int debug_events = 0;		/* show events from kernel */
137130803Smarcelstatic int debug_memory = 0;		/* show target memory accesses */
138130803Smarcelstatic int debug_exceptions = 0;	/* show target exceptions */
139130803Smarcelstatic int useshell = 0;		/* use shell for subprocesses */
140130803Smarcel
141130803Smarcel/* This vector maps GDB's idea of a register's number into an address
142130803Smarcel   in the win32 exception context vector.
143130803Smarcel
144130803Smarcel   It also contains the bit mask needed to load the register in question.
145130803Smarcel
146130803Smarcel   One day we could read a reg, we could inspect the context we
147130803Smarcel   already have loaded, if it doesn't have the bit set that we need,
148130803Smarcel   we read that set of registers in using GetThreadContext.  If the
149130803Smarcel   context already contains what we need, we just unpack it. Then to
150130803Smarcel   write a register, first we have to ensure that the context contains
151130803Smarcel   the other regs of the group, and then we copy the info in and set
152130803Smarcel   out bit. */
153130803Smarcel
154130803Smarcel#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
155130803Smarcelstatic const int mappings[] =
156130803Smarcel{
157130803Smarcel  context_offset (Eax),
158130803Smarcel  context_offset (Ecx),
159130803Smarcel  context_offset (Edx),
160130803Smarcel  context_offset (Ebx),
161130803Smarcel  context_offset (Esp),
162130803Smarcel  context_offset (Ebp),
163130803Smarcel  context_offset (Esi),
164130803Smarcel  context_offset (Edi),
165130803Smarcel  context_offset (Eip),
166130803Smarcel  context_offset (EFlags),
167130803Smarcel  context_offset (SegCs),
168130803Smarcel  context_offset (SegSs),
169130803Smarcel  context_offset (SegDs),
170130803Smarcel  context_offset (SegEs),
171130803Smarcel  context_offset (SegFs),
172130803Smarcel  context_offset (SegGs),
173130803Smarcel  context_offset (FloatSave.RegisterArea[0 * 10]),
174130803Smarcel  context_offset (FloatSave.RegisterArea[1 * 10]),
175130803Smarcel  context_offset (FloatSave.RegisterArea[2 * 10]),
176130803Smarcel  context_offset (FloatSave.RegisterArea[3 * 10]),
177130803Smarcel  context_offset (FloatSave.RegisterArea[4 * 10]),
178130803Smarcel  context_offset (FloatSave.RegisterArea[5 * 10]),
179130803Smarcel  context_offset (FloatSave.RegisterArea[6 * 10]),
180130803Smarcel  context_offset (FloatSave.RegisterArea[7 * 10]),
181130803Smarcel  context_offset (FloatSave.ControlWord),
182130803Smarcel  context_offset (FloatSave.StatusWord),
183130803Smarcel  context_offset (FloatSave.TagWord),
184130803Smarcel  context_offset (FloatSave.ErrorSelector),
185130803Smarcel  context_offset (FloatSave.ErrorOffset),
186130803Smarcel  context_offset (FloatSave.DataSelector),
187130803Smarcel  context_offset (FloatSave.DataOffset),
188130803Smarcel  context_offset (FloatSave.ErrorSelector)
189130803Smarcel  /* XMM0-7 */ ,
190130803Smarcel  context_offset (ExtendedRegisters[10*16]),
191130803Smarcel  context_offset (ExtendedRegisters[11*16]),
192130803Smarcel  context_offset (ExtendedRegisters[12*16]),
193130803Smarcel  context_offset (ExtendedRegisters[13*16]),
194130803Smarcel  context_offset (ExtendedRegisters[14*16]),
195130803Smarcel  context_offset (ExtendedRegisters[15*16]),
196130803Smarcel  context_offset (ExtendedRegisters[16*16]),
197130803Smarcel  context_offset (ExtendedRegisters[17*16]),
198130803Smarcel  /* MXCSR */
199130803Smarcel  context_offset (ExtendedRegisters[24])
200130803Smarcel};
201130803Smarcel
202130803Smarcel#undef context_offset
203130803Smarcel
204130803Smarcel/* This vector maps the target's idea of an exception (extracted
205130803Smarcel   from the DEBUG_EVENT structure) to GDB's idea. */
206130803Smarcel
207130803Smarcelstruct xlate_exception
208130803Smarcel  {
209130803Smarcel    int them;
210130803Smarcel    enum target_signal us;
211130803Smarcel  };
212130803Smarcel
213130803Smarcelstatic const struct xlate_exception
214130803Smarcel  xlate[] =
215130803Smarcel{
216130803Smarcel  {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
217130803Smarcel  {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
218130803Smarcel  {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
219130803Smarcel  {DBG_CONTROL_C, TARGET_SIGNAL_INT},
220130803Smarcel  {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
221130803Smarcel  {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE},
222130803Smarcel  {-1, -1}};
223130803Smarcel
224130803Smarcelstatic void
225130803Smarcelcheck (BOOL ok, const char *file, int line)
226130803Smarcel{
227130803Smarcel  if (!ok)
228130803Smarcel    printf_filtered ("error return %s:%d was %lu\n", file, line,
229130803Smarcel		     GetLastError ());
230130803Smarcel}
231130803Smarcel
232130803Smarcel/* Find a thread record given a thread id.
233130803Smarcel   If get_context then also retrieve the context for this
234130803Smarcel   thread. */
235130803Smarcelstatic thread_info *
236130803Smarcelthread_rec (DWORD id, int get_context)
237130803Smarcel{
238130803Smarcel  thread_info *th;
239130803Smarcel
240130803Smarcel  for (th = &thread_head; (th = th->next) != NULL;)
241130803Smarcel    if (th->id == id)
242130803Smarcel      {
243130803Smarcel	if (!th->suspend_count && get_context)
244130803Smarcel	  {
245130803Smarcel	    if (get_context > 0 && id != current_event.dwThreadId)
246130803Smarcel	      th->suspend_count = SuspendThread (th->h) + 1;
247130803Smarcel	    else if (get_context < 0)
248130803Smarcel	      th->suspend_count = -1;
249130803Smarcel	    th->reload_context = 1;
250130803Smarcel	  }
251130803Smarcel	return th;
252130803Smarcel      }
253130803Smarcel
254130803Smarcel  return NULL;
255130803Smarcel}
256130803Smarcel
257130803Smarcel/* Add a thread to the thread list */
258130803Smarcelstatic thread_info *
259130803Smarcelchild_add_thread (DWORD id, HANDLE h)
260130803Smarcel{
261130803Smarcel  thread_info *th;
262130803Smarcel
263130803Smarcel  if ((th = thread_rec (id, FALSE)))
264130803Smarcel    return th;
265130803Smarcel
266130803Smarcel  th = (thread_info *) xmalloc (sizeof (*th));
267130803Smarcel  memset (th, 0, sizeof (*th));
268130803Smarcel  th->id = id;
269130803Smarcel  th->h = h;
270130803Smarcel  th->next = thread_head.next;
271130803Smarcel  thread_head.next = th;
272130803Smarcel  add_thread (pid_to_ptid (id));
273130803Smarcel  /* Set the debug registers for the new thread in they are used.  */
274130803Smarcel  if (debug_registers_used)
275130803Smarcel    {
276130803Smarcel      /* Only change the value of the debug registers.  */
277130803Smarcel      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
278130803Smarcel      CHECK (GetThreadContext (th->h, &th->context));
279130803Smarcel      th->context.Dr0 = dr[0];
280130803Smarcel      th->context.Dr1 = dr[1];
281130803Smarcel      th->context.Dr2 = dr[2];
282130803Smarcel      th->context.Dr3 = dr[3];
283130803Smarcel      /* th->context.Dr6 = dr[6];
284130803Smarcel      FIXME: should we set dr6 also ?? */
285130803Smarcel      th->context.Dr7 = dr[7];
286130803Smarcel      CHECK (SetThreadContext (th->h, &th->context));
287130803Smarcel      th->context.ContextFlags = 0;
288130803Smarcel    }
289130803Smarcel  return th;
290130803Smarcel}
291130803Smarcel
292130803Smarcel/* Clear out any old thread list and reintialize it to a
293130803Smarcel   pristine state. */
294130803Smarcelstatic void
295130803Smarcelchild_init_thread_list (void)
296130803Smarcel{
297130803Smarcel  thread_info *th = &thread_head;
298130803Smarcel
299130803Smarcel  DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
300130803Smarcel  init_thread_list ();
301130803Smarcel  while (th->next != NULL)
302130803Smarcel    {
303130803Smarcel      thread_info *here = th->next;
304130803Smarcel      th->next = here->next;
305130803Smarcel      (void) CloseHandle (here->h);
306130803Smarcel      xfree (here);
307130803Smarcel    }
308130803Smarcel}
309130803Smarcel
310130803Smarcel/* Delete a thread from the list of threads */
311130803Smarcelstatic void
312130803Smarcelchild_delete_thread (DWORD id)
313130803Smarcel{
314130803Smarcel  thread_info *th;
315130803Smarcel
316130803Smarcel  if (info_verbose)
317130803Smarcel    printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
318130803Smarcel  delete_thread (pid_to_ptid (id));
319130803Smarcel
320130803Smarcel  for (th = &thread_head;
321130803Smarcel       th->next != NULL && th->next->id != id;
322130803Smarcel       th = th->next)
323130803Smarcel    continue;
324130803Smarcel
325130803Smarcel  if (th->next != NULL)
326130803Smarcel    {
327130803Smarcel      thread_info *here = th->next;
328130803Smarcel      th->next = here->next;
329130803Smarcel      CloseHandle (here->h);
330130803Smarcel      xfree (here);
331130803Smarcel    }
332130803Smarcel}
333130803Smarcel
334130803Smarcelstatic void
335130803Smarceldo_child_fetch_inferior_registers (int r)
336130803Smarcel{
337130803Smarcel  char *context_offset = ((char *) &current_thread->context) + mappings[r];
338130803Smarcel  long l;
339130803Smarcel
340130803Smarcel  if (!current_thread)
341130803Smarcel    return;	/* Windows sometimes uses a non-existent thread id in its
342130803Smarcel		   events */
343130803Smarcel
344130803Smarcel  if (current_thread->reload_context)
345130803Smarcel    {
346130803Smarcel      thread_info *th = current_thread;
347130803Smarcel      th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
348130803Smarcel      GetThreadContext (th->h, &th->context);
349130803Smarcel      /* Copy dr values from that thread.  */
350130803Smarcel      dr[0] = th->context.Dr0;
351130803Smarcel      dr[1] = th->context.Dr1;
352130803Smarcel      dr[2] = th->context.Dr2;
353130803Smarcel      dr[3] = th->context.Dr3;
354130803Smarcel      dr[6] = th->context.Dr6;
355130803Smarcel      dr[7] = th->context.Dr7;
356130803Smarcel      current_thread->reload_context = 0;
357130803Smarcel    }
358130803Smarcel
359130803Smarcel#define I387_ST0_REGNUM I386_ST0_REGNUM
360130803Smarcel
361130803Smarcel  if (r == I387_FISEG_REGNUM)
362130803Smarcel    {
363130803Smarcel      l = *((long *) context_offset) & 0xffff;
364130803Smarcel      supply_register (r, (char *) &l);
365130803Smarcel    }
366130803Smarcel  else if (r == I387_FOP_REGNUM)
367130803Smarcel    {
368130803Smarcel      l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
369130803Smarcel      supply_register (r, (char *) &l);
370130803Smarcel    }
371130803Smarcel  else if (r >= 0)
372130803Smarcel    supply_register (r, context_offset);
373130803Smarcel  else
374130803Smarcel    {
375130803Smarcel      for (r = 0; r < NUM_REGS; r++)
376130803Smarcel	do_child_fetch_inferior_registers (r);
377130803Smarcel    }
378130803Smarcel
379130803Smarcel#undef I387_ST0_REGNUM
380130803Smarcel}
381130803Smarcel
382130803Smarcelstatic void
383130803Smarcelchild_fetch_inferior_registers (int r)
384130803Smarcel{
385130803Smarcel  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
386130803Smarcel  /* Check if current_thread exists.  Windows sometimes uses a non-existent
387130803Smarcel     thread id in its events */
388130803Smarcel  if (current_thread)
389130803Smarcel    do_child_fetch_inferior_registers (r);
390130803Smarcel}
391130803Smarcel
392130803Smarcelstatic void
393130803Smarceldo_child_store_inferior_registers (int r)
394130803Smarcel{
395130803Smarcel  if (!current_thread)
396130803Smarcel    /* Windows sometimes uses a non-existent thread id in its events */;
397130803Smarcel  else if (r >= 0)
398130803Smarcel    regcache_collect (r, ((char *) &current_thread->context) + mappings[r]);
399130803Smarcel  else
400130803Smarcel    {
401130803Smarcel      for (r = 0; r < NUM_REGS; r++)
402130803Smarcel	do_child_store_inferior_registers (r);
403130803Smarcel    }
404130803Smarcel}
405130803Smarcel
406130803Smarcel/* Store a new register value into the current thread context */
407130803Smarcelstatic void
408130803Smarcelchild_store_inferior_registers (int r)
409130803Smarcel{
410130803Smarcel  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
411130803Smarcel  /* Check if current_thread exists.  Windows sometimes uses a non-existent
412130803Smarcel     thread id in its events */
413130803Smarcel  if (current_thread)
414130803Smarcel    do_child_store_inferior_registers (r);
415130803Smarcel}
416130803Smarcel
417130803Smarcelstatic int psapi_loaded = 0;
418130803Smarcelstatic HMODULE psapi_module_handle = NULL;
419130803Smarcelstatic BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
420130803Smarcelstatic BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
421130803Smarcelstatic DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
422130803Smarcel
423130803Smarcelint
424130803Smarcelpsapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
425130803Smarcel{
426130803Smarcel  DWORD len;
427130803Smarcel  MODULEINFO mi;
428130803Smarcel  int i;
429130803Smarcel  HMODULE dh_buf[1];
430130803Smarcel  HMODULE *DllHandle = dh_buf;
431130803Smarcel  DWORD cbNeeded;
432130803Smarcel  BOOL ok;
433130803Smarcel
434130803Smarcel  if (!psapi_loaded ||
435130803Smarcel      psapi_EnumProcessModules == NULL ||
436130803Smarcel      psapi_GetModuleInformation == NULL ||
437130803Smarcel      psapi_GetModuleFileNameExA == NULL)
438130803Smarcel    {
439130803Smarcel      if (psapi_loaded)
440130803Smarcel	goto failed;
441130803Smarcel      psapi_loaded = 1;
442130803Smarcel      psapi_module_handle = LoadLibrary ("psapi.dll");
443130803Smarcel      if (!psapi_module_handle)
444130803Smarcel	{
445130803Smarcel	  /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
446130803Smarcel	  goto failed;
447130803Smarcel	}
448130803Smarcel      psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
449130803Smarcel      psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
450130803Smarcel      psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
451130803Smarcel						    "GetModuleFileNameExA");
452130803Smarcel      if (psapi_EnumProcessModules == NULL ||
453130803Smarcel	  psapi_GetModuleInformation == NULL ||
454130803Smarcel	  psapi_GetModuleFileNameExA == NULL)
455130803Smarcel	goto failed;
456130803Smarcel    }
457130803Smarcel
458130803Smarcel  cbNeeded = 0;
459130803Smarcel  ok = (*psapi_EnumProcessModules) (current_process_handle,
460130803Smarcel				    DllHandle,
461130803Smarcel				    sizeof (HMODULE),
462130803Smarcel				    &cbNeeded);
463130803Smarcel
464130803Smarcel  if (!ok || !cbNeeded)
465130803Smarcel    goto failed;
466130803Smarcel
467130803Smarcel  DllHandle = (HMODULE *) alloca (cbNeeded);
468130803Smarcel  if (!DllHandle)
469130803Smarcel    goto failed;
470130803Smarcel
471130803Smarcel  ok = (*psapi_EnumProcessModules) (current_process_handle,
472130803Smarcel				    DllHandle,
473130803Smarcel				    cbNeeded,
474130803Smarcel				    &cbNeeded);
475130803Smarcel  if (!ok)
476130803Smarcel    goto failed;
477130803Smarcel
478130803Smarcel  for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
479130803Smarcel    {
480130803Smarcel      if (!(*psapi_GetModuleInformation) (current_process_handle,
481130803Smarcel					  DllHandle[i],
482130803Smarcel					  &mi,
483130803Smarcel					  sizeof (mi)))
484130803Smarcel	error ("Can't get module info");
485130803Smarcel
486130803Smarcel      len = (*psapi_GetModuleFileNameExA) (current_process_handle,
487130803Smarcel					   DllHandle[i],
488130803Smarcel					   dll_name_ret,
489130803Smarcel					   MAX_PATH);
490130803Smarcel      if (len == 0)
491130803Smarcel	error ("Error getting dll name: %u\n", (unsigned) GetLastError ());
492130803Smarcel
493130803Smarcel      if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
494130803Smarcel	return 1;
495130803Smarcel    }
496130803Smarcel
497130803Smarcelfailed:
498130803Smarcel  dll_name_ret[0] = '\0';
499130803Smarcel  return 0;
500130803Smarcel}
501130803Smarcel
502130803Smarcel/* Encapsulate the information required in a call to
503130803Smarcel   symbol_file_add_args */
504130803Smarcelstruct safe_symbol_file_add_args
505130803Smarcel{
506130803Smarcel  char *name;
507130803Smarcel  int from_tty;
508130803Smarcel  struct section_addr_info *addrs;
509130803Smarcel  int mainline;
510130803Smarcel  int flags;
511130803Smarcel  struct ui_file *err, *out;
512130803Smarcel  struct objfile *ret;
513130803Smarcel};
514130803Smarcel
515130803Smarcel/* Maintain a linked list of "so" information. */
516130803Smarcelstruct so_stuff
517130803Smarcel{
518130803Smarcel  struct so_stuff *next;
519130803Smarcel  DWORD load_addr;
520130803Smarcel  DWORD end_addr;
521130803Smarcel  int loaded;
522130803Smarcel  struct objfile *objfile;
523130803Smarcel  char name[1];
524130803Smarcel} solib_start, *solib_end;
525130803Smarcel
526130803Smarcel/* Call symbol_file_add with stderr redirected.  We don't care if there
527130803Smarcel   are errors. */
528130803Smarcelstatic int
529130803Smarcelsafe_symbol_file_add_stub (void *argv)
530130803Smarcel{
531130803Smarcel#define p ((struct safe_symbol_file_add_args *)argv)
532130803Smarcel  struct so_stuff *so = &solib_start;
533130803Smarcel
534130803Smarcel  while ((so = so->next))
535130803Smarcel    if (so->loaded && strcasecmp (so->name, p->name) == 0)
536130803Smarcel      return 0;
537130803Smarcel  p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
538130803Smarcel  return !!p->ret;
539130803Smarcel#undef p
540130803Smarcel}
541130803Smarcel
542130803Smarcel/* Restore gdb's stderr after calling symbol_file_add */
543130803Smarcelstatic void
544130803Smarcelsafe_symbol_file_add_cleanup (void *p)
545130803Smarcel{
546130803Smarcel#define sp ((struct safe_symbol_file_add_args *)p)
547130803Smarcel  gdb_flush (gdb_stderr);
548130803Smarcel  gdb_flush (gdb_stdout);
549130803Smarcel  ui_file_delete (gdb_stderr);
550130803Smarcel  ui_file_delete (gdb_stdout);
551130803Smarcel  gdb_stderr = sp->err;
552130803Smarcel  gdb_stdout = sp->out;
553130803Smarcel#undef sp
554130803Smarcel}
555130803Smarcel
556130803Smarcel/* symbol_file_add wrapper that prevents errors from being displayed. */
557130803Smarcelstatic struct objfile *
558130803Smarcelsafe_symbol_file_add (char *name, int from_tty,
559130803Smarcel		      struct section_addr_info *addrs,
560130803Smarcel		      int mainline, int flags)
561130803Smarcel{
562130803Smarcel  struct safe_symbol_file_add_args p;
563130803Smarcel  struct cleanup *cleanup;
564130803Smarcel
565130803Smarcel  cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
566130803Smarcel
567130803Smarcel  p.err = gdb_stderr;
568130803Smarcel  p.out = gdb_stdout;
569130803Smarcel  gdb_flush (gdb_stderr);
570130803Smarcel  gdb_flush (gdb_stdout);
571130803Smarcel  gdb_stderr = ui_file_new ();
572130803Smarcel  gdb_stdout = ui_file_new ();
573130803Smarcel  p.name = name;
574130803Smarcel  p.from_tty = from_tty;
575130803Smarcel  p.addrs = addrs;
576130803Smarcel  p.mainline = mainline;
577130803Smarcel  p.flags = flags;
578130803Smarcel  catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
579130803Smarcel
580130803Smarcel  do_cleanups (cleanup);
581130803Smarcel  return p.ret;
582130803Smarcel}
583130803Smarcel
584130803Smarcel/* Remember the maximum DLL length for printing in info dll command. */
585130803Smarcelint max_dll_name_len;
586130803Smarcel
587130803Smarcelstatic void
588130803Smarcelregister_loaded_dll (const char *name, DWORD load_addr)
589130803Smarcel{
590130803Smarcel  struct so_stuff *so;
591130803Smarcel  char ppath[MAX_PATH + 1];
592130803Smarcel  char buf[MAX_PATH + 1];
593130803Smarcel  char cwd[MAX_PATH + 1];
594130803Smarcel  char *p;
595130803Smarcel  WIN32_FIND_DATA w32_fd;
596130803Smarcel  HANDLE h = FindFirstFile(name, &w32_fd);
597130803Smarcel  MEMORY_BASIC_INFORMATION m;
598130803Smarcel  size_t len;
599130803Smarcel
600130803Smarcel  if (h == INVALID_HANDLE_VALUE)
601130803Smarcel    strcpy (buf, name);
602130803Smarcel  else
603130803Smarcel    {
604130803Smarcel      FindClose (h);
605130803Smarcel      strcpy (buf, name);
606130803Smarcel      if (GetCurrentDirectory (MAX_PATH + 1, cwd))
607130803Smarcel	{
608130803Smarcel	  p = strrchr (buf, '\\');
609130803Smarcel	  if (p)
610130803Smarcel	    p[1] = '\0';
611130803Smarcel	  SetCurrentDirectory (buf);
612130803Smarcel	  GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
613130803Smarcel	  SetCurrentDirectory (cwd);
614130803Smarcel	}
615130803Smarcel    }
616130803Smarcel
617130803Smarcel  cygwin_conv_to_posix_path (buf, ppath);
618130803Smarcel  so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
619130803Smarcel  so->loaded = 0;
620130803Smarcel  so->load_addr = load_addr;
621130803Smarcel  if (VirtualQueryEx (current_process_handle, (void *) load_addr, &m,
622130803Smarcel		      sizeof (m)))
623130803Smarcel    so->end_addr = (DWORD) m.AllocationBase + m.RegionSize;
624130803Smarcel  else
625130803Smarcel    so->end_addr = load_addr + 0x2000;	/* completely arbitrary */
626130803Smarcel
627130803Smarcel  so->next = NULL;
628130803Smarcel  so->objfile = NULL;
629130803Smarcel  strcpy (so->name, ppath);
630130803Smarcel
631130803Smarcel  solib_end->next = so;
632130803Smarcel  solib_end = so;
633130803Smarcel  len = strlen (ppath);
634130803Smarcel  if (len > max_dll_name_len)
635130803Smarcel    max_dll_name_len = len;
636130803Smarcel}
637130803Smarcel
638130803Smarcelchar *
639130803Smarcelget_image_name (HANDLE h, void *address, int unicode)
640130803Smarcel{
641130803Smarcel  static char buf[(2 * MAX_PATH) + 1];
642130803Smarcel  DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
643130803Smarcel  char *address_ptr;
644130803Smarcel  int len = 0;
645130803Smarcel  char b[2];
646130803Smarcel  DWORD done;
647130803Smarcel
648130803Smarcel  /* Attempt to read the name of the dll that was detected.
649130803Smarcel     This is documented to work only when actively debugging
650130803Smarcel     a program.  It will not work for attached processes. */
651130803Smarcel  if (address == NULL)
652130803Smarcel    return NULL;
653130803Smarcel
654130803Smarcel  /* See if we could read the address of a string, and that the
655130803Smarcel     address isn't null. */
656130803Smarcel  if (!ReadProcessMemory (h, address,  &address_ptr, sizeof (address_ptr), &done)
657130803Smarcel      || done != sizeof (address_ptr) || !address_ptr)
658130803Smarcel    return NULL;
659130803Smarcel
660130803Smarcel  /* Find the length of the string */
661130803Smarcel  while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
662130803Smarcel	 && (b[0] != 0 || b[size - 1] != 0) && done == size)
663130803Smarcel    continue;
664130803Smarcel
665130803Smarcel  if (!unicode)
666130803Smarcel    ReadProcessMemory (h, address_ptr, buf, len, &done);
667130803Smarcel  else
668130803Smarcel    {
669130803Smarcel      WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
670130803Smarcel      ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
671130803Smarcel			 &done);
672130803Smarcel
673130803Smarcel      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
674130803Smarcel    }
675130803Smarcel
676130803Smarcel  return buf;
677130803Smarcel}
678130803Smarcel
679130803Smarcel/* Wait for child to do something.  Return pid of child, or -1 in case
680130803Smarcel   of error; store status through argument pointer OURSTATUS.  */
681130803Smarcelstatic int
682130803Smarcelhandle_load_dll (void *dummy)
683130803Smarcel{
684130803Smarcel  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
685130803Smarcel  char dll_buf[MAX_PATH + 1];
686130803Smarcel  char *dll_name = NULL;
687130803Smarcel  char *p;
688130803Smarcel
689130803Smarcel  dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
690130803Smarcel
691130803Smarcel  if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
692130803Smarcel    dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
693130803Smarcel
694130803Smarcel  dll_name = dll_buf;
695130803Smarcel
696130803Smarcel  if (*dll_name == '\0')
697130803Smarcel    dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode);
698130803Smarcel  if (!dll_name)
699130803Smarcel    return 1;
700130803Smarcel
701130803Smarcel  register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000);
702130803Smarcel
703130803Smarcel  return 1;
704130803Smarcel}
705130803Smarcel
706130803Smarcelstatic int
707130803Smarcelhandle_unload_dll (void *dummy)
708130803Smarcel{
709130803Smarcel  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
710130803Smarcel  struct so_stuff *so;
711130803Smarcel
712130803Smarcel  for (so = &solib_start; so->next != NULL; so = so->next)
713130803Smarcel    if (so->next->load_addr == lpBaseOfDll)
714130803Smarcel      {
715130803Smarcel	struct so_stuff *sodel = so->next;
716130803Smarcel	so->next = sodel->next;
717130803Smarcel	if (!so->next)
718130803Smarcel	  solib_end = so;
719130803Smarcel	if (sodel->objfile)
720130803Smarcel	  free_objfile (sodel->objfile);
721130803Smarcel	xfree(sodel);
722130803Smarcel	return 1;
723130803Smarcel      }
724130803Smarcel  error ("Error: dll starting at 0x%lx not found.\n", (DWORD) lpBaseOfDll);
725130803Smarcel
726130803Smarcel  return 0;
727130803Smarcel}
728130803Smarcel
729130803Smarcelchar *
730130803Smarcelsolib_address (CORE_ADDR address)
731130803Smarcel{
732130803Smarcel  struct so_stuff *so;
733130803Smarcel  for (so = &solib_start; so->next != NULL; so = so->next)
734130803Smarcel    if (address >= so->load_addr && address <= so->end_addr)
735130803Smarcel      return so->name;
736130803Smarcel  return NULL;
737130803Smarcel}
738130803Smarcel
739130803Smarcel/* Return name of last loaded DLL. */
740130803Smarcelchar *
741130803Smarcelchild_solib_loaded_library_pathname (int pid)
742130803Smarcel{
743130803Smarcel  return !solib_end || !solib_end->name[0] ? NULL : solib_end->name;
744130803Smarcel}
745130803Smarcel
746130803Smarcel/* Clear list of loaded DLLs. */
747130803Smarcelvoid
748130803Smarcelchild_clear_solibs (void)
749130803Smarcel{
750130803Smarcel  struct so_stuff *so, *so1 = solib_start.next;
751130803Smarcel
752130803Smarcel  while ((so = so1) != NULL)
753130803Smarcel    {
754130803Smarcel      so1 = so->next;
755130803Smarcel      xfree (so);
756130803Smarcel    }
757130803Smarcel
758130803Smarcel  solib_start.next = NULL;
759130803Smarcel  solib_start.objfile = NULL;
760130803Smarcel  solib_end = &solib_start;
761130803Smarcel  max_dll_name_len = sizeof ("DLL Name") - 1;
762130803Smarcel}
763130803Smarcel
764130803Smarcel/* Get the loaded address of all sections, given that .text was loaded
765130803Smarcel   at text_load. Assumes that all sections are subject to the same
766130803Smarcel   relocation offset. Returns NULL if problems occur or if the
767130803Smarcel   sections were not relocated. */
768130803Smarcel
769130803Smarcelstatic struct section_addr_info *
770130803Smarcelget_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load)
771130803Smarcel{
772130803Smarcel  struct section_addr_info *result = NULL;
773130803Smarcel  int section_count = bfd_count_sections (abfd);
774130803Smarcel  asection *text_section = bfd_get_section_by_name (abfd, ".text");
775130803Smarcel  CORE_ADDR text_vma;
776130803Smarcel
777130803Smarcel  if (!text_section)
778130803Smarcel    {
779130803Smarcel      /* Couldn't get the .text section. Weird. */
780130803Smarcel    }
781130803Smarcel
782130803Smarcel  else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section)))
783130803Smarcel    {
784130803Smarcel      /* DLL wasn't relocated. */
785130803Smarcel    }
786130803Smarcel
787130803Smarcel  else
788130803Smarcel    {
789130803Smarcel      /* Figure out all sections' loaded addresses. The offset here is
790130803Smarcel	 such that taking a bfd_get_section_vma() result and adding
791130803Smarcel	 offset will give the real load address of the section. */
792130803Smarcel
793130803Smarcel      CORE_ADDR offset = text_load - text_vma;
794130803Smarcel
795130803Smarcel      struct section_table *table_start = NULL;
796130803Smarcel      struct section_table *table_end = NULL;
797130803Smarcel      struct section_table *iter = NULL;
798130803Smarcel
799130803Smarcel      build_section_table (abfd, &table_start, &table_end);
800130803Smarcel
801130803Smarcel      for (iter = table_start; iter < table_end; ++iter)
802130803Smarcel	{
803130803Smarcel	  /* Relocated addresses. */
804130803Smarcel	  iter->addr += offset;
805130803Smarcel	  iter->endaddr += offset;
806130803Smarcel	}
807130803Smarcel
808130803Smarcel      result = build_section_addr_info_from_section_table (table_start,
809130803Smarcel							   table_end);
810130803Smarcel
811130803Smarcel      xfree (table_start);
812130803Smarcel    }
813130803Smarcel
814130803Smarcel  return result;
815130803Smarcel}
816130803Smarcel
817130803Smarcel/* Add DLL symbol information. */
818130803Smarcelstatic struct objfile *
819130803Smarcelsolib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr)
820130803Smarcel{
821130803Smarcel  struct section_addr_info *addrs = NULL;
822130803Smarcel  static struct objfile *result = NULL;
823130803Smarcel  bfd *abfd = NULL;
824130803Smarcel
825130803Smarcel  /* The symbols in a dll are offset by 0x1000, which is the
826130803Smarcel     the offset from 0 of the first byte in an image - because
827130803Smarcel     of the file header and the section alignment. */
828130803Smarcel
829130803Smarcel  if (!name || !name[0])
830130803Smarcel    return NULL;
831130803Smarcel
832130803Smarcel  abfd = bfd_openr (name, "pei-i386");
833130803Smarcel
834130803Smarcel  if (!abfd)
835130803Smarcel    {
836130803Smarcel      /* pei failed - try pe */
837130803Smarcel      abfd = bfd_openr (name, "pe-i386");
838130803Smarcel    }
839130803Smarcel
840130803Smarcel  if (abfd)
841130803Smarcel    {
842130803Smarcel      if (bfd_check_format (abfd, bfd_object))
843130803Smarcel	{
844130803Smarcel	  addrs = get_relocated_section_addrs (abfd, load_addr);
845130803Smarcel	}
846130803Smarcel
847130803Smarcel      bfd_close (abfd);
848130803Smarcel    }
849130803Smarcel
850130803Smarcel  if (addrs)
851130803Smarcel    {
852130803Smarcel      result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED);
853130803Smarcel      free_section_addr_info (addrs);
854130803Smarcel    }
855130803Smarcel  else
856130803Smarcel    {
857130803Smarcel      /* Fallback on handling just the .text section. */
858130803Smarcel      struct cleanup *my_cleanups;
859130803Smarcel
860130803Smarcel      addrs = alloc_section_addr_info (1);
861130803Smarcel      my_cleanups = make_cleanup (xfree, addrs);
862130803Smarcel      addrs->other[0].name = ".text";
863130803Smarcel      addrs->other[0].addr = load_addr;
864130803Smarcel
865130803Smarcel      result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED);
866130803Smarcel      do_cleanups (my_cleanups);
867130803Smarcel    }
868130803Smarcel
869130803Smarcel  return result;
870130803Smarcel}
871130803Smarcel
872130803Smarcel/* Load DLL symbol info. */
873130803Smarcelvoid
874130803Smarceldll_symbol_command (char *args, int from_tty)
875130803Smarcel{
876130803Smarcel  int n;
877130803Smarcel  dont_repeat ();
878130803Smarcel
879130803Smarcel  if (args == NULL)
880130803Smarcel    error ("dll-symbols requires a file name");
881130803Smarcel
882130803Smarcel  n = strlen (args);
883130803Smarcel  if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
884130803Smarcel    {
885130803Smarcel      char *newargs = (char *) alloca (n + 4 + 1);
886130803Smarcel      strcpy (newargs, args);
887130803Smarcel      strcat (newargs, ".dll");
888130803Smarcel      args = newargs;
889130803Smarcel    }
890130803Smarcel
891130803Smarcel  safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
892130803Smarcel}
893130803Smarcel
894130803Smarcel/* List currently loaded DLLs. */
895130803Smarcelvoid
896130803Smarcelinfo_dll_command (char *ignore, int from_tty)
897130803Smarcel{
898130803Smarcel  struct so_stuff *so = &solib_start;
899130803Smarcel
900130803Smarcel  if (!so->next)
901130803Smarcel    return;
902130803Smarcel
903130803Smarcel  printf_filtered ("%*s  Load Address\n", -max_dll_name_len, "DLL Name");
904130803Smarcel  while ((so = so->next) != NULL)
905130803Smarcel    printf_filtered ("%*s  %08lx\n", -max_dll_name_len, so->name, so->load_addr);
906130803Smarcel
907130803Smarcel  return;
908130803Smarcel}
909130803Smarcel
910130803Smarcel/* Handle DEBUG_STRING output from child process.
911130803Smarcel   Cygwin prepends its messages with a "cygwin:".  Interpret this as
912130803Smarcel   a Cygwin signal.  Otherwise just print the string as a warning. */
913130803Smarcelstatic int
914130803Smarcelhandle_output_debug_string (struct target_waitstatus *ourstatus)
915130803Smarcel{
916130803Smarcel  char *s;
917130803Smarcel  int gotasig = FALSE;
918130803Smarcel
919130803Smarcel  if (!target_read_string
920130803Smarcel    ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
921130803Smarcel      || !s || !*s)
922130803Smarcel    return gotasig;
923130803Smarcel
924130803Smarcel  if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
925130803Smarcel    {
926130803Smarcel      if (strncmp (s, "cYg", 3) != 0)
927130803Smarcel	warning ("%s", s);
928130803Smarcel    }
929130803Smarcel  else
930130803Smarcel    {
931130803Smarcel      char *p;
932130803Smarcel      int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
933130803Smarcel      gotasig = target_signal_from_host (sig);
934130803Smarcel      ourstatus->value.sig = gotasig;
935130803Smarcel      if (gotasig)
936130803Smarcel	ourstatus->kind = TARGET_WAITKIND_STOPPED;
937130803Smarcel    }
938130803Smarcel
939130803Smarcel  xfree (s);
940130803Smarcel  return gotasig;
941130803Smarcel}
942130803Smarcel
943130803Smarcelstatic int
944130803Smarceldisplay_selector (HANDLE thread, DWORD sel)
945130803Smarcel{
946130803Smarcel  LDT_ENTRY info;
947130803Smarcel  if (GetThreadSelectorEntry (thread, sel, &info))
948130803Smarcel    {
949130803Smarcel      int base, limit;
950130803Smarcel      printf_filtered ("0x%03lx: ", sel);
951130803Smarcel      if (!info.HighWord.Bits.Pres)
952130803Smarcel	{
953130803Smarcel	  puts_filtered ("Segment not present\n");
954130803Smarcel	  return 0;
955130803Smarcel	}
956130803Smarcel      base = (info.HighWord.Bits.BaseHi << 24) +
957130803Smarcel	     (info.HighWord.Bits.BaseMid << 16)
958130803Smarcel	     + info.BaseLow;
959130803Smarcel      limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow;
960130803Smarcel      if (info.HighWord.Bits.Granularity)
961130803Smarcel	limit = (limit << 12) | 0xfff;
962130803Smarcel      printf_filtered ("base=0x%08x limit=0x%08x", base, limit);
963130803Smarcel      if (info.HighWord.Bits.Default_Big)
964130803Smarcel	puts_filtered(" 32-bit ");
965130803Smarcel      else
966130803Smarcel	puts_filtered(" 16-bit ");
967130803Smarcel      switch ((info.HighWord.Bits.Type & 0xf) >> 1)
968130803Smarcel	{
969130803Smarcel	case 0:
970130803Smarcel	  puts_filtered ("Data (Read-Only, Exp-up");
971130803Smarcel	  break;
972130803Smarcel	case 1:
973130803Smarcel	  puts_filtered ("Data (Read/Write, Exp-up");
974130803Smarcel	  break;
975130803Smarcel	case 2:
976130803Smarcel	  puts_filtered ("Unused segment (");
977130803Smarcel	  break;
978130803Smarcel	case 3:
979130803Smarcel	  puts_filtered ("Data (Read/Write, Exp-down");
980130803Smarcel	  break;
981130803Smarcel	case 4:
982130803Smarcel	  puts_filtered ("Code (Exec-Only, N.Conf");
983130803Smarcel	  break;
984130803Smarcel	case 5:
985130803Smarcel	  puts_filtered ("Code (Exec/Read, N.Conf");
986130803Smarcel	  break;
987130803Smarcel	case 6:
988130803Smarcel	  puts_filtered ("Code (Exec-Only, Conf");
989130803Smarcel	  break;
990130803Smarcel	case 7:
991130803Smarcel	  puts_filtered ("Code (Exec/Read, Conf");
992130803Smarcel	  break;
993130803Smarcel	default:
994130803Smarcel	  printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type);
995130803Smarcel	}
996130803Smarcel      if ((info.HighWord.Bits.Type & 0x1) == 0)
997130803Smarcel	puts_filtered(", N.Acc");
998130803Smarcel      puts_filtered (")\n");
999130803Smarcel      if ((info.HighWord.Bits.Type & 0x10) == 0)
1000130803Smarcel	puts_filtered("System selector ");
1001130803Smarcel      printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl);
1002130803Smarcel      if (info.HighWord.Bits.Granularity)
1003130803Smarcel	puts_filtered ("Page granular.\n");
1004130803Smarcel      else
1005130803Smarcel	puts_filtered ("Byte granular.\n");
1006130803Smarcel      return 1;
1007130803Smarcel    }
1008130803Smarcel  else
1009130803Smarcel    {
1010130803Smarcel      printf_filtered ("Invalid selector 0x%lx.\n",sel);
1011130803Smarcel      return 0;
1012130803Smarcel    }
1013130803Smarcel}
1014130803Smarcel
1015130803Smarcelstatic void
1016130803Smarceldisplay_selectors (char * args, int from_tty)
1017130803Smarcel{
1018130803Smarcel  if (!current_thread)
1019130803Smarcel    {
1020130803Smarcel      puts_filtered ("Impossible to display selectors now.\n");
1021130803Smarcel      return;
1022130803Smarcel    }
1023130803Smarcel  if (!args)
1024130803Smarcel    {
1025130803Smarcel
1026130803Smarcel      puts_filtered ("Selector $cs\n");
1027130803Smarcel      display_selector (current_thread->h,
1028130803Smarcel	current_thread->context.SegCs);
1029130803Smarcel      puts_filtered ("Selector $ds\n");
1030130803Smarcel      display_selector (current_thread->h,
1031130803Smarcel	current_thread->context.SegDs);
1032130803Smarcel      puts_filtered ("Selector $es\n");
1033130803Smarcel      display_selector (current_thread->h,
1034130803Smarcel	current_thread->context.SegEs);
1035130803Smarcel      puts_filtered ("Selector $ss\n");
1036130803Smarcel      display_selector (current_thread->h,
1037130803Smarcel	current_thread->context.SegSs);
1038130803Smarcel      puts_filtered ("Selector $fs\n");
1039130803Smarcel      display_selector (current_thread->h,
1040130803Smarcel	current_thread->context.SegFs);
1041130803Smarcel      puts_filtered ("Selector $gs\n");
1042130803Smarcel      display_selector (current_thread->h,
1043130803Smarcel	current_thread->context.SegGs);
1044130803Smarcel    }
1045130803Smarcel  else
1046130803Smarcel    {
1047130803Smarcel      int sel;
1048130803Smarcel      sel = parse_and_eval_long (args);
1049130803Smarcel      printf_filtered ("Selector \"%s\"\n",args);
1050130803Smarcel      display_selector (current_thread->h, sel);
1051130803Smarcel    }
1052130803Smarcel}
1053130803Smarcel
1054130803Smarcelstatic struct cmd_list_element *info_w32_cmdlist = NULL;
1055130803Smarcel
1056130803Smarcelstatic void
1057130803Smarcelinfo_w32_command (char *args, int from_tty)
1058130803Smarcel{
1059130803Smarcel  help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
1060130803Smarcel}
1061130803Smarcel
1062130803Smarcel
1063130803Smarcel#define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
1064130803Smarcel  printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \
1065130803Smarcel  (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress)
1066130803Smarcel
1067130803Smarcelstatic int
1068130803Smarcelhandle_exception (struct target_waitstatus *ourstatus)
1069130803Smarcel{
1070130803Smarcel  thread_info *th;
1071130803Smarcel  DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1072130803Smarcel
1073130803Smarcel  ourstatus->kind = TARGET_WAITKIND_STOPPED;
1074130803Smarcel
1075130803Smarcel  /* Record the context of the current thread */
1076130803Smarcel  th = thread_rec (current_event.dwThreadId, -1);
1077130803Smarcel
1078130803Smarcel  switch (code)
1079130803Smarcel    {
1080130803Smarcel    case EXCEPTION_ACCESS_VIOLATION:
1081130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
1082130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1083130803Smarcel      break;
1084130803Smarcel    case STATUS_STACK_OVERFLOW:
1085130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
1086130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1087130803Smarcel      break;
1088130803Smarcel    case STATUS_FLOAT_DENORMAL_OPERAND:
1089130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
1090130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1091130803Smarcel      break;
1092130803Smarcel    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1093130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
1094130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1095130803Smarcel      break;
1096130803Smarcel    case STATUS_FLOAT_INEXACT_RESULT:
1097130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
1098130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1099130803Smarcel      break;
1100130803Smarcel    case STATUS_FLOAT_INVALID_OPERATION:
1101130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
1102130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1103130803Smarcel      break;
1104130803Smarcel    case STATUS_FLOAT_OVERFLOW:
1105130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
1106130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1107130803Smarcel      break;
1108130803Smarcel    case STATUS_FLOAT_STACK_CHECK:
1109130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
1110130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1111130803Smarcel      break;
1112130803Smarcel    case STATUS_FLOAT_UNDERFLOW:
1113130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
1114130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1115130803Smarcel      break;
1116130803Smarcel    case STATUS_FLOAT_DIVIDE_BY_ZERO:
1117130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
1118130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1119130803Smarcel      break;
1120130803Smarcel    case STATUS_INTEGER_DIVIDE_BY_ZERO:
1121130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
1122130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1123130803Smarcel      break;
1124130803Smarcel    case STATUS_INTEGER_OVERFLOW:
1125130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
1126130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_FPE;
1127130803Smarcel      break;
1128130803Smarcel    case EXCEPTION_BREAKPOINT:
1129130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
1130130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1131130803Smarcel      break;
1132130803Smarcel    case DBG_CONTROL_C:
1133130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
1134130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_INT;
1135130803Smarcel      break;
1136130803Smarcel    case DBG_CONTROL_BREAK:
1137130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
1138130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_INT;
1139130803Smarcel      break;
1140130803Smarcel    case EXCEPTION_SINGLE_STEP:
1141130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
1142130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1143130803Smarcel      break;
1144130803Smarcel    case EXCEPTION_ILLEGAL_INSTRUCTION:
1145130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
1146130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_ILL;
1147130803Smarcel      break;
1148130803Smarcel    case EXCEPTION_PRIV_INSTRUCTION:
1149130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
1150130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_ILL;
1151130803Smarcel      break;
1152130803Smarcel    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1153130803Smarcel      DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
1154130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_ILL;
1155130803Smarcel      break;
1156130803Smarcel    default:
1157130803Smarcel      if (current_event.u.Exception.dwFirstChance)
1158130803Smarcel	return 0;
1159130803Smarcel      printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
1160130803Smarcel		    current_event.u.Exception.ExceptionRecord.ExceptionCode,
1161130803Smarcel	(DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
1162130803Smarcel      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1163130803Smarcel      break;
1164130803Smarcel    }
1165130803Smarcel  exception_count++;
1166130803Smarcel  last_sig = ourstatus->value.sig;
1167130803Smarcel  return 1;
1168130803Smarcel}
1169130803Smarcel
1170130803Smarcel/* Resume all artificially suspended threads if we are continuing
1171130803Smarcel   execution */
1172130803Smarcelstatic BOOL
1173130803Smarcelchild_continue (DWORD continue_status, int id)
1174130803Smarcel{
1175130803Smarcel  int i;
1176130803Smarcel  thread_info *th;
1177130803Smarcel  BOOL res;
1178130803Smarcel
1179130803Smarcel  DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n",
1180130803Smarcel		  current_event.dwProcessId, current_event.dwThreadId,
1181130803Smarcel		  continue_status == DBG_CONTINUE ?
1182130803Smarcel		  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
1183130803Smarcel  res = ContinueDebugEvent (current_event.dwProcessId,
1184130803Smarcel			    current_event.dwThreadId,
1185130803Smarcel			    continue_status);
1186130803Smarcel  continue_status = 0;
1187130803Smarcel  if (res)
1188130803Smarcel    for (th = &thread_head; (th = th->next) != NULL;)
1189130803Smarcel      if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
1190130803Smarcel	{
1191130803Smarcel
1192130803Smarcel	  for (i = 0; i < th->suspend_count; i++)
1193130803Smarcel	    (void) ResumeThread (th->h);
1194130803Smarcel	  th->suspend_count = 0;
1195130803Smarcel	  if (debug_registers_changed)
1196130803Smarcel	    {
1197130803Smarcel	      /* Only change the value of the debug registers */
1198130803Smarcel	      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
1199130803Smarcel	      th->context.Dr0 = dr[0];
1200130803Smarcel	      th->context.Dr1 = dr[1];
1201130803Smarcel	      th->context.Dr2 = dr[2];
1202130803Smarcel	      th->context.Dr3 = dr[3];
1203130803Smarcel	      /* th->context.Dr6 = dr[6];
1204130803Smarcel		 FIXME: should we set dr6 also ?? */
1205130803Smarcel	      th->context.Dr7 = dr[7];
1206130803Smarcel	      CHECK (SetThreadContext (th->h, &th->context));
1207130803Smarcel	      th->context.ContextFlags = 0;
1208130803Smarcel	    }
1209130803Smarcel	}
1210130803Smarcel
1211130803Smarcel  debug_registers_changed = 0;
1212130803Smarcel  return res;
1213130803Smarcel}
1214130803Smarcel
1215130803Smarcel/* Called in pathological case where Windows fails to send a
1216130803Smarcel   CREATE_PROCESS_DEBUG_EVENT after an attach.  */
1217130803SmarcelDWORD
1218130803Smarcelfake_create_process (void)
1219130803Smarcel{
1220130803Smarcel  current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
1221130803Smarcel					current_event.dwProcessId);
1222130803Smarcel  main_thread_id = current_event.dwThreadId;
1223130803Smarcel  current_thread = child_add_thread (main_thread_id,
1224130803Smarcel				     current_event.u.CreateThread.hThread);
1225130803Smarcel  return main_thread_id;
1226130803Smarcel}
1227130803Smarcel
1228130803Smarcel/* Get the next event from the child.  Return 1 if the event requires
1229130803Smarcel   handling by WFI (or whatever).
1230130803Smarcel */
1231130803Smarcelstatic int
1232130803Smarcelget_child_debug_event (int pid, struct target_waitstatus *ourstatus)
1233130803Smarcel{
1234130803Smarcel  BOOL debug_event;
1235130803Smarcel  DWORD continue_status, event_code;
1236130803Smarcel  thread_info *th;
1237130803Smarcel  static thread_info dummy_thread_info;
1238130803Smarcel  int retval = 0;
1239130803Smarcel
1240130803Smarcel  last_sig = TARGET_SIGNAL_0;
1241130803Smarcel
1242130803Smarcel  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
1243130803Smarcel    goto out;
1244130803Smarcel
1245130803Smarcel  event_count++;
1246130803Smarcel  continue_status = DBG_CONTINUE;
1247130803Smarcel
1248130803Smarcel  event_code = current_event.dwDebugEventCode;
1249130803Smarcel  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1250130803Smarcel  th = NULL;
1251130803Smarcel
1252130803Smarcel  switch (event_code)
1253130803Smarcel    {
1254130803Smarcel    case CREATE_THREAD_DEBUG_EVENT:
1255130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
1256130803Smarcel		     (unsigned) current_event.dwProcessId,
1257130803Smarcel		     (unsigned) current_event.dwThreadId,
1258130803Smarcel		     "CREATE_THREAD_DEBUG_EVENT"));
1259130803Smarcel      if (saw_create != 1)
1260130803Smarcel	{
1261130803Smarcel	  if (!saw_create && attach_flag)
1262130803Smarcel	    {
1263130803Smarcel	      /* Kludge around a Windows bug where first event is a create
1264130803Smarcel		 thread event.  Caused when attached process does not have
1265130803Smarcel		 a main thread. */
1266130803Smarcel	      retval = ourstatus->value.related_pid = fake_create_process ();
1267130803Smarcel	      saw_create++;
1268130803Smarcel	    }
1269130803Smarcel	  break;
1270130803Smarcel	}
1271130803Smarcel      /* Record the existence of this thread */
1272130803Smarcel      th = child_add_thread (current_event.dwThreadId,
1273130803Smarcel			     current_event.u.CreateThread.hThread);
1274130803Smarcel      if (info_verbose)
1275130803Smarcel	printf_unfiltered ("[New %s]\n",
1276130803Smarcel			   target_pid_to_str (
1277130803Smarcel			     pid_to_ptid (current_event.dwThreadId)));
1278130803Smarcel      retval = current_event.dwThreadId;
1279130803Smarcel      break;
1280130803Smarcel
1281130803Smarcel    case EXIT_THREAD_DEBUG_EVENT:
1282130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1283130803Smarcel		     (unsigned) current_event.dwProcessId,
1284130803Smarcel		     (unsigned) current_event.dwThreadId,
1285130803Smarcel		     "EXIT_THREAD_DEBUG_EVENT"));
1286130803Smarcel      if (current_event.dwThreadId != main_thread_id)
1287130803Smarcel	{
1288130803Smarcel	  child_delete_thread (current_event.dwThreadId);
1289130803Smarcel	  th = &dummy_thread_info;
1290130803Smarcel	}
1291130803Smarcel      break;
1292130803Smarcel
1293130803Smarcel    case CREATE_PROCESS_DEBUG_EVENT:
1294130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1295130803Smarcel		     (unsigned) current_event.dwProcessId,
1296130803Smarcel		     (unsigned) current_event.dwThreadId,
1297130803Smarcel		     "CREATE_PROCESS_DEBUG_EVENT"));
1298130803Smarcel      CloseHandle (current_event.u.CreateProcessInfo.hFile);
1299130803Smarcel      if (++saw_create != 1)
1300130803Smarcel	{
1301130803Smarcel	  CloseHandle (current_event.u.CreateProcessInfo.hProcess);
1302130803Smarcel	  break;
1303130803Smarcel	}
1304130803Smarcel
1305130803Smarcel      current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1306130803Smarcel      if (main_thread_id)
1307130803Smarcel	child_delete_thread (main_thread_id);
1308130803Smarcel      main_thread_id = current_event.dwThreadId;
1309130803Smarcel      /* Add the main thread */
1310130803Smarcel      th = child_add_thread (main_thread_id,
1311130803Smarcel			     current_event.u.CreateProcessInfo.hThread);
1312130803Smarcel      retval = ourstatus->value.related_pid = current_event.dwThreadId;
1313130803Smarcel      break;
1314130803Smarcel
1315130803Smarcel    case EXIT_PROCESS_DEBUG_EVENT:
1316130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1317130803Smarcel		     (unsigned) current_event.dwProcessId,
1318130803Smarcel		     (unsigned) current_event.dwThreadId,
1319130803Smarcel		     "EXIT_PROCESS_DEBUG_EVENT"));
1320130803Smarcel      if (saw_create != 1)
1321130803Smarcel	break;
1322130803Smarcel      ourstatus->kind = TARGET_WAITKIND_EXITED;
1323130803Smarcel      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1324130803Smarcel      CloseHandle (current_process_handle);
1325130803Smarcel      retval = main_thread_id;
1326130803Smarcel      break;
1327130803Smarcel
1328130803Smarcel    case LOAD_DLL_DEBUG_EVENT:
1329130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1330130803Smarcel		     (unsigned) current_event.dwProcessId,
1331130803Smarcel		     (unsigned) current_event.dwThreadId,
1332130803Smarcel		     "LOAD_DLL_DEBUG_EVENT"));
1333130803Smarcel      CloseHandle (current_event.u.LoadDll.hFile);
1334130803Smarcel      if (saw_create != 1)
1335130803Smarcel	break;
1336130803Smarcel      catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
1337130803Smarcel      registers_changed ();	/* mark all regs invalid */
1338130803Smarcel      ourstatus->kind = TARGET_WAITKIND_LOADED;
1339130803Smarcel      ourstatus->value.integer = 0;
1340130803Smarcel      retval = main_thread_id;
1341130803Smarcel      re_enable_breakpoints_in_shlibs ();
1342130803Smarcel      break;
1343130803Smarcel
1344130803Smarcel    case UNLOAD_DLL_DEBUG_EVENT:
1345130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1346130803Smarcel		     (unsigned) current_event.dwProcessId,
1347130803Smarcel		     (unsigned) current_event.dwThreadId,
1348130803Smarcel		     "UNLOAD_DLL_DEBUG_EVENT"));
1349130803Smarcel      if (saw_create != 1)
1350130803Smarcel	break;
1351130803Smarcel      catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
1352130803Smarcel      registers_changed ();	/* mark all regs invalid */
1353130803Smarcel      /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
1354130803Smarcel	 does not exist yet. */
1355130803Smarcel      break;
1356130803Smarcel
1357130803Smarcel    case EXCEPTION_DEBUG_EVENT:
1358130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1359130803Smarcel		     (unsigned) current_event.dwProcessId,
1360130803Smarcel		     (unsigned) current_event.dwThreadId,
1361130803Smarcel		     "EXCEPTION_DEBUG_EVENT"));
1362130803Smarcel      if (saw_create != 1)
1363130803Smarcel	break;
1364130803Smarcel      if (handle_exception (ourstatus))
1365130803Smarcel	retval = current_event.dwThreadId;
1366130803Smarcel      break;
1367130803Smarcel
1368130803Smarcel    case OUTPUT_DEBUG_STRING_EVENT:	/* message from the kernel */
1369130803Smarcel      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1370130803Smarcel		     (unsigned) current_event.dwProcessId,
1371130803Smarcel		     (unsigned) current_event.dwThreadId,
1372130803Smarcel		     "OUTPUT_DEBUG_STRING_EVENT"));
1373130803Smarcel      if (saw_create != 1)
1374130803Smarcel	break;
1375130803Smarcel      if (handle_output_debug_string (ourstatus))
1376130803Smarcel	retval = main_thread_id;
1377130803Smarcel      break;
1378130803Smarcel
1379130803Smarcel    default:
1380130803Smarcel      if (saw_create != 1)
1381130803Smarcel	break;
1382130803Smarcel      printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
1383130803Smarcel			 (DWORD) current_event.dwProcessId,
1384130803Smarcel			 (DWORD) current_event.dwThreadId);
1385130803Smarcel      printf_unfiltered ("                 unknown event code %ld\n",
1386130803Smarcel			 current_event.dwDebugEventCode);
1387130803Smarcel      break;
1388130803Smarcel    }
1389130803Smarcel
1390130803Smarcel  if (!retval || saw_create != 1)
1391130803Smarcel    CHECK (child_continue (continue_status, -1));
1392130803Smarcel  else
1393130803Smarcel    {
1394130803Smarcel      inferior_ptid = pid_to_ptid (retval);
1395130803Smarcel      current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
1396130803Smarcel    }
1397130803Smarcel
1398130803Smarcelout:
1399130803Smarcel  return retval;
1400130803Smarcel}
1401130803Smarcel
1402130803Smarcel/* Wait for interesting events to occur in the target process. */
1403130803Smarcelstatic ptid_t
1404130803Smarcelchild_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
1405130803Smarcel{
1406130803Smarcel  int pid = PIDGET (ptid);
1407130803Smarcel
1408130803Smarcel  /* We loop when we get a non-standard exception rather than return
1409130803Smarcel     with a SPURIOUS because resume can try and step or modify things,
1410130803Smarcel     which needs a current_thread->h.  But some of these exceptions mark
1411130803Smarcel     the birth or death of threads, which mean that the current thread
1412130803Smarcel     isn't necessarily what you think it is. */
1413130803Smarcel
1414130803Smarcel  while (1)
1415130803Smarcel    {
1416130803Smarcel      int retval = get_child_debug_event (pid, ourstatus);
1417130803Smarcel      if (retval)
1418130803Smarcel	return pid_to_ptid (retval);
1419130803Smarcel      else
1420130803Smarcel	{
1421130803Smarcel	  int detach = 0;
1422130803Smarcel
1423130803Smarcel	  if (ui_loop_hook != NULL)
1424130803Smarcel	    detach = ui_loop_hook (0);
1425130803Smarcel
1426130803Smarcel	  if (detach)
1427130803Smarcel	    child_kill_inferior ();
1428130803Smarcel	}
1429130803Smarcel    }
1430130803Smarcel}
1431130803Smarcel
1432130803Smarcelstatic void
1433130803Smarceldo_initial_child_stuff (DWORD pid)
1434130803Smarcel{
1435130803Smarcel  extern int stop_after_trap;
1436130803Smarcel  int i;
1437130803Smarcel
1438130803Smarcel  last_sig = TARGET_SIGNAL_0;
1439130803Smarcel  event_count = 0;
1440130803Smarcel  exception_count = 0;
1441130803Smarcel  debug_registers_changed = 0;
1442130803Smarcel  debug_registers_used = 0;
1443130803Smarcel  for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
1444130803Smarcel    dr[i] = 0;
1445130803Smarcel  current_event.dwProcessId = pid;
1446130803Smarcel  memset (&current_event, 0, sizeof (current_event));
1447130803Smarcel  push_target (&child_ops);
1448130803Smarcel  child_init_thread_list ();
1449130803Smarcel  disable_breakpoints_in_shlibs (1);
1450130803Smarcel  child_clear_solibs ();
1451130803Smarcel  clear_proceed_status ();
1452130803Smarcel  init_wait_for_inferior ();
1453130803Smarcel
1454130803Smarcel  target_terminal_init ();
1455130803Smarcel  target_terminal_inferior ();
1456130803Smarcel
1457130803Smarcel  while (1)
1458130803Smarcel    {
1459130803Smarcel      stop_after_trap = 1;
1460130803Smarcel      wait_for_inferior ();
1461130803Smarcel      if (stop_signal != TARGET_SIGNAL_TRAP)
1462130803Smarcel	resume (0, stop_signal);
1463130803Smarcel      else
1464130803Smarcel	break;
1465130803Smarcel    }
1466130803Smarcel  stop_after_trap = 0;
1467130803Smarcel  return;
1468130803Smarcel}
1469130803Smarcel
1470130803Smarcel/* Since Windows XP, detaching from a process is supported by Windows.
1471130803Smarcel   The following code tries loading the appropriate functions dynamically.
1472130803Smarcel   If loading these functions succeeds use them to actually detach from
1473130803Smarcel   the inferior process, otherwise behave as usual, pretending that
1474130803Smarcel   detach has worked. */
1475130803Smarcelstatic BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL);
1476130803Smarcelstatic BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
1477130803Smarcel
1478130803Smarcelstatic int
1479130803Smarcelhas_detach_ability (void)
1480130803Smarcel{
1481130803Smarcel  static HMODULE kernel32 = NULL;
1482130803Smarcel
1483130803Smarcel  if (!kernel32)
1484130803Smarcel    kernel32 = LoadLibrary ("kernel32.dll");
1485130803Smarcel  if (kernel32)
1486130803Smarcel    {
1487130803Smarcel      if (!DebugSetProcessKillOnExit)
1488130803Smarcel	DebugSetProcessKillOnExit = GetProcAddress (kernel32,
1489130803Smarcel						 "DebugSetProcessKillOnExit");
1490130803Smarcel      if (!DebugActiveProcessStop)
1491130803Smarcel	DebugActiveProcessStop = GetProcAddress (kernel32,
1492130803Smarcel						 "DebugActiveProcessStop");
1493130803Smarcel      if (DebugSetProcessKillOnExit && DebugActiveProcessStop)
1494130803Smarcel	return 1;
1495130803Smarcel    }
1496130803Smarcel  return 0;
1497130803Smarcel}
1498130803Smarcel
1499130803Smarcel/* Try to set or remove a user privilege to the current process.  Return -1
1500130803Smarcel   if that fails, the previous setting of that privilege otherwise.
1501130803Smarcel
1502130803Smarcel   This code is copied from the Cygwin source code and rearranged to allow
1503130803Smarcel   dynamically loading of the needed symbols from advapi32 which is only
1504130803Smarcel   available on NT/2K/XP. */
1505130803Smarcelstatic int
1506130803Smarcelset_process_privilege (const char *privilege, BOOL enable)
1507130803Smarcel{
1508130803Smarcel  static HMODULE advapi32 = NULL;
1509130803Smarcel  static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
1510130803Smarcel  static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
1511130803Smarcel  static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
1512130803Smarcel					      DWORD, PTOKEN_PRIVILEGES, PDWORD);
1513130803Smarcel
1514130803Smarcel  HANDLE token_hdl = NULL;
1515130803Smarcel  LUID restore_priv;
1516130803Smarcel  TOKEN_PRIVILEGES new_priv, orig_priv;
1517130803Smarcel  int ret = -1;
1518130803Smarcel  DWORD size;
1519130803Smarcel
1520130803Smarcel  if (GetVersion () >= 0x80000000)  /* No security availbale on 9x/Me */
1521130803Smarcel    return 0;
1522130803Smarcel
1523130803Smarcel  if (!advapi32)
1524130803Smarcel    {
1525130803Smarcel      if (!(advapi32 = LoadLibrary ("advapi32.dll")))
1526130803Smarcel	goto out;
1527130803Smarcel      if (!OpenProcessToken)
1528130803Smarcel	OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken");
1529130803Smarcel      if (!LookupPrivilegeValue)
1530130803Smarcel	LookupPrivilegeValue = GetProcAddress (advapi32,
1531130803Smarcel					       "LookupPrivilegeValueA");
1532130803Smarcel      if (!AdjustTokenPrivileges)
1533130803Smarcel	AdjustTokenPrivileges = GetProcAddress (advapi32,
1534130803Smarcel						"AdjustTokenPrivileges");
1535130803Smarcel      if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
1536130803Smarcel	{
1537130803Smarcel	  advapi32 = NULL;
1538130803Smarcel	  goto out;
1539130803Smarcel	}
1540130803Smarcel    }
1541130803Smarcel
1542130803Smarcel  if (!OpenProcessToken (GetCurrentProcess (),
1543130803Smarcel			 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
1544130803Smarcel			 &token_hdl))
1545130803Smarcel    goto out;
1546130803Smarcel
1547130803Smarcel  if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
1548130803Smarcel    goto out;
1549130803Smarcel
1550130803Smarcel  new_priv.PrivilegeCount = 1;
1551130803Smarcel  new_priv.Privileges[0].Luid = restore_priv;
1552130803Smarcel  new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
1553130803Smarcel
1554130803Smarcel  if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv,
1555130803Smarcel			      sizeof orig_priv, &orig_priv, &size))
1556130803Smarcel    goto out;
1557130803Smarcel#if 0
1558130803Smarcel  /* Disabled, otherwise every `attach' in an unprivileged user session
1559130803Smarcel     would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
1560130803Smarcel     child_attach(). */
1561130803Smarcel  /* AdjustTokenPrivileges returns TRUE even if the privilege could not
1562130803Smarcel     be enabled. GetLastError () returns an correct error code, though. */
1563130803Smarcel  if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
1564130803Smarcel    goto out;
1565130803Smarcel#endif
1566130803Smarcel
1567130803Smarcel  ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
1568130803Smarcel
1569130803Smarcelout:
1570130803Smarcel  if (token_hdl)
1571130803Smarcel    CloseHandle (token_hdl);
1572130803Smarcel
1573130803Smarcel  return ret;
1574130803Smarcel}
1575130803Smarcel
1576130803Smarcel/* Attach to process PID, then initialize for debugging it.  */
1577130803Smarcelstatic void
1578130803Smarcelchild_attach (char *args, int from_tty)
1579130803Smarcel{
1580130803Smarcel  BOOL ok;
1581130803Smarcel  DWORD pid;
1582130803Smarcel
1583130803Smarcel  if (!args)
1584130803Smarcel    error_no_arg ("process-id to attach");
1585130803Smarcel
1586130803Smarcel  if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
1587130803Smarcel    {
1588130803Smarcel      printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n");
1589130803Smarcel      printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n");
1590130803Smarcel    }
1591130803Smarcel
1592130803Smarcel  pid = strtoul (args, 0, 0);		/* Windows pid */
1593130803Smarcel
1594130803Smarcel  ok = DebugActiveProcess (pid);
1595130803Smarcel  saw_create = 0;
1596130803Smarcel
1597130803Smarcel  if (!ok)
1598130803Smarcel    {
1599130803Smarcel      /* Try fall back to Cygwin pid */
1600130803Smarcel      pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
1601130803Smarcel
1602130803Smarcel      if (pid > 0)
1603130803Smarcel	ok = DebugActiveProcess (pid);
1604130803Smarcel
1605130803Smarcel      if (!ok)
1606130803Smarcel	error ("Can't attach to process.");
1607130803Smarcel    }
1608130803Smarcel
1609130803Smarcel  if (has_detach_ability ())
1610130803Smarcel    DebugSetProcessKillOnExit (FALSE);
1611130803Smarcel
1612130803Smarcel  attach_flag = 1;
1613130803Smarcel
1614130803Smarcel  if (from_tty)
1615130803Smarcel    {
1616130803Smarcel      char *exec_file = (char *) get_exec_file (0);
1617130803Smarcel
1618130803Smarcel      if (exec_file)
1619130803Smarcel	printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
1620130803Smarcel			   target_pid_to_str (pid_to_ptid (pid)));
1621130803Smarcel      else
1622130803Smarcel	printf_unfiltered ("Attaching to %s\n",
1623130803Smarcel			   target_pid_to_str (pid_to_ptid (pid)));
1624130803Smarcel
1625130803Smarcel      gdb_flush (gdb_stdout);
1626130803Smarcel    }
1627130803Smarcel
1628130803Smarcel  do_initial_child_stuff (pid);
1629130803Smarcel  target_terminal_ours ();
1630130803Smarcel}
1631130803Smarcel
1632130803Smarcelstatic void
1633130803Smarcelchild_detach (char *args, int from_tty)
1634130803Smarcel{
1635130803Smarcel  int detached = 1;
1636130803Smarcel
1637130803Smarcel  if (has_detach_ability ())
1638130803Smarcel    {
1639130803Smarcel      delete_command (NULL, 0);
1640130803Smarcel      child_continue (DBG_CONTINUE, -1);
1641130803Smarcel      if (!DebugActiveProcessStop (current_event.dwProcessId))
1642130803Smarcel	{
1643130803Smarcel	  error ("Can't detach process %lu (error %lu)",
1644130803Smarcel		 current_event.dwProcessId, GetLastError ());
1645130803Smarcel	  detached = 0;
1646130803Smarcel	}
1647130803Smarcel      DebugSetProcessKillOnExit (FALSE);
1648130803Smarcel    }
1649130803Smarcel  if (detached && from_tty)
1650130803Smarcel    {
1651130803Smarcel      char *exec_file = get_exec_file (0);
1652130803Smarcel      if (exec_file == 0)
1653130803Smarcel	exec_file = "";
1654130803Smarcel      printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file,
1655130803Smarcel			 current_event.dwProcessId);
1656130803Smarcel      gdb_flush (gdb_stdout);
1657130803Smarcel    }
1658130803Smarcel  inferior_ptid = null_ptid;
1659130803Smarcel  unpush_target (&child_ops);
1660130803Smarcel}
1661130803Smarcel
1662130803Smarcel/* Print status information about what we're accessing.  */
1663130803Smarcel
1664130803Smarcelstatic void
1665130803Smarcelchild_files_info (struct target_ops *ignore)
1666130803Smarcel{
1667130803Smarcel  printf_unfiltered ("\tUsing the running image of %s %s.\n",
1668130803Smarcel      attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
1669130803Smarcel}
1670130803Smarcel
1671130803Smarcelstatic void
1672130803Smarcelchild_open (char *arg, int from_tty)
1673130803Smarcel{
1674130803Smarcel  error ("Use the \"run\" command to start a Unix child process.");
1675130803Smarcel}
1676130803Smarcel
1677130803Smarcel/* Start an inferior win32 child process and sets inferior_ptid to its pid.
1678130803Smarcel   EXEC_FILE is the file to run.
1679130803Smarcel   ALLARGS is a string containing the arguments to the program.
1680130803Smarcel   ENV is the environment vector to pass.  Errors reported with error().  */
1681130803Smarcel
1682130803Smarcelstatic void
1683130803Smarcelchild_create_inferior (char *exec_file, char *allargs, char **env)
1684130803Smarcel{
1685130803Smarcel  char *winenv;
1686130803Smarcel  char *temp;
1687130803Smarcel  int envlen;
1688130803Smarcel  int i;
1689130803Smarcel  STARTUPINFO si;
1690130803Smarcel  PROCESS_INFORMATION pi;
1691130803Smarcel  BOOL ret;
1692130803Smarcel  DWORD flags;
1693130803Smarcel  char *args;
1694130803Smarcel  char real_path[MAXPATHLEN];
1695130803Smarcel  char *toexec;
1696130803Smarcel  char shell[MAX_PATH + 1]; /* Path to shell */
1697130803Smarcel  const char *sh;
1698130803Smarcel  int tty;
1699130803Smarcel  int ostdin, ostdout, ostderr;
1700130803Smarcel
1701130803Smarcel  if (!exec_file)
1702130803Smarcel    error ("No executable specified, use `target exec'.\n");
1703130803Smarcel
1704130803Smarcel  memset (&si, 0, sizeof (si));
1705130803Smarcel  si.cb = sizeof (si);
1706130803Smarcel
1707130803Smarcel  if (!useshell)
1708130803Smarcel    {
1709130803Smarcel      flags = DEBUG_ONLY_THIS_PROCESS;
1710130803Smarcel      cygwin_conv_to_win32_path (exec_file, real_path);
1711130803Smarcel      toexec = real_path;
1712130803Smarcel    }
1713130803Smarcel  else
1714130803Smarcel    {
1715130803Smarcel      char *newallargs;
1716130803Smarcel      sh = getenv ("SHELL");
1717130803Smarcel      if (!sh)
1718130803Smarcel	sh = "/bin/sh";
1719130803Smarcel      cygwin_conv_to_win32_path (sh, shell);
1720130803Smarcel      newallargs = alloca (sizeof (" -c 'exec  '") + strlen (exec_file)
1721130803Smarcel			   + strlen (allargs) + 2);
1722130803Smarcel      sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
1723130803Smarcel      allargs = newallargs;
1724130803Smarcel      toexec = shell;
1725130803Smarcel      flags = DEBUG_PROCESS;
1726130803Smarcel    }
1727130803Smarcel
1728130803Smarcel  if (new_group)
1729130803Smarcel    flags |= CREATE_NEW_PROCESS_GROUP;
1730130803Smarcel
1731130803Smarcel  if (new_console)
1732130803Smarcel    flags |= CREATE_NEW_CONSOLE;
1733130803Smarcel
1734130803Smarcel  attach_flag = 0;
1735130803Smarcel
1736130803Smarcel  args = alloca (strlen (toexec) + strlen (allargs) + 2);
1737130803Smarcel  strcpy (args, toexec);
1738130803Smarcel  strcat (args, " ");
1739130803Smarcel  strcat (args, allargs);
1740130803Smarcel
1741130803Smarcel  /* Prepare the environment vars for CreateProcess.  */
1742130803Smarcel  {
1743130803Smarcel    /* This code used to assume all env vars were file names and would
1744130803Smarcel       translate them all to win32 style.  That obviously doesn't work in the
1745130803Smarcel       general case.  The current rule is that we only translate PATH.
1746130803Smarcel       We need to handle PATH because we're about to call CreateProcess and
1747130803Smarcel       it uses PATH to find DLL's.  Fortunately PATH has a well-defined value
1748130803Smarcel       in both posix and win32 environments.  cygwin.dll will change it back
1749130803Smarcel       to posix style if necessary.  */
1750130803Smarcel
1751130803Smarcel    static const char *conv_path_names[] =
1752130803Smarcel    {
1753130803Smarcel      "PATH=",
1754130803Smarcel      0
1755130803Smarcel    };
1756130803Smarcel
1757130803Smarcel    /* CreateProcess takes the environment list as a null terminated set of
1758130803Smarcel       strings (i.e. two nulls terminate the list).  */
1759130803Smarcel
1760130803Smarcel    /* Get total size for env strings.  */
1761130803Smarcel    for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1762130803Smarcel      {
1763130803Smarcel	int j, len;
1764130803Smarcel
1765130803Smarcel	for (j = 0; conv_path_names[j]; j++)
1766130803Smarcel	  {
1767130803Smarcel	    len = strlen (conv_path_names[j]);
1768130803Smarcel	    if (strncmp (conv_path_names[j], env[i], len) == 0)
1769130803Smarcel	      {
1770130803Smarcel		if (cygwin_posix_path_list_p (env[i] + len))
1771130803Smarcel		  envlen += len
1772130803Smarcel		    + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
1773130803Smarcel		else
1774130803Smarcel		  envlen += strlen (env[i]) + 1;
1775130803Smarcel		break;
1776130803Smarcel	      }
1777130803Smarcel	  }
1778130803Smarcel	if (conv_path_names[j] == NULL)
1779130803Smarcel	  envlen += strlen (env[i]) + 1;
1780130803Smarcel      }
1781130803Smarcel
1782130803Smarcel    winenv = alloca (envlen + 1);
1783130803Smarcel
1784130803Smarcel    /* Copy env strings into new buffer.  */
1785130803Smarcel    for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1786130803Smarcel      {
1787130803Smarcel	int j, len;
1788130803Smarcel
1789130803Smarcel	for (j = 0; conv_path_names[j]; j++)
1790130803Smarcel	  {
1791130803Smarcel	    len = strlen (conv_path_names[j]);
1792130803Smarcel	    if (strncmp (conv_path_names[j], env[i], len) == 0)
1793130803Smarcel	      {
1794130803Smarcel		if (cygwin_posix_path_list_p (env[i] + len))
1795130803Smarcel		  {
1796130803Smarcel		    memcpy (temp, env[i], len);
1797130803Smarcel		    cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
1798130803Smarcel		  }
1799130803Smarcel		else
1800130803Smarcel		  strcpy (temp, env[i]);
1801130803Smarcel		break;
1802130803Smarcel	      }
1803130803Smarcel	  }
1804130803Smarcel	if (conv_path_names[j] == NULL)
1805130803Smarcel	  strcpy (temp, env[i]);
1806130803Smarcel
1807130803Smarcel	temp += strlen (temp) + 1;
1808130803Smarcel      }
1809130803Smarcel
1810130803Smarcel    /* Final nil string to terminate new env.  */
1811130803Smarcel    *temp = 0;
1812130803Smarcel  }
1813130803Smarcel
1814130803Smarcel  if (!inferior_io_terminal)
1815130803Smarcel    tty = ostdin = ostdout = ostderr = -1;
1816130803Smarcel  else
1817130803Smarcel    {
1818130803Smarcel      tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
1819130803Smarcel      if (tty < 0)
1820130803Smarcel	{
1821130803Smarcel	  print_sys_errmsg (inferior_io_terminal, errno);
1822130803Smarcel	  ostdin = ostdout = ostderr = -1;
1823130803Smarcel	}
1824130803Smarcel      else
1825130803Smarcel	{
1826130803Smarcel	  ostdin = dup (0);
1827130803Smarcel	  ostdout = dup (1);
1828130803Smarcel	  ostderr = dup (2);
1829130803Smarcel	  dup2 (tty, 0);
1830130803Smarcel	  dup2 (tty, 1);
1831130803Smarcel	  dup2 (tty, 2);
1832130803Smarcel	}
1833130803Smarcel    }
1834130803Smarcel
1835130803Smarcel  ret = CreateProcess (0,
1836130803Smarcel		       args,	/* command line */
1837130803Smarcel		       NULL,	/* Security */
1838130803Smarcel		       NULL,	/* thread */
1839130803Smarcel		       TRUE,	/* inherit handles */
1840130803Smarcel		       flags,	/* start flags */
1841130803Smarcel		       winenv,
1842130803Smarcel		       NULL,	/* current directory */
1843130803Smarcel		       &si,
1844130803Smarcel		       &pi);
1845130803Smarcel  if (tty >= 0)
1846130803Smarcel    {
1847130803Smarcel      close (tty);
1848130803Smarcel      dup2 (ostdin, 0);
1849130803Smarcel      dup2 (ostdout, 1);
1850130803Smarcel      dup2 (ostderr, 2);
1851130803Smarcel      close (ostdin);
1852130803Smarcel      close (ostdout);
1853130803Smarcel      close (ostderr);
1854130803Smarcel    }
1855130803Smarcel
1856130803Smarcel  if (!ret)
1857130803Smarcel    error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ());
1858130803Smarcel
1859130803Smarcel  CloseHandle (pi.hThread);
1860130803Smarcel  CloseHandle (pi.hProcess);
1861130803Smarcel
1862130803Smarcel  if (useshell && shell[0] != '\0')
1863130803Smarcel    saw_create = -1;
1864130803Smarcel  else
1865130803Smarcel    saw_create = 0;
1866130803Smarcel
1867130803Smarcel  do_initial_child_stuff (pi.dwProcessId);
1868130803Smarcel
1869130803Smarcel  /* child_continue (DBG_CONTINUE, -1); */
1870130803Smarcel  proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
1871130803Smarcel}
1872130803Smarcel
1873130803Smarcelstatic void
1874130803Smarcelchild_mourn_inferior (void)
1875130803Smarcel{
1876130803Smarcel  (void) child_continue (DBG_CONTINUE, -1);
1877130803Smarcel  i386_cleanup_dregs();
1878130803Smarcel  unpush_target (&child_ops);
1879130803Smarcel  generic_mourn_inferior ();
1880130803Smarcel}
1881130803Smarcel
1882130803Smarcel/* Send a SIGINT to the process group.  This acts just like the user typed a
1883130803Smarcel   ^C on the controlling terminal. */
1884130803Smarcel
1885130803Smarcelstatic void
1886130803Smarcelchild_stop (void)
1887130803Smarcel{
1888130803Smarcel  DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
1889130803Smarcel  CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
1890130803Smarcel  registers_changed ();		/* refresh register state */
1891130803Smarcel}
1892130803Smarcel
1893130803Smarcelint
1894130803Smarcelchild_xfer_memory (CORE_ADDR memaddr, char *our, int len,
1895130803Smarcel		   int write, struct mem_attrib *mem,
1896130803Smarcel		   struct target_ops *target)
1897130803Smarcel{
1898130803Smarcel  DWORD done = 0;
1899130803Smarcel  if (write)
1900130803Smarcel    {
1901130803Smarcel      DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1902130803Smarcel		  len, (DWORD) memaddr));
1903130803Smarcel      if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1904130803Smarcel			       len, &done))
1905130803Smarcel	done = 0;
1906130803Smarcel      FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
1907130803Smarcel    }
1908130803Smarcel  else
1909130803Smarcel    {
1910130803Smarcel      DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1911130803Smarcel		  len, (DWORD) memaddr));
1912130803Smarcel      if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our,
1913130803Smarcel			      len, &done))
1914130803Smarcel	done = 0;
1915130803Smarcel    }
1916130803Smarcel  return done;
1917130803Smarcel}
1918130803Smarcel
1919130803Smarcelvoid
1920130803Smarcelchild_kill_inferior (void)
1921130803Smarcel{
1922130803Smarcel  CHECK (TerminateProcess (current_process_handle, 0));
1923130803Smarcel
1924130803Smarcel  for (;;)
1925130803Smarcel    {
1926130803Smarcel      if (!child_continue (DBG_CONTINUE, -1))
1927130803Smarcel	break;
1928130803Smarcel      if (!WaitForDebugEvent (&current_event, INFINITE))
1929130803Smarcel	break;
1930130803Smarcel      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1931130803Smarcel	break;
1932130803Smarcel    }
1933130803Smarcel
1934130803Smarcel  CHECK (CloseHandle (current_process_handle));
1935130803Smarcel
1936130803Smarcel  /* this may fail in an attached process so don't check. */
1937130803Smarcel  if (current_thread && current_thread->h)
1938130803Smarcel    (void) CloseHandle (current_thread->h);
1939130803Smarcel  target_mourn_inferior ();	/* or just child_mourn_inferior? */
1940130803Smarcel}
1941130803Smarcel
1942130803Smarcelvoid
1943130803Smarcelchild_resume (ptid_t ptid, int step, enum target_signal sig)
1944130803Smarcel{
1945130803Smarcel  thread_info *th;
1946130803Smarcel  DWORD continue_status = DBG_CONTINUE;
1947130803Smarcel
1948130803Smarcel  int pid = PIDGET (ptid);
1949130803Smarcel
1950130803Smarcel  if (sig != TARGET_SIGNAL_0)
1951130803Smarcel    {
1952130803Smarcel      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
1953130803Smarcel	{
1954130803Smarcel	  DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
1955130803Smarcel	}
1956130803Smarcel      else if (sig == last_sig)
1957130803Smarcel	continue_status = DBG_EXCEPTION_NOT_HANDLED;
1958130803Smarcel      else
1959130803Smarcel#if 0
1960130803Smarcel/* This code does not seem to work, because
1961130803Smarcel  the kernel does probably not consider changes in the ExceptionRecord
1962130803Smarcel  structure when passing the exception to the inferior.
1963130803Smarcel  Note that this seems possible in the exception handler itself.  */
1964130803Smarcel	{
1965130803Smarcel	  int i;
1966130803Smarcel	  for (i = 0; xlate[i].them != -1; i++)
1967130803Smarcel	    if (xlate[i].us == sig)
1968130803Smarcel	      {
1969130803Smarcel		current_event.u.Exception.ExceptionRecord.ExceptionCode =
1970130803Smarcel		  xlate[i].them;
1971130803Smarcel		continue_status = DBG_EXCEPTION_NOT_HANDLED;
1972130803Smarcel		break;
1973130803Smarcel	      }
1974130803Smarcel	  if (continue_status == DBG_CONTINUE)
1975130803Smarcel	    {
1976130803Smarcel	      DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
1977130803Smarcel	    }
1978130803Smarcel	}
1979130803Smarcel#endif
1980130803Smarcel	DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
1981130803Smarcel	  last_sig));
1982130803Smarcel    }
1983130803Smarcel
1984130803Smarcel  last_sig = TARGET_SIGNAL_0;
1985130803Smarcel
1986130803Smarcel  DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1987130803Smarcel	       pid, step, sig));
1988130803Smarcel
1989130803Smarcel  /* Get context for currently selected thread */
1990130803Smarcel  th = thread_rec (current_event.dwThreadId, FALSE);
1991130803Smarcel  if (th)
1992130803Smarcel    {
1993130803Smarcel      if (step)
1994130803Smarcel	{
1995130803Smarcel	  /* Single step by setting t bit */
1996130803Smarcel	  child_fetch_inferior_registers (PS_REGNUM);
1997130803Smarcel	  th->context.EFlags |= FLAG_TRACE_BIT;
1998130803Smarcel	}
1999130803Smarcel
2000130803Smarcel      if (th->context.ContextFlags)
2001130803Smarcel	{
2002130803Smarcel	  if (debug_registers_changed)
2003130803Smarcel	    {
2004130803Smarcel	      th->context.Dr0 = dr[0];
2005130803Smarcel	      th->context.Dr1 = dr[1];
2006130803Smarcel	      th->context.Dr2 = dr[2];
2007130803Smarcel	      th->context.Dr3 = dr[3];
2008130803Smarcel	      /* th->context.Dr6 = dr[6];
2009130803Smarcel	       FIXME: should we set dr6 also ?? */
2010130803Smarcel	      th->context.Dr7 = dr[7];
2011130803Smarcel	    }
2012130803Smarcel	  CHECK (SetThreadContext (th->h, &th->context));
2013130803Smarcel	  th->context.ContextFlags = 0;
2014130803Smarcel	}
2015130803Smarcel    }
2016130803Smarcel
2017130803Smarcel  /* Allow continuing with the same signal that interrupted us.
2018130803Smarcel     Otherwise complain. */
2019130803Smarcel
2020130803Smarcel  child_continue (continue_status, pid);
2021130803Smarcel}
2022130803Smarcel
2023130803Smarcelstatic void
2024130803Smarcelchild_prepare_to_store (void)
2025130803Smarcel{
2026130803Smarcel  /* Do nothing, since we can store individual regs */
2027130803Smarcel}
2028130803Smarcel
2029130803Smarcelstatic int
2030130803Smarcelchild_can_run (void)
2031130803Smarcel{
2032130803Smarcel  return 1;
2033130803Smarcel}
2034130803Smarcel
2035130803Smarcelstatic void
2036130803Smarcelchild_close (int x)
2037130803Smarcel{
2038130803Smarcel  DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
2039130803Smarcel		PIDGET (inferior_ptid)));
2040130803Smarcel}
2041130803Smarcel
2042130803Smarcelstruct target_ops child_ops;
2043130803Smarcel
2044130803Smarcelstatic void
2045130803Smarcelinit_child_ops (void)
2046130803Smarcel{
2047130803Smarcel  child_ops.to_shortname = "child";
2048130803Smarcel  child_ops.to_longname = "Win32 child process";
2049130803Smarcel  child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
2050130803Smarcel  child_ops.to_open = child_open;
2051130803Smarcel  child_ops.to_close = child_close;
2052130803Smarcel  child_ops.to_attach = child_attach;
2053130803Smarcel  child_ops.to_detach = child_detach;
2054130803Smarcel  child_ops.to_resume = child_resume;
2055130803Smarcel  child_ops.to_wait = child_wait;
2056130803Smarcel  child_ops.to_fetch_registers = child_fetch_inferior_registers;
2057130803Smarcel  child_ops.to_store_registers = child_store_inferior_registers;
2058130803Smarcel  child_ops.to_prepare_to_store = child_prepare_to_store;
2059130803Smarcel  child_ops.to_xfer_memory = child_xfer_memory;
2060130803Smarcel  child_ops.to_files_info = child_files_info;
2061130803Smarcel  child_ops.to_insert_breakpoint = memory_insert_breakpoint;
2062130803Smarcel  child_ops.to_remove_breakpoint = memory_remove_breakpoint;
2063130803Smarcel  child_ops.to_terminal_init = terminal_init_inferior;
2064130803Smarcel  child_ops.to_terminal_inferior = terminal_inferior;
2065130803Smarcel  child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
2066130803Smarcel  child_ops.to_terminal_ours = terminal_ours;
2067130803Smarcel  child_ops.to_terminal_save_ours = terminal_save_ours;
2068130803Smarcel  child_ops.to_terminal_info = child_terminal_info;
2069130803Smarcel  child_ops.to_kill = child_kill_inferior;
2070130803Smarcel  child_ops.to_create_inferior = child_create_inferior;
2071130803Smarcel  child_ops.to_mourn_inferior = child_mourn_inferior;
2072130803Smarcel  child_ops.to_can_run = child_can_run;
2073130803Smarcel  child_ops.to_thread_alive = win32_child_thread_alive;
2074130803Smarcel  child_ops.to_pid_to_str = cygwin_pid_to_str;
2075130803Smarcel  child_ops.to_stop = child_stop;
2076130803Smarcel  child_ops.to_stratum = process_stratum;
2077130803Smarcel  child_ops.to_has_all_memory = 1;
2078130803Smarcel  child_ops.to_has_memory = 1;
2079130803Smarcel  child_ops.to_has_stack = 1;
2080130803Smarcel  child_ops.to_has_registers = 1;
2081130803Smarcel  child_ops.to_has_execution = 1;
2082130803Smarcel  child_ops.to_magic = OPS_MAGIC;
2083130803Smarcel}
2084130803Smarcel
2085130803Smarcelvoid
2086130803Smarcel_initialize_win32_nat (void)
2087130803Smarcel{
2088130803Smarcel  struct cmd_list_element *c;
2089130803Smarcel
2090130803Smarcel  init_child_ops ();
2091130803Smarcel
2092130803Smarcel  c = add_com ("dll-symbols", class_files, dll_symbol_command,
2093130803Smarcel	       "Load dll library symbols from FILE.");
2094130803Smarcel  set_cmd_completer (c, filename_completer);
2095130803Smarcel
2096130803Smarcel  add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
2097130803Smarcel
2098130803Smarcel  add_show_from_set (add_set_cmd ("shell", class_support, var_boolean,
2099130803Smarcel				  (char *) &useshell,
2100130803Smarcel		 "Set use of shell to start subprocess.",
2101130803Smarcel				  &setlist),
2102130803Smarcel		     &showlist);
2103130803Smarcel
2104130803Smarcel  add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
2105130803Smarcel				  (char *) &new_console,
2106130803Smarcel		 "Set creation of new console when creating child process.",
2107130803Smarcel				  &setlist),
2108130803Smarcel		     &showlist);
2109130803Smarcel
2110130803Smarcel  add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
2111130803Smarcel				  (char *) &new_group,
2112130803Smarcel		   "Set creation of new group when creating child process.",
2113130803Smarcel				  &setlist),
2114130803Smarcel		     &showlist);
2115130803Smarcel
2116130803Smarcel  add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
2117130803Smarcel				  (char *) &debug_exec,
2118130803Smarcel		       "Set whether to display execution in child process.",
2119130803Smarcel				  &setlist),
2120130803Smarcel		     &showlist);
2121130803Smarcel
2122130803Smarcel  add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
2123130803Smarcel				  (char *) &debug_events,
2124130803Smarcel		   "Set whether to display kernel events in child process.",
2125130803Smarcel				  &setlist),
2126130803Smarcel		     &showlist);
2127130803Smarcel
2128130803Smarcel  add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
2129130803Smarcel				  (char *) &debug_memory,
2130130803Smarcel		 "Set whether to display memory accesses in child process.",
2131130803Smarcel				  &setlist),
2132130803Smarcel		     &showlist);
2133130803Smarcel
2134130803Smarcel  add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
2135130803Smarcel				  (char *) &debug_exceptions,
2136130803Smarcel	       "Set whether to display kernel exceptions in child process.",
2137130803Smarcel				  &setlist),
2138130803Smarcel		     &showlist);
2139130803Smarcel
2140130803Smarcel  add_info ("dll", info_dll_command, "Status of loaded DLLs.");
2141130803Smarcel  add_info_alias ("sharedlibrary", "dll", 1);
2142130803Smarcel
2143130803Smarcel  add_prefix_cmd ("w32", class_info, info_w32_command,
2144130803Smarcel		  "Print information specific to Win32 debugging.",
2145130803Smarcel		  &info_w32_cmdlist, "info w32 ", 0, &infolist);
2146130803Smarcel
2147130803Smarcel  add_cmd ("selector", class_info, display_selectors,
2148130803Smarcel	   "Display selectors infos.",
2149130803Smarcel	   &info_w32_cmdlist);
2150130803Smarcel
2151130803Smarcel  add_target (&child_ops);
2152130803Smarcel}
2153130803Smarcel
2154130803Smarcel/* Hardware watchpoint support, adapted from go32-nat.c code.  */
2155130803Smarcel
2156130803Smarcel/* Pass the address ADDR to the inferior in the I'th debug register.
2157130803Smarcel   Here we just store the address in dr array, the registers will be
2158130803Smarcel   actually set up when child_continue is called.  */
2159130803Smarcelvoid
2160130803Smarcelcygwin_set_dr (int i, CORE_ADDR addr)
2161130803Smarcel{
2162130803Smarcel  if (i < 0 || i > 3)
2163130803Smarcel    internal_error (__FILE__, __LINE__,
2164130803Smarcel		    "Invalid register %d in cygwin_set_dr.\n", i);
2165130803Smarcel  dr[i] = (unsigned) addr;
2166130803Smarcel  debug_registers_changed = 1;
2167130803Smarcel  debug_registers_used = 1;
2168130803Smarcel}
2169130803Smarcel
2170130803Smarcel/* Pass the value VAL to the inferior in the DR7 debug control
2171130803Smarcel   register.  Here we just store the address in D_REGS, the watchpoint
2172130803Smarcel   will be actually set up in child_wait.  */
2173130803Smarcelvoid
2174130803Smarcelcygwin_set_dr7 (unsigned val)
2175130803Smarcel{
2176130803Smarcel  dr[7] = val;
2177130803Smarcel  debug_registers_changed = 1;
2178130803Smarcel  debug_registers_used = 1;
2179130803Smarcel}
2180130803Smarcel
2181130803Smarcel/* Get the value of the DR6 debug status register from the inferior.
2182130803Smarcel   Here we just return the value stored in dr[6]
2183130803Smarcel   by the last call to thread_rec for current_event.dwThreadId id.  */
2184130803Smarcelunsigned
2185130803Smarcelcygwin_get_dr6 (void)
2186130803Smarcel{
2187130803Smarcel  return dr[6];
2188130803Smarcel}
2189130803Smarcel
2190130803Smarcel/* Determine if the thread referenced by "pid" is alive
2191130803Smarcel   by "polling" it.  If WaitForSingleObject returns WAIT_OBJECT_0
2192130803Smarcel   it means that the pid has died.  Otherwise it is assumed to be alive. */
2193130803Smarcelstatic int
2194130803Smarcelwin32_child_thread_alive (ptid_t ptid)
2195130803Smarcel{
2196130803Smarcel  int pid = PIDGET (ptid);
2197130803Smarcel
2198130803Smarcel  return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
2199130803Smarcel    FALSE : TRUE;
2200130803Smarcel}
2201130803Smarcel
2202130803Smarcel/* Convert pid to printable format. */
2203130803Smarcelchar *
2204130803Smarcelcygwin_pid_to_str (ptid_t ptid)
2205130803Smarcel{
2206130803Smarcel  static char buf[80];
2207130803Smarcel  int pid = PIDGET (ptid);
2208130803Smarcel
2209130803Smarcel  if ((DWORD) pid == current_event.dwProcessId)
2210130803Smarcel    sprintf (buf, "process %d", pid);
2211130803Smarcel  else
2212130803Smarcel    sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
2213130803Smarcel  return buf;
2214130803Smarcel}
2215130803Smarcel
2216130803Smarcelstatic int
2217130803Smarcelcore_dll_symbols_add (char *dll_name, DWORD base_addr)
2218130803Smarcel{
2219130803Smarcel  struct objfile *objfile;
2220130803Smarcel  char *objfile_basename;
2221130803Smarcel  const char *dll_basename;
2222130803Smarcel
2223130803Smarcel  if (!(dll_basename = strrchr (dll_name, '/')))
2224130803Smarcel    dll_basename = dll_name;
2225130803Smarcel  else
2226130803Smarcel    dll_basename++;
2227130803Smarcel
2228130803Smarcel  ALL_OBJFILES (objfile)
2229130803Smarcel  {
2230130803Smarcel    objfile_basename = strrchr (objfile->name, '/');
2231130803Smarcel
2232130803Smarcel    if (objfile_basename &&
2233130803Smarcel	strcmp (dll_basename, objfile_basename + 1) == 0)
2234130803Smarcel      {
2235130803Smarcel	printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
2236130803Smarcel			   base_addr, dll_name);
2237130803Smarcel	goto out;
2238130803Smarcel      }
2239130803Smarcel  }
2240130803Smarcel
2241130803Smarcel    register_loaded_dll (dll_name, base_addr + 0x1000);
2242130803Smarcel    solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
2243130803Smarcel
2244130803Smarcel  out:
2245130803Smarcel    return 1;
2246130803Smarcel  }
2247130803Smarcel
2248130803Smarcel  typedef struct
2249130803Smarcel  {
2250130803Smarcel    struct target_ops *target;
2251130803Smarcel    bfd_vma addr;
2252130803Smarcel  } map_code_section_args;
2253130803Smarcel
2254130803Smarcel  static void
2255130803Smarcel  map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
2256130803Smarcel  {
2257130803Smarcel    int old;
2258130803Smarcel    int update_coreops;
2259130803Smarcel    struct section_table *new_target_sect_ptr;
2260130803Smarcel
2261130803Smarcel    map_code_section_args *args = (map_code_section_args *) obj;
2262130803Smarcel    struct target_ops *target = args->target;
2263130803Smarcel    if (sect->flags & SEC_CODE)
2264130803Smarcel      {
2265130803Smarcel	update_coreops = core_ops.to_sections == target->to_sections;
2266130803Smarcel
2267130803Smarcel	if (target->to_sections)
2268130803Smarcel	  {
2269130803Smarcel	    old = target->to_sections_end - target->to_sections;
2270130803Smarcel	    target->to_sections = (struct section_table *)
2271130803Smarcel	      xrealloc ((char *) target->to_sections,
2272130803Smarcel			(sizeof (struct section_table)) * (1 + old));
2273130803Smarcel	  }
2274130803Smarcel	else
2275130803Smarcel	  {
2276130803Smarcel	    old = 0;
2277130803Smarcel	    target->to_sections = (struct section_table *)
2278130803Smarcel	      xmalloc ((sizeof (struct section_table)));
2279130803Smarcel	  }
2280130803Smarcel	target->to_sections_end = target->to_sections + (1 + old);
2281130803Smarcel
2282130803Smarcel	/* Update the to_sections field in the core_ops structure
2283130803Smarcel	   if needed.  */
2284130803Smarcel	if (update_coreops)
2285130803Smarcel	  {
2286130803Smarcel	    core_ops.to_sections = target->to_sections;
2287130803Smarcel	    core_ops.to_sections_end = target->to_sections_end;
2288130803Smarcel	  }
2289130803Smarcel	new_target_sect_ptr = target->to_sections + old;
2290130803Smarcel	new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
2291130803Smarcel	new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
2292130803Smarcel	  bfd_section_size (abfd, sect);;
2293130803Smarcel	new_target_sect_ptr->the_bfd_section = sect;
2294130803Smarcel	new_target_sect_ptr->bfd = abfd;
2295130803Smarcel      }
2296130803Smarcel  }
2297130803Smarcel
2298130803Smarcel  static int
2299130803Smarcel  dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
2300130803Smarcel{
2301130803Smarcel  bfd *dll_bfd;
2302130803Smarcel  map_code_section_args map_args;
2303130803Smarcel  asection *lowest_sect;
2304130803Smarcel  char *name;
2305130803Smarcel  if (dll_name == NULL || target == NULL)
2306130803Smarcel    return 0;
2307130803Smarcel  name = xstrdup (dll_name);
2308130803Smarcel  dll_bfd = bfd_openr (name, "pei-i386");
2309130803Smarcel  if (dll_bfd == NULL)
2310130803Smarcel    return 0;
2311130803Smarcel
2312130803Smarcel  if (bfd_check_format (dll_bfd, bfd_object))
2313130803Smarcel    {
2314130803Smarcel      lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
2315130803Smarcel      if (lowest_sect == NULL)
2316130803Smarcel	return 0;
2317130803Smarcel      map_args.target = target;
2318130803Smarcel      map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
2319130803Smarcel
2320130803Smarcel      bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
2321130803Smarcel    }
2322130803Smarcel
2323130803Smarcel  return 1;
2324130803Smarcel}
2325130803Smarcel
2326130803Smarcelstatic void
2327130803Smarcelcore_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
2328130803Smarcel{
2329130803Smarcel  struct target_ops *target = (struct target_ops *) obj;
2330130803Smarcel
2331130803Smarcel  DWORD base_addr;
2332130803Smarcel
2333130803Smarcel  int dll_name_size;
2334130803Smarcel  char *dll_name = NULL;
2335130803Smarcel  char *buf = NULL;
2336130803Smarcel  struct win32_pstatus *pstatus;
2337130803Smarcel  char *p;
2338130803Smarcel
2339130803Smarcel  if (strncmp (sect->name, ".module", 7))
2340130803Smarcel    return;
2341130803Smarcel
2342130803Smarcel  buf = (char *) xmalloc (sect->_raw_size + 1);
2343130803Smarcel  if (!buf)
2344130803Smarcel    {
2345130803Smarcel      printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2346130803Smarcel      goto out;
2347130803Smarcel    }
2348130803Smarcel  if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size))
2349130803Smarcel    goto out;
2350130803Smarcel
2351130803Smarcel  pstatus = (struct win32_pstatus *) buf;
2352130803Smarcel
2353130803Smarcel  memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
2354130803Smarcel  dll_name_size = pstatus->data.module_info.module_name_size;
2355130803Smarcel  if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size)
2356130803Smarcel      goto out;
2357130803Smarcel
2358130803Smarcel  dll_name = (char *) xmalloc (dll_name_size + 1);
2359130803Smarcel  if (!dll_name)
2360130803Smarcel    {
2361130803Smarcel      printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2362130803Smarcel      goto out;
2363130803Smarcel    }
2364130803Smarcel  strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
2365130803Smarcel
2366130803Smarcel  while ((p = strchr (dll_name, '\\')))
2367130803Smarcel    *p = '/';
2368130803Smarcel
2369130803Smarcel  if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
2370130803Smarcel    printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
2371130803Smarcel
2372130803Smarcel  if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
2373130803Smarcel    printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
2374130803Smarcel
2375130803Smarcelout:
2376130803Smarcel  if (buf)
2377130803Smarcel    xfree (buf);
2378130803Smarcel  if (dll_name)
2379130803Smarcel    xfree (dll_name);
2380130803Smarcel  return;
2381130803Smarcel}
2382130803Smarcel
2383130803Smarcelvoid
2384130803Smarcelchild_solib_add (char *filename, int from_tty, struct target_ops *target,
2385130803Smarcel		 int readsyms)
2386130803Smarcel{
2387130803Smarcel  if (!readsyms)
2388130803Smarcel    return;
2389130803Smarcel  if (core_bfd)
2390130803Smarcel    {
2391130803Smarcel      child_clear_solibs ();
2392130803Smarcel      bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
2393130803Smarcel    }
2394130803Smarcel  else
2395130803Smarcel    {
2396130803Smarcel      if (solib_end && solib_end->name)
2397130803Smarcel	     solib_end->objfile = solib_symbols_add (solib_end->name, from_tty,
2398130803Smarcel						solib_end->load_addr);
2399130803Smarcel    }
2400130803Smarcel}
2401130803Smarcel
2402130803Smarcelstatic void
2403130803Smarcelfetch_elf_core_registers (char *core_reg_sect,
2404130803Smarcel			  unsigned core_reg_size,
2405130803Smarcel			  int which,
2406130803Smarcel			  CORE_ADDR reg_addr)
2407130803Smarcel{
2408130803Smarcel  int r;
2409130803Smarcel  if (core_reg_size < sizeof (CONTEXT))
2410130803Smarcel    {
2411130803Smarcel      error ("Core file register section too small (%u bytes).", core_reg_size);
2412130803Smarcel      return;
2413130803Smarcel    }
2414130803Smarcel  for (r = 0; r < NUM_REGS; r++)
2415130803Smarcel    supply_register (r, core_reg_sect + mappings[r]);
2416130803Smarcel}
2417130803Smarcel
2418130803Smarcelstatic struct core_fns win32_elf_core_fns =
2419130803Smarcel{
2420130803Smarcel  bfd_target_elf_flavour,
2421130803Smarcel  default_check_format,
2422130803Smarcel  default_core_sniffer,
2423130803Smarcel  fetch_elf_core_registers,
2424130803Smarcel  NULL
2425130803Smarcel};
2426130803Smarcel
2427130803Smarcelvoid
2428130803Smarcel_initialize_core_win32 (void)
2429130803Smarcel{
2430130803Smarcel  add_core_fns (&win32_elf_core_fns);
2431130803Smarcel}
2432130803Smarcel
2433130803Smarcelvoid
2434130803Smarcel_initialize_check_for_gdb_ini (void)
2435130803Smarcel{
2436130803Smarcel  char *homedir;
2437130803Smarcel  if (inhibit_gdbinit)
2438130803Smarcel    return;
2439130803Smarcel
2440130803Smarcel  homedir = getenv ("HOME");
2441130803Smarcel  if (homedir)
2442130803Smarcel    {
2443130803Smarcel      char *p;
2444130803Smarcel      char *oldini = (char *) alloca (strlen (homedir) +
2445130803Smarcel				      sizeof ("/gdb.ini"));
2446130803Smarcel      strcpy (oldini, homedir);
2447130803Smarcel      p = strchr (oldini, '\0');
2448130803Smarcel      if (p > oldini && p[-1] != '/')
2449130803Smarcel	*p++ = '/';
2450130803Smarcel      strcpy (p, "gdb.ini");
2451130803Smarcel      if (access (oldini, 0) == 0)
2452130803Smarcel	{
2453130803Smarcel	  int len = strlen (oldini);
2454130803Smarcel	  char *newini = alloca (len + 1);
2455130803Smarcel	  sprintf (newini, "%.*s.gdbinit",
2456130803Smarcel	    (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
2457130803Smarcel	  warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini);
2458130803Smarcel	}
2459130803Smarcel    }
2460130803Smarcel}
2461