xref: /openbsd-src/gnu/usr.bin/binutils/gdb/win32-nat.c (revision 63addd46c1e40ca0f49488ddcdc4ab598023b0c1)
1e93f7393Sniklas /* Target-vector operations for controlling win32 child processes, for GDB.
2b725ae77Skettenis 
3*63addd46Skettenis    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4*63addd46Skettenis    Free Software Foundation, Inc.
5b725ae77Skettenis 
6b725ae77Skettenis    Contributed by Cygnus Solutions, A Red Hat Company.
7e93f7393Sniklas 
8e93f7393Sniklas    This file is part of GDB.
9e93f7393Sniklas 
10e93f7393Sniklas    This program is free software; you can redistribute it and/or modify
11e93f7393Sniklas    it under the terms of the GNU General Public License as published by
12e93f7393Sniklas    the Free Software Foundation; either version 2 of the License, or
13e93f7393Sniklas    (at your option) any later version.
14e93f7393Sniklas 
15e93f7393Sniklas    This program is distributed in the hope that it will be useful,
16e93f7393Sniklas    but WITHOUT ANY WARRANTY; without eve nthe implied warranty of
17e93f7393Sniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18e93f7393Sniklas    GNU General Public License for more details.
19e93f7393Sniklas 
20e93f7393Sniklas    You should have received a copy of the GNU General Public License
21e93f7393Sniklas    along with this program; if not, write to the Free Software
22b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
23b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
24e93f7393Sniklas 
25b725ae77Skettenis /* Originally by Steve Chamberlain, sac@cygnus.com */
26e93f7393Sniklas 
27b725ae77Skettenis /* We assume we're being built with and will be used for cygwin.  */
28e93f7393Sniklas 
29e93f7393Sniklas #include "defs.h"
30e93f7393Sniklas #include "frame.h"		/* required by inferior.h */
31e93f7393Sniklas #include "inferior.h"
32e93f7393Sniklas #include "target.h"
33e93f7393Sniklas #include "gdbcore.h"
34e93f7393Sniklas #include "command.h"
35b725ae77Skettenis #include "completer.h"
36b725ae77Skettenis #include "regcache.h"
37b725ae77Skettenis #include "top.h"
38e93f7393Sniklas #include <signal.h>
39e93f7393Sniklas #include <sys/types.h>
40e93f7393Sniklas #include <fcntl.h>
41e93f7393Sniklas #include <stdlib.h>
42e93f7393Sniklas #include <windows.h>
43b725ae77Skettenis #include <imagehlp.h>
44b725ae77Skettenis #include <sys/cygwin.h>
45e93f7393Sniklas 
46e93f7393Sniklas #include "buildsym.h"
47e93f7393Sniklas #include "symfile.h"
48e93f7393Sniklas #include "objfiles.h"
49e93f7393Sniklas #include "gdb_string.h"
50e93f7393Sniklas #include "gdbthread.h"
51e93f7393Sniklas #include "gdbcmd.h"
52e93f7393Sniklas #include <sys/param.h>
53e93f7393Sniklas #include <unistd.h>
54b725ae77Skettenis #include "exec.h"
55b725ae77Skettenis 
56b725ae77Skettenis #include "i386-tdep.h"
57b725ae77Skettenis #include "i387-tdep.h"
58b725ae77Skettenis 
59b725ae77Skettenis /* If we're not using the old Cygwin header file set, define the
60b725ae77Skettenis    following which never should have been in the generic Win32 API
61b725ae77Skettenis    headers in the first place since they were our own invention... */
62b725ae77Skettenis #ifndef _GNU_H_WINDOWS_H
63b725ae77Skettenis enum
64b725ae77Skettenis   {
65b725ae77Skettenis     FLAG_TRACE_BIT = 0x100,
66b725ae77Skettenis     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
67b725ae77Skettenis   };
68b725ae77Skettenis #endif
69b725ae77Skettenis #include <sys/procfs.h>
70b725ae77Skettenis #include <psapi.h>
71b725ae77Skettenis 
72b725ae77Skettenis #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
73b725ae77Skettenis 	| CONTEXT_EXTENDED_REGISTERS
74b725ae77Skettenis 
75b725ae77Skettenis static unsigned dr[8];
76b725ae77Skettenis static int debug_registers_changed;
77b725ae77Skettenis static int debug_registers_used;
78b725ae77Skettenis 
79b725ae77Skettenis /* The string sent by cygwin when it processes a signal.
80b725ae77Skettenis    FIXME: This should be in a cygwin include file. */
81b725ae77Skettenis #define CYGWIN_SIGNAL_STRING "cygwin: signal"
82e93f7393Sniklas 
83e93f7393Sniklas #define CHECK(x)	check (x, __FILE__,__LINE__)
84b725ae77Skettenis #define DEBUG_EXEC(x)	if (debug_exec)		printf_unfiltered x
85b725ae77Skettenis #define DEBUG_EVENTS(x)	if (debug_events)	printf_unfiltered x
86b725ae77Skettenis #define DEBUG_MEM(x)	if (debug_memory)	printf_unfiltered x
87b725ae77Skettenis #define DEBUG_EXCEPT(x)	if (debug_exceptions)	printf_unfiltered x
88e93f7393Sniklas 
89b725ae77Skettenis static void child_stop (void);
90b725ae77Skettenis static int win32_child_thread_alive (ptid_t);
91b725ae77Skettenis void child_kill_inferior (void);
92e93f7393Sniklas 
93b725ae77Skettenis static enum target_signal last_sig = TARGET_SIGNAL_0;
94b725ae77Skettenis /* Set if a signal was received from the debugged process */
95e93f7393Sniklas 
96b725ae77Skettenis /* Thread information structure used to track information that is
97b725ae77Skettenis    not available in gdb's thread structure. */
98b725ae77Skettenis typedef struct thread_info_struct
99b725ae77Skettenis   {
100b725ae77Skettenis     struct thread_info_struct *next;
101b725ae77Skettenis     DWORD id;
102b725ae77Skettenis     HANDLE h;
103b725ae77Skettenis     char *name;
104b725ae77Skettenis     int suspend_count;
105b725ae77Skettenis     int reload_context;
106b725ae77Skettenis     CONTEXT context;
107b725ae77Skettenis     STACKFRAME sf;
108b725ae77Skettenis   }
109b725ae77Skettenis thread_info;
110b725ae77Skettenis 
111b725ae77Skettenis static thread_info thread_head;
112e93f7393Sniklas 
113e93f7393Sniklas /* The process and thread handles for the above context. */
114e93f7393Sniklas 
115b725ae77Skettenis static DEBUG_EVENT current_event;	/* The current debug event from
116b725ae77Skettenis 					   WaitForDebugEvent */
117b725ae77Skettenis static HANDLE current_process_handle;	/* Currently executing process */
118b725ae77Skettenis static thread_info *current_thread;	/* Info on currently selected thread */
119b725ae77Skettenis static DWORD main_thread_id;		/* Thread ID of the main thread */
120e93f7393Sniklas 
121e93f7393Sniklas /* Counts of things. */
122e93f7393Sniklas static int exception_count = 0;
123e93f7393Sniklas static int event_count = 0;
124b725ae77Skettenis static int saw_create;
125e93f7393Sniklas 
126e93f7393Sniklas /* User options. */
127e93f7393Sniklas static int new_console = 0;
128b725ae77Skettenis static int new_group = 1;
129e93f7393Sniklas static int debug_exec = 0;		/* show execution */
130e93f7393Sniklas static int debug_events = 0;		/* show events from kernel */
131e93f7393Sniklas static int debug_memory = 0;		/* show target memory accesses */
132e93f7393Sniklas static int debug_exceptions = 0;	/* show target exceptions */
133b725ae77Skettenis static int useshell = 0;		/* use shell for subprocesses */
134e93f7393Sniklas 
135e93f7393Sniklas /* This vector maps GDB's idea of a register's number into an address
136e93f7393Sniklas    in the win32 exception context vector.
137e93f7393Sniklas 
138e93f7393Sniklas    It also contains the bit mask needed to load the register in question.
139e93f7393Sniklas 
140e93f7393Sniklas    One day we could read a reg, we could inspect the context we
141e93f7393Sniklas    already have loaded, if it doesn't have the bit set that we need,
142e93f7393Sniklas    we read that set of registers in using GetThreadContext.  If the
143e93f7393Sniklas    context already contains what we need, we just unpack it. Then to
144e93f7393Sniklas    write a register, first we have to ensure that the context contains
145e93f7393Sniklas    the other regs of the group, and then we copy the info in and set
146e93f7393Sniklas    out bit. */
147e93f7393Sniklas 
148b725ae77Skettenis #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
149b725ae77Skettenis static const int mappings[] =
150e93f7393Sniklas {
151b725ae77Skettenis   context_offset (Eax),
152b725ae77Skettenis   context_offset (Ecx),
153b725ae77Skettenis   context_offset (Edx),
154b725ae77Skettenis   context_offset (Ebx),
155b725ae77Skettenis   context_offset (Esp),
156b725ae77Skettenis   context_offset (Ebp),
157b725ae77Skettenis   context_offset (Esi),
158b725ae77Skettenis   context_offset (Edi),
159b725ae77Skettenis   context_offset (Eip),
160b725ae77Skettenis   context_offset (EFlags),
161b725ae77Skettenis   context_offset (SegCs),
162b725ae77Skettenis   context_offset (SegSs),
163b725ae77Skettenis   context_offset (SegDs),
164b725ae77Skettenis   context_offset (SegEs),
165b725ae77Skettenis   context_offset (SegFs),
166b725ae77Skettenis   context_offset (SegGs),
167b725ae77Skettenis   context_offset (FloatSave.RegisterArea[0 * 10]),
168b725ae77Skettenis   context_offset (FloatSave.RegisterArea[1 * 10]),
169b725ae77Skettenis   context_offset (FloatSave.RegisterArea[2 * 10]),
170b725ae77Skettenis   context_offset (FloatSave.RegisterArea[3 * 10]),
171b725ae77Skettenis   context_offset (FloatSave.RegisterArea[4 * 10]),
172b725ae77Skettenis   context_offset (FloatSave.RegisterArea[5 * 10]),
173b725ae77Skettenis   context_offset (FloatSave.RegisterArea[6 * 10]),
174b725ae77Skettenis   context_offset (FloatSave.RegisterArea[7 * 10]),
175b725ae77Skettenis   context_offset (FloatSave.ControlWord),
176b725ae77Skettenis   context_offset (FloatSave.StatusWord),
177b725ae77Skettenis   context_offset (FloatSave.TagWord),
178b725ae77Skettenis   context_offset (FloatSave.ErrorSelector),
179b725ae77Skettenis   context_offset (FloatSave.ErrorOffset),
180b725ae77Skettenis   context_offset (FloatSave.DataSelector),
181b725ae77Skettenis   context_offset (FloatSave.DataOffset),
182b725ae77Skettenis   context_offset (FloatSave.ErrorSelector)
183b725ae77Skettenis   /* XMM0-7 */ ,
184b725ae77Skettenis   context_offset (ExtendedRegisters[10*16]),
185b725ae77Skettenis   context_offset (ExtendedRegisters[11*16]),
186b725ae77Skettenis   context_offset (ExtendedRegisters[12*16]),
187b725ae77Skettenis   context_offset (ExtendedRegisters[13*16]),
188b725ae77Skettenis   context_offset (ExtendedRegisters[14*16]),
189b725ae77Skettenis   context_offset (ExtendedRegisters[15*16]),
190b725ae77Skettenis   context_offset (ExtendedRegisters[16*16]),
191b725ae77Skettenis   context_offset (ExtendedRegisters[17*16]),
192b725ae77Skettenis   /* MXCSR */
193b725ae77Skettenis   context_offset (ExtendedRegisters[24])
194e93f7393Sniklas };
195e93f7393Sniklas 
196b725ae77Skettenis #undef context_offset
197e93f7393Sniklas 
198e93f7393Sniklas /* This vector maps the target's idea of an exception (extracted
199e93f7393Sniklas    from the DEBUG_EVENT structure) to GDB's idea. */
200e93f7393Sniklas 
201e93f7393Sniklas struct xlate_exception
202e93f7393Sniklas   {
203e93f7393Sniklas     int them;
204e93f7393Sniklas     enum target_signal us;
205e93f7393Sniklas   };
206e93f7393Sniklas 
207e93f7393Sniklas static const struct xlate_exception
208e93f7393Sniklas   xlate[] =
209e93f7393Sniklas {
210e93f7393Sniklas   {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
211e93f7393Sniklas   {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
212e93f7393Sniklas   {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
213e93f7393Sniklas   {DBG_CONTROL_C, TARGET_SIGNAL_INT},
214e93f7393Sniklas   {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
215b725ae77Skettenis   {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE},
216e93f7393Sniklas   {-1, -1}};
217e93f7393Sniklas 
218e93f7393Sniklas static void
check(BOOL ok,const char * file,int line)219e93f7393Sniklas check (BOOL ok, const char *file, int line)
220e93f7393Sniklas {
221e93f7393Sniklas   if (!ok)
222b725ae77Skettenis     printf_filtered ("error return %s:%d was %lu\n", file, line,
223b725ae77Skettenis 		     GetLastError ());
224b725ae77Skettenis }
225b725ae77Skettenis 
226b725ae77Skettenis /* Find a thread record given a thread id.
227b725ae77Skettenis    If get_context then also retrieve the context for this
228b725ae77Skettenis    thread. */
229b725ae77Skettenis static thread_info *
thread_rec(DWORD id,int get_context)230b725ae77Skettenis thread_rec (DWORD id, int get_context)
231b725ae77Skettenis {
232b725ae77Skettenis   thread_info *th;
233b725ae77Skettenis 
234b725ae77Skettenis   for (th = &thread_head; (th = th->next) != NULL;)
235b725ae77Skettenis     if (th->id == id)
236b725ae77Skettenis       {
237b725ae77Skettenis 	if (!th->suspend_count && get_context)
238b725ae77Skettenis 	  {
239b725ae77Skettenis 	    if (get_context > 0 && id != current_event.dwThreadId)
240b725ae77Skettenis 	      th->suspend_count = SuspendThread (th->h) + 1;
241b725ae77Skettenis 	    else if (get_context < 0)
242b725ae77Skettenis 	      th->suspend_count = -1;
243b725ae77Skettenis 	    th->reload_context = 1;
244b725ae77Skettenis 	  }
245b725ae77Skettenis 	return th;
246b725ae77Skettenis       }
247b725ae77Skettenis 
248b725ae77Skettenis   return NULL;
249b725ae77Skettenis }
250b725ae77Skettenis 
251b725ae77Skettenis /* Add a thread to the thread list */
252b725ae77Skettenis static thread_info *
child_add_thread(DWORD id,HANDLE h)253b725ae77Skettenis child_add_thread (DWORD id, HANDLE h)
254b725ae77Skettenis {
255b725ae77Skettenis   thread_info *th;
256b725ae77Skettenis 
257b725ae77Skettenis   if ((th = thread_rec (id, FALSE)))
258b725ae77Skettenis     return th;
259b725ae77Skettenis 
260b725ae77Skettenis   th = (thread_info *) xmalloc (sizeof (*th));
261b725ae77Skettenis   memset (th, 0, sizeof (*th));
262b725ae77Skettenis   th->id = id;
263b725ae77Skettenis   th->h = h;
264b725ae77Skettenis   th->next = thread_head.next;
265b725ae77Skettenis   thread_head.next = th;
266b725ae77Skettenis   add_thread (pid_to_ptid (id));
267b725ae77Skettenis   /* Set the debug registers for the new thread in they are used.  */
268b725ae77Skettenis   if (debug_registers_used)
269b725ae77Skettenis     {
270b725ae77Skettenis       /* Only change the value of the debug registers.  */
271b725ae77Skettenis       th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
272b725ae77Skettenis       CHECK (GetThreadContext (th->h, &th->context));
273b725ae77Skettenis       th->context.Dr0 = dr[0];
274b725ae77Skettenis       th->context.Dr1 = dr[1];
275b725ae77Skettenis       th->context.Dr2 = dr[2];
276b725ae77Skettenis       th->context.Dr3 = dr[3];
277b725ae77Skettenis       /* th->context.Dr6 = dr[6];
278b725ae77Skettenis       FIXME: should we set dr6 also ?? */
279b725ae77Skettenis       th->context.Dr7 = dr[7];
280b725ae77Skettenis       CHECK (SetThreadContext (th->h, &th->context));
281b725ae77Skettenis       th->context.ContextFlags = 0;
282b725ae77Skettenis     }
283b725ae77Skettenis   return th;
284b725ae77Skettenis }
285b725ae77Skettenis 
286b725ae77Skettenis /* Clear out any old thread list and reintialize it to a
287b725ae77Skettenis    pristine state. */
288b725ae77Skettenis static void
child_init_thread_list(void)289b725ae77Skettenis child_init_thread_list (void)
290b725ae77Skettenis {
291b725ae77Skettenis   thread_info *th = &thread_head;
292b725ae77Skettenis 
293b725ae77Skettenis   DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
294b725ae77Skettenis   init_thread_list ();
295b725ae77Skettenis   while (th->next != NULL)
296b725ae77Skettenis     {
297b725ae77Skettenis       thread_info *here = th->next;
298b725ae77Skettenis       th->next = here->next;
299b725ae77Skettenis       (void) CloseHandle (here->h);
300b725ae77Skettenis       xfree (here);
301b725ae77Skettenis     }
302b725ae77Skettenis }
303b725ae77Skettenis 
304b725ae77Skettenis /* Delete a thread from the list of threads */
305b725ae77Skettenis static void
child_delete_thread(DWORD id)306b725ae77Skettenis child_delete_thread (DWORD id)
307b725ae77Skettenis {
308b725ae77Skettenis   thread_info *th;
309b725ae77Skettenis 
310b725ae77Skettenis   if (info_verbose)
311b725ae77Skettenis     printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
312b725ae77Skettenis   delete_thread (pid_to_ptid (id));
313b725ae77Skettenis 
314b725ae77Skettenis   for (th = &thread_head;
315b725ae77Skettenis        th->next != NULL && th->next->id != id;
316b725ae77Skettenis        th = th->next)
317b725ae77Skettenis     continue;
318b725ae77Skettenis 
319b725ae77Skettenis   if (th->next != NULL)
320b725ae77Skettenis     {
321b725ae77Skettenis       thread_info *here = th->next;
322b725ae77Skettenis       th->next = here->next;
323b725ae77Skettenis       CloseHandle (here->h);
324b725ae77Skettenis       xfree (here);
325b725ae77Skettenis     }
326b725ae77Skettenis }
327b725ae77Skettenis 
328b725ae77Skettenis static void
do_child_fetch_inferior_registers(int r)329b725ae77Skettenis do_child_fetch_inferior_registers (int r)
330b725ae77Skettenis {
331b725ae77Skettenis   char *context_offset = ((char *) &current_thread->context) + mappings[r];
332b725ae77Skettenis   long l;
333b725ae77Skettenis 
334b725ae77Skettenis   if (!current_thread)
335b725ae77Skettenis     return;	/* Windows sometimes uses a non-existent thread id in its
336b725ae77Skettenis 		   events */
337b725ae77Skettenis 
338b725ae77Skettenis   if (current_thread->reload_context)
339b725ae77Skettenis     {
340b725ae77Skettenis       thread_info *th = current_thread;
341b725ae77Skettenis       th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
342b725ae77Skettenis       GetThreadContext (th->h, &th->context);
343b725ae77Skettenis       /* Copy dr values from that thread.  */
344b725ae77Skettenis       dr[0] = th->context.Dr0;
345b725ae77Skettenis       dr[1] = th->context.Dr1;
346b725ae77Skettenis       dr[2] = th->context.Dr2;
347b725ae77Skettenis       dr[3] = th->context.Dr3;
348b725ae77Skettenis       dr[6] = th->context.Dr6;
349b725ae77Skettenis       dr[7] = th->context.Dr7;
350b725ae77Skettenis       current_thread->reload_context = 0;
351b725ae77Skettenis     }
352b725ae77Skettenis 
353b725ae77Skettenis #define I387_ST0_REGNUM I386_ST0_REGNUM
354b725ae77Skettenis 
355b725ae77Skettenis   if (r == I387_FISEG_REGNUM)
356b725ae77Skettenis     {
357b725ae77Skettenis       l = *((long *) context_offset) & 0xffff;
358*63addd46Skettenis       regcache_raw_supply (current_regcache, r, (char *) &l);
359b725ae77Skettenis     }
360b725ae77Skettenis   else if (r == I387_FOP_REGNUM)
361b725ae77Skettenis     {
362b725ae77Skettenis       l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
363*63addd46Skettenis       regcache_raw_supply (current_regcache, r, (char *) &l);
364b725ae77Skettenis     }
365b725ae77Skettenis   else if (r >= 0)
366*63addd46Skettenis     regcache_raw_supply (current_regcache, r, context_offset);
367b725ae77Skettenis   else
368b725ae77Skettenis     {
369b725ae77Skettenis       for (r = 0; r < NUM_REGS; r++)
370b725ae77Skettenis 	do_child_fetch_inferior_registers (r);
371b725ae77Skettenis     }
372b725ae77Skettenis 
373b725ae77Skettenis #undef I387_ST0_REGNUM
374e93f7393Sniklas }
375e93f7393Sniklas 
376e93f7393Sniklas static void
child_fetch_inferior_registers(int r)377e93f7393Sniklas child_fetch_inferior_registers (int r)
378e93f7393Sniklas {
379b725ae77Skettenis   current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
380b725ae77Skettenis   /* Check if current_thread exists.  Windows sometimes uses a non-existent
381b725ae77Skettenis      thread id in its events */
382b725ae77Skettenis   if (current_thread)
383b725ae77Skettenis     do_child_fetch_inferior_registers (r);
384e93f7393Sniklas }
385b725ae77Skettenis 
386b725ae77Skettenis static void
do_child_store_inferior_registers(int r)387b725ae77Skettenis do_child_store_inferior_registers (int r)
388b725ae77Skettenis {
389b725ae77Skettenis   if (!current_thread)
390b725ae77Skettenis     /* Windows sometimes uses a non-existent thread id in its events */;
391b725ae77Skettenis   else if (r >= 0)
392*63addd46Skettenis     regcache_raw_collect (current_regcache, r,
393*63addd46Skettenis 			  ((char *) &current_thread->context) + mappings[r]);
394e93f7393Sniklas   else
395e93f7393Sniklas     {
396b725ae77Skettenis       for (r = 0; r < NUM_REGS; r++)
397b725ae77Skettenis 	do_child_store_inferior_registers (r);
398e93f7393Sniklas     }
399e93f7393Sniklas }
400e93f7393Sniklas 
401b725ae77Skettenis /* Store a new register value into the current thread context */
402e93f7393Sniklas static void
child_store_inferior_registers(int r)403e93f7393Sniklas child_store_inferior_registers (int r)
404e93f7393Sniklas {
405b725ae77Skettenis   current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
406b725ae77Skettenis   /* Check if current_thread exists.  Windows sometimes uses a non-existent
407b725ae77Skettenis      thread id in its events */
408b725ae77Skettenis   if (current_thread)
409b725ae77Skettenis     do_child_store_inferior_registers (r);
410e93f7393Sniklas }
411b725ae77Skettenis 
412b725ae77Skettenis static int psapi_loaded = 0;
413b725ae77Skettenis static HMODULE psapi_module_handle = NULL;
414b725ae77Skettenis static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
415b725ae77Skettenis static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
416b725ae77Skettenis static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
417b725ae77Skettenis 
418b725ae77Skettenis int
psapi_get_dll_name(DWORD BaseAddress,char * dll_name_ret)419b725ae77Skettenis psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
420b725ae77Skettenis {
421b725ae77Skettenis   DWORD len;
422b725ae77Skettenis   MODULEINFO mi;
423b725ae77Skettenis   int i;
424b725ae77Skettenis   HMODULE dh_buf[1];
425b725ae77Skettenis   HMODULE *DllHandle = dh_buf;
426b725ae77Skettenis   DWORD cbNeeded;
427b725ae77Skettenis   BOOL ok;
428b725ae77Skettenis 
429b725ae77Skettenis   if (!psapi_loaded ||
430b725ae77Skettenis       psapi_EnumProcessModules == NULL ||
431b725ae77Skettenis       psapi_GetModuleInformation == NULL ||
432b725ae77Skettenis       psapi_GetModuleFileNameExA == NULL)
433b725ae77Skettenis     {
434b725ae77Skettenis       if (psapi_loaded)
435b725ae77Skettenis 	goto failed;
436b725ae77Skettenis       psapi_loaded = 1;
437b725ae77Skettenis       psapi_module_handle = LoadLibrary ("psapi.dll");
438b725ae77Skettenis       if (!psapi_module_handle)
439b725ae77Skettenis 	{
440b725ae77Skettenis 	  /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
441b725ae77Skettenis 	  goto failed;
442b725ae77Skettenis 	}
443b725ae77Skettenis       psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
444b725ae77Skettenis       psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
445b725ae77Skettenis       psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
446b725ae77Skettenis 						    "GetModuleFileNameExA");
447b725ae77Skettenis       if (psapi_EnumProcessModules == NULL ||
448b725ae77Skettenis 	  psapi_GetModuleInformation == NULL ||
449b725ae77Skettenis 	  psapi_GetModuleFileNameExA == NULL)
450b725ae77Skettenis 	goto failed;
451b725ae77Skettenis     }
452b725ae77Skettenis 
453b725ae77Skettenis   cbNeeded = 0;
454b725ae77Skettenis   ok = (*psapi_EnumProcessModules) (current_process_handle,
455b725ae77Skettenis 				    DllHandle,
456b725ae77Skettenis 				    sizeof (HMODULE),
457b725ae77Skettenis 				    &cbNeeded);
458b725ae77Skettenis 
459b725ae77Skettenis   if (!ok || !cbNeeded)
460b725ae77Skettenis     goto failed;
461b725ae77Skettenis 
462b725ae77Skettenis   DllHandle = (HMODULE *) alloca (cbNeeded);
463b725ae77Skettenis   if (!DllHandle)
464b725ae77Skettenis     goto failed;
465b725ae77Skettenis 
466b725ae77Skettenis   ok = (*psapi_EnumProcessModules) (current_process_handle,
467b725ae77Skettenis 				    DllHandle,
468b725ae77Skettenis 				    cbNeeded,
469b725ae77Skettenis 				    &cbNeeded);
470b725ae77Skettenis   if (!ok)
471b725ae77Skettenis     goto failed;
472b725ae77Skettenis 
473b725ae77Skettenis   for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
474b725ae77Skettenis     {
475b725ae77Skettenis       if (!(*psapi_GetModuleInformation) (current_process_handle,
476b725ae77Skettenis 					  DllHandle[i],
477b725ae77Skettenis 					  &mi,
478b725ae77Skettenis 					  sizeof (mi)))
479b725ae77Skettenis 	error ("Can't get module info");
480b725ae77Skettenis 
481b725ae77Skettenis       len = (*psapi_GetModuleFileNameExA) (current_process_handle,
482b725ae77Skettenis 					   DllHandle[i],
483b725ae77Skettenis 					   dll_name_ret,
484b725ae77Skettenis 					   MAX_PATH);
485b725ae77Skettenis       if (len == 0)
486b725ae77Skettenis 	error ("Error getting dll name: %u\n", (unsigned) GetLastError ());
487b725ae77Skettenis 
488b725ae77Skettenis       if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
489b725ae77Skettenis 	return 1;
490b725ae77Skettenis     }
491b725ae77Skettenis 
492b725ae77Skettenis failed:
493b725ae77Skettenis   dll_name_ret[0] = '\0';
494b725ae77Skettenis   return 0;
495b725ae77Skettenis }
496b725ae77Skettenis 
497b725ae77Skettenis /* Encapsulate the information required in a call to
498b725ae77Skettenis    symbol_file_add_args */
499b725ae77Skettenis struct safe_symbol_file_add_args
500b725ae77Skettenis {
501b725ae77Skettenis   char *name;
502b725ae77Skettenis   int from_tty;
503b725ae77Skettenis   struct section_addr_info *addrs;
504b725ae77Skettenis   int mainline;
505b725ae77Skettenis   int flags;
506b725ae77Skettenis   struct ui_file *err, *out;
507b725ae77Skettenis   struct objfile *ret;
508b725ae77Skettenis };
509b725ae77Skettenis 
510b725ae77Skettenis /* Maintain a linked list of "so" information. */
511b725ae77Skettenis struct so_stuff
512b725ae77Skettenis {
513b725ae77Skettenis   struct so_stuff *next;
514b725ae77Skettenis   DWORD load_addr;
515b725ae77Skettenis   DWORD end_addr;
516b725ae77Skettenis   int loaded;
517b725ae77Skettenis   struct objfile *objfile;
518b725ae77Skettenis   char name[1];
519b725ae77Skettenis } solib_start, *solib_end;
520b725ae77Skettenis 
521b725ae77Skettenis /* Call symbol_file_add with stderr redirected.  We don't care if there
522b725ae77Skettenis    are errors. */
523b725ae77Skettenis static int
safe_symbol_file_add_stub(void * argv)524b725ae77Skettenis safe_symbol_file_add_stub (void *argv)
525b725ae77Skettenis {
526b725ae77Skettenis #define p ((struct safe_symbol_file_add_args *)argv)
527b725ae77Skettenis   struct so_stuff *so = &solib_start;
528b725ae77Skettenis 
529b725ae77Skettenis   while ((so = so->next))
530b725ae77Skettenis     if (so->loaded && strcasecmp (so->name, p->name) == 0)
531b725ae77Skettenis       return 0;
532b725ae77Skettenis   p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
533b725ae77Skettenis   return !!p->ret;
534b725ae77Skettenis #undef p
535b725ae77Skettenis }
536b725ae77Skettenis 
537b725ae77Skettenis /* Restore gdb's stderr after calling symbol_file_add */
538b725ae77Skettenis static void
safe_symbol_file_add_cleanup(void * p)539b725ae77Skettenis safe_symbol_file_add_cleanup (void *p)
540b725ae77Skettenis {
541b725ae77Skettenis #define sp ((struct safe_symbol_file_add_args *)p)
542b725ae77Skettenis   gdb_flush (gdb_stderr);
543b725ae77Skettenis   gdb_flush (gdb_stdout);
544b725ae77Skettenis   ui_file_delete (gdb_stderr);
545b725ae77Skettenis   ui_file_delete (gdb_stdout);
546b725ae77Skettenis   gdb_stderr = sp->err;
547b725ae77Skettenis   gdb_stdout = sp->out;
548b725ae77Skettenis #undef sp
549b725ae77Skettenis }
550b725ae77Skettenis 
551b725ae77Skettenis /* symbol_file_add wrapper that prevents errors from being displayed. */
552b725ae77Skettenis static struct objfile *
safe_symbol_file_add(char * name,int from_tty,struct section_addr_info * addrs,int mainline,int flags)553b725ae77Skettenis safe_symbol_file_add (char *name, int from_tty,
554b725ae77Skettenis 		      struct section_addr_info *addrs,
555b725ae77Skettenis 		      int mainline, int flags)
556b725ae77Skettenis {
557b725ae77Skettenis   struct safe_symbol_file_add_args p;
558b725ae77Skettenis   struct cleanup *cleanup;
559b725ae77Skettenis 
560b725ae77Skettenis   cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
561b725ae77Skettenis 
562b725ae77Skettenis   p.err = gdb_stderr;
563b725ae77Skettenis   p.out = gdb_stdout;
564b725ae77Skettenis   gdb_flush (gdb_stderr);
565b725ae77Skettenis   gdb_flush (gdb_stdout);
566b725ae77Skettenis   gdb_stderr = ui_file_new ();
567b725ae77Skettenis   gdb_stdout = ui_file_new ();
568b725ae77Skettenis   p.name = name;
569b725ae77Skettenis   p.from_tty = from_tty;
570b725ae77Skettenis   p.addrs = addrs;
571b725ae77Skettenis   p.mainline = mainline;
572b725ae77Skettenis   p.flags = flags;
573b725ae77Skettenis   catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
574b725ae77Skettenis 
575b725ae77Skettenis   do_cleanups (cleanup);
576b725ae77Skettenis   return p.ret;
577b725ae77Skettenis }
578b725ae77Skettenis 
579b725ae77Skettenis /* Remember the maximum DLL length for printing in info dll command. */
580b725ae77Skettenis int max_dll_name_len;
581b725ae77Skettenis 
582b725ae77Skettenis static void
register_loaded_dll(const char * name,DWORD load_addr)583b725ae77Skettenis register_loaded_dll (const char *name, DWORD load_addr)
584b725ae77Skettenis {
585b725ae77Skettenis   struct so_stuff *so;
586b725ae77Skettenis   char ppath[MAX_PATH + 1];
587b725ae77Skettenis   char buf[MAX_PATH + 1];
588b725ae77Skettenis   char cwd[MAX_PATH + 1];
589b725ae77Skettenis   char *p;
590b725ae77Skettenis   WIN32_FIND_DATA w32_fd;
591b725ae77Skettenis   HANDLE h = FindFirstFile(name, &w32_fd);
592b725ae77Skettenis   MEMORY_BASIC_INFORMATION m;
593b725ae77Skettenis   size_t len;
594b725ae77Skettenis 
595b725ae77Skettenis   if (h == INVALID_HANDLE_VALUE)
596b725ae77Skettenis     strcpy (buf, name);
597e93f7393Sniklas   else
598e93f7393Sniklas     {
599b725ae77Skettenis       FindClose (h);
600b725ae77Skettenis       strcpy (buf, name);
601b725ae77Skettenis       if (GetCurrentDirectory (MAX_PATH + 1, cwd))
602e93f7393Sniklas 	{
603b725ae77Skettenis 	  p = strrchr (buf, '\\');
604b725ae77Skettenis 	  if (p)
605b725ae77Skettenis 	    p[1] = '\0';
606b725ae77Skettenis 	  SetCurrentDirectory (buf);
607b725ae77Skettenis 	  GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
608b725ae77Skettenis 	  SetCurrentDirectory (cwd);
609b725ae77Skettenis 	}
610b725ae77Skettenis     }
611b725ae77Skettenis 
612b725ae77Skettenis   cygwin_conv_to_posix_path (buf, ppath);
613b725ae77Skettenis   so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
614b725ae77Skettenis   so->loaded = 0;
615b725ae77Skettenis   so->load_addr = load_addr;
616b725ae77Skettenis   if (VirtualQueryEx (current_process_handle, (void *) load_addr, &m,
617b725ae77Skettenis 		      sizeof (m)))
618b725ae77Skettenis     so->end_addr = (DWORD) m.AllocationBase + m.RegionSize;
619b725ae77Skettenis   else
620b725ae77Skettenis     so->end_addr = load_addr + 0x2000;	/* completely arbitrary */
621b725ae77Skettenis 
622b725ae77Skettenis   so->next = NULL;
623b725ae77Skettenis   so->objfile = NULL;
624b725ae77Skettenis   strcpy (so->name, ppath);
625b725ae77Skettenis 
626b725ae77Skettenis   solib_end->next = so;
627b725ae77Skettenis   solib_end = so;
628b725ae77Skettenis   len = strlen (ppath);
629b725ae77Skettenis   if (len > max_dll_name_len)
630b725ae77Skettenis     max_dll_name_len = len;
631b725ae77Skettenis }
632b725ae77Skettenis 
633b725ae77Skettenis char *
get_image_name(HANDLE h,void * address,int unicode)634b725ae77Skettenis get_image_name (HANDLE h, void *address, int unicode)
635b725ae77Skettenis {
636b725ae77Skettenis   static char buf[(2 * MAX_PATH) + 1];
637b725ae77Skettenis   DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
638b725ae77Skettenis   char *address_ptr;
639b725ae77Skettenis   int len = 0;
640b725ae77Skettenis   char b[2];
641e93f7393Sniklas   DWORD done;
642e93f7393Sniklas 
643b725ae77Skettenis   /* Attempt to read the name of the dll that was detected.
644b725ae77Skettenis      This is documented to work only when actively debugging
645b725ae77Skettenis      a program.  It will not work for attached processes. */
646b725ae77Skettenis   if (address == NULL)
647b725ae77Skettenis     return NULL;
648e93f7393Sniklas 
649e93f7393Sniklas   /* See if we could read the address of a string, and that the
650e93f7393Sniklas      address isn't null. */
651b725ae77Skettenis   if (!ReadProcessMemory (h, address,  &address_ptr, sizeof (address_ptr), &done)
652b725ae77Skettenis       || done != sizeof (address_ptr) || !address_ptr)
653b725ae77Skettenis     return NULL;
654e93f7393Sniklas 
655b725ae77Skettenis   /* Find the length of the string */
656b725ae77Skettenis   while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
657b725ae77Skettenis 	 && (b[0] != 0 || b[size - 1] != 0) && done == size)
658b725ae77Skettenis     continue;
659e93f7393Sniklas 
660b725ae77Skettenis   if (!unicode)
661b725ae77Skettenis     ReadProcessMemory (h, address_ptr, buf, len, &done);
662e93f7393Sniklas   else
663e93f7393Sniklas     {
664b725ae77Skettenis       WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
665b725ae77Skettenis       ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
666e93f7393Sniklas 			 &done);
667b725ae77Skettenis 
668b725ae77Skettenis       WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
669e93f7393Sniklas     }
670e93f7393Sniklas 
671b725ae77Skettenis   return buf;
672b725ae77Skettenis }
673e93f7393Sniklas 
674b725ae77Skettenis /* Wait for child to do something.  Return pid of child, or -1 in case
675b725ae77Skettenis    of error; store status through argument pointer OURSTATUS.  */
676b725ae77Skettenis static int
handle_load_dll(void * dummy)677b725ae77Skettenis handle_load_dll (void *dummy)
678e93f7393Sniklas {
679b725ae77Skettenis   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
680b725ae77Skettenis   char dll_buf[MAX_PATH + 1];
681b725ae77Skettenis   char *dll_name = NULL;
682b725ae77Skettenis   char *p;
683e93f7393Sniklas 
684b725ae77Skettenis   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
685b725ae77Skettenis 
686b725ae77Skettenis   if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
687b725ae77Skettenis     dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
688b725ae77Skettenis 
689b725ae77Skettenis   dll_name = dll_buf;
690b725ae77Skettenis 
691b725ae77Skettenis   if (*dll_name == '\0')
692b725ae77Skettenis     dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode);
693b725ae77Skettenis   if (!dll_name)
694e93f7393Sniklas     return 1;
695e93f7393Sniklas 
696b725ae77Skettenis   register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000);
697e93f7393Sniklas 
698e93f7393Sniklas   return 1;
699e93f7393Sniklas }
700e93f7393Sniklas 
701e93f7393Sniklas static int
handle_unload_dll(void * dummy)702b725ae77Skettenis handle_unload_dll (void *dummy)
703e93f7393Sniklas {
704b725ae77Skettenis   DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
705b725ae77Skettenis   struct so_stuff *so;
706b725ae77Skettenis 
707b725ae77Skettenis   for (so = &solib_start; so->next != NULL; so = so->next)
708b725ae77Skettenis     if (so->next->load_addr == lpBaseOfDll)
709b725ae77Skettenis       {
710b725ae77Skettenis 	struct so_stuff *sodel = so->next;
711b725ae77Skettenis 	so->next = sodel->next;
712b725ae77Skettenis 	if (!so->next)
713b725ae77Skettenis 	  solib_end = so;
714b725ae77Skettenis 	if (sodel->objfile)
715b725ae77Skettenis 	  free_objfile (sodel->objfile);
716b725ae77Skettenis 	xfree(sodel);
717b725ae77Skettenis 	return 1;
718b725ae77Skettenis       }
719b725ae77Skettenis   error ("Error: dll starting at 0x%lx not found.\n", (DWORD) lpBaseOfDll);
720b725ae77Skettenis 
721b725ae77Skettenis   return 0;
722b725ae77Skettenis }
723b725ae77Skettenis 
724b725ae77Skettenis char *
solib_address(CORE_ADDR address)725b725ae77Skettenis solib_address (CORE_ADDR address)
726b725ae77Skettenis {
727b725ae77Skettenis   struct so_stuff *so;
728b725ae77Skettenis   for (so = &solib_start; so->next != NULL; so = so->next)
729b725ae77Skettenis     if (address >= so->load_addr && address <= so->end_addr)
730b725ae77Skettenis       return so->name;
731b725ae77Skettenis   return NULL;
732b725ae77Skettenis }
733b725ae77Skettenis 
734b725ae77Skettenis /* Return name of last loaded DLL. */
735b725ae77Skettenis char *
child_solib_loaded_library_pathname(int pid)736b725ae77Skettenis child_solib_loaded_library_pathname (int pid)
737b725ae77Skettenis {
738b725ae77Skettenis   return !solib_end || !solib_end->name[0] ? NULL : solib_end->name;
739b725ae77Skettenis }
740b725ae77Skettenis 
741b725ae77Skettenis /* Clear list of loaded DLLs. */
742b725ae77Skettenis void
child_clear_solibs(void)743b725ae77Skettenis child_clear_solibs (void)
744b725ae77Skettenis {
745b725ae77Skettenis   struct so_stuff *so, *so1 = solib_start.next;
746b725ae77Skettenis 
747b725ae77Skettenis   while ((so = so1) != NULL)
748b725ae77Skettenis     {
749b725ae77Skettenis       so1 = so->next;
750b725ae77Skettenis       xfree (so);
751b725ae77Skettenis     }
752b725ae77Skettenis 
753b725ae77Skettenis   solib_start.next = NULL;
754b725ae77Skettenis   solib_start.objfile = NULL;
755b725ae77Skettenis   solib_end = &solib_start;
756b725ae77Skettenis   max_dll_name_len = sizeof ("DLL Name") - 1;
757b725ae77Skettenis }
758b725ae77Skettenis 
759b725ae77Skettenis /* Get the loaded address of all sections, given that .text was loaded
760b725ae77Skettenis    at text_load. Assumes that all sections are subject to the same
761b725ae77Skettenis    relocation offset. Returns NULL if problems occur or if the
762b725ae77Skettenis    sections were not relocated. */
763b725ae77Skettenis 
764b725ae77Skettenis static struct section_addr_info *
get_relocated_section_addrs(bfd * abfd,CORE_ADDR text_load)765b725ae77Skettenis get_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load)
766b725ae77Skettenis {
767b725ae77Skettenis   struct section_addr_info *result = NULL;
768b725ae77Skettenis   int section_count = bfd_count_sections (abfd);
769b725ae77Skettenis   asection *text_section = bfd_get_section_by_name (abfd, ".text");
770b725ae77Skettenis   CORE_ADDR text_vma;
771b725ae77Skettenis 
772b725ae77Skettenis   if (!text_section)
773b725ae77Skettenis     {
774b725ae77Skettenis       /* Couldn't get the .text section. Weird. */
775b725ae77Skettenis     }
776b725ae77Skettenis 
777b725ae77Skettenis   else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section)))
778b725ae77Skettenis     {
779b725ae77Skettenis       /* DLL wasn't relocated. */
780b725ae77Skettenis     }
781b725ae77Skettenis 
782b725ae77Skettenis   else
783b725ae77Skettenis     {
784b725ae77Skettenis       /* Figure out all sections' loaded addresses. The offset here is
785b725ae77Skettenis 	 such that taking a bfd_get_section_vma() result and adding
786b725ae77Skettenis 	 offset will give the real load address of the section. */
787b725ae77Skettenis 
788b725ae77Skettenis       CORE_ADDR offset = text_load - text_vma;
789b725ae77Skettenis 
790b725ae77Skettenis       struct section_table *table_start = NULL;
791b725ae77Skettenis       struct section_table *table_end = NULL;
792b725ae77Skettenis       struct section_table *iter = NULL;
793b725ae77Skettenis 
794b725ae77Skettenis       build_section_table (abfd, &table_start, &table_end);
795b725ae77Skettenis 
796b725ae77Skettenis       for (iter = table_start; iter < table_end; ++iter)
797b725ae77Skettenis 	{
798b725ae77Skettenis 	  /* Relocated addresses. */
799b725ae77Skettenis 	  iter->addr += offset;
800b725ae77Skettenis 	  iter->endaddr += offset;
801b725ae77Skettenis 	}
802b725ae77Skettenis 
803b725ae77Skettenis       result = build_section_addr_info_from_section_table (table_start,
804b725ae77Skettenis 							   table_end);
805b725ae77Skettenis 
806b725ae77Skettenis       xfree (table_start);
807b725ae77Skettenis     }
808b725ae77Skettenis 
809b725ae77Skettenis   return result;
810b725ae77Skettenis }
811b725ae77Skettenis 
812b725ae77Skettenis /* Add DLL symbol information. */
813b725ae77Skettenis static struct objfile *
solib_symbols_add(char * name,int from_tty,CORE_ADDR load_addr)814b725ae77Skettenis solib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr)
815b725ae77Skettenis {
816b725ae77Skettenis   struct section_addr_info *addrs = NULL;
817b725ae77Skettenis   static struct objfile *result = NULL;
818b725ae77Skettenis   bfd *abfd = NULL;
819b725ae77Skettenis 
820b725ae77Skettenis   /* The symbols in a dll are offset by 0x1000, which is the
821b725ae77Skettenis      the offset from 0 of the first byte in an image - because
822b725ae77Skettenis      of the file header and the section alignment. */
823b725ae77Skettenis 
824b725ae77Skettenis   if (!name || !name[0])
825b725ae77Skettenis     return NULL;
826b725ae77Skettenis 
827b725ae77Skettenis   abfd = bfd_openr (name, "pei-i386");
828b725ae77Skettenis 
829b725ae77Skettenis   if (!abfd)
830b725ae77Skettenis     {
831b725ae77Skettenis       /* pei failed - try pe */
832b725ae77Skettenis       abfd = bfd_openr (name, "pe-i386");
833b725ae77Skettenis     }
834b725ae77Skettenis 
835b725ae77Skettenis   if (abfd)
836b725ae77Skettenis     {
837b725ae77Skettenis       if (bfd_check_format (abfd, bfd_object))
838b725ae77Skettenis 	{
839b725ae77Skettenis 	  addrs = get_relocated_section_addrs (abfd, load_addr);
840b725ae77Skettenis 	}
841b725ae77Skettenis 
842b725ae77Skettenis       bfd_close (abfd);
843b725ae77Skettenis     }
844b725ae77Skettenis 
845b725ae77Skettenis   if (addrs)
846b725ae77Skettenis     {
847b725ae77Skettenis       result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED);
848b725ae77Skettenis       free_section_addr_info (addrs);
849b725ae77Skettenis     }
850b725ae77Skettenis   else
851b725ae77Skettenis     {
852b725ae77Skettenis       /* Fallback on handling just the .text section. */
853b725ae77Skettenis       struct cleanup *my_cleanups;
854b725ae77Skettenis 
855b725ae77Skettenis       addrs = alloc_section_addr_info (1);
856b725ae77Skettenis       my_cleanups = make_cleanup (xfree, addrs);
857b725ae77Skettenis       addrs->other[0].name = ".text";
858b725ae77Skettenis       addrs->other[0].addr = load_addr;
859b725ae77Skettenis 
860b725ae77Skettenis       result = safe_symbol_file_add (name, from_tty, addrs, 0, OBJF_SHARED);
861b725ae77Skettenis       do_cleanups (my_cleanups);
862b725ae77Skettenis     }
863b725ae77Skettenis 
864b725ae77Skettenis   return result;
865b725ae77Skettenis }
866b725ae77Skettenis 
867b725ae77Skettenis /* Load DLL symbol info. */
868b725ae77Skettenis void
dll_symbol_command(char * args,int from_tty)869b725ae77Skettenis dll_symbol_command (char *args, int from_tty)
870b725ae77Skettenis {
871b725ae77Skettenis   int n;
872b725ae77Skettenis   dont_repeat ();
873b725ae77Skettenis 
874b725ae77Skettenis   if (args == NULL)
875b725ae77Skettenis     error ("dll-symbols requires a file name");
876b725ae77Skettenis 
877b725ae77Skettenis   n = strlen (args);
878b725ae77Skettenis   if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
879b725ae77Skettenis     {
880b725ae77Skettenis       char *newargs = (char *) alloca (n + 4 + 1);
881b725ae77Skettenis       strcpy (newargs, args);
882b725ae77Skettenis       strcat (newargs, ".dll");
883b725ae77Skettenis       args = newargs;
884b725ae77Skettenis     }
885b725ae77Skettenis 
886b725ae77Skettenis   safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
887b725ae77Skettenis }
888b725ae77Skettenis 
889b725ae77Skettenis /* List currently loaded DLLs. */
890b725ae77Skettenis void
info_dll_command(char * ignore,int from_tty)891b725ae77Skettenis info_dll_command (char *ignore, int from_tty)
892b725ae77Skettenis {
893b725ae77Skettenis   struct so_stuff *so = &solib_start;
894b725ae77Skettenis 
895b725ae77Skettenis   if (!so->next)
896b725ae77Skettenis     return;
897b725ae77Skettenis 
898b725ae77Skettenis   printf_filtered ("%*s  Load Address\n", -max_dll_name_len, "DLL Name");
899b725ae77Skettenis   while ((so = so->next) != NULL)
900b725ae77Skettenis     printf_filtered ("%*s  %08lx\n", -max_dll_name_len, so->name, so->load_addr);
901b725ae77Skettenis 
902b725ae77Skettenis   return;
903b725ae77Skettenis }
904b725ae77Skettenis 
905b725ae77Skettenis /* Handle DEBUG_STRING output from child process.
906b725ae77Skettenis    Cygwin prepends its messages with a "cygwin:".  Interpret this as
907b725ae77Skettenis    a Cygwin signal.  Otherwise just print the string as a warning. */
908b725ae77Skettenis static int
handle_output_debug_string(struct target_waitstatus * ourstatus)909b725ae77Skettenis handle_output_debug_string (struct target_waitstatus *ourstatus)
910b725ae77Skettenis {
911b725ae77Skettenis   char *s;
912b725ae77Skettenis   int gotasig = FALSE;
913b725ae77Skettenis 
914b725ae77Skettenis   if (!target_read_string
915b725ae77Skettenis     ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
916b725ae77Skettenis       || !s || !*s)
917b725ae77Skettenis     return gotasig;
918b725ae77Skettenis 
919b725ae77Skettenis   if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
920b725ae77Skettenis     {
921b725ae77Skettenis       if (strncmp (s, "cYg", 3) != 0)
922b725ae77Skettenis 	warning ("%s", s);
923b725ae77Skettenis     }
924b725ae77Skettenis   else
925b725ae77Skettenis     {
926b725ae77Skettenis       char *p;
927b725ae77Skettenis       int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
928b725ae77Skettenis       gotasig = target_signal_from_host (sig);
929b725ae77Skettenis       ourstatus->value.sig = gotasig;
930b725ae77Skettenis       if (gotasig)
931b725ae77Skettenis 	ourstatus->kind = TARGET_WAITKIND_STOPPED;
932b725ae77Skettenis     }
933b725ae77Skettenis 
934b725ae77Skettenis   xfree (s);
935b725ae77Skettenis   return gotasig;
936b725ae77Skettenis }
937b725ae77Skettenis 
938b725ae77Skettenis static int
display_selector(HANDLE thread,DWORD sel)939b725ae77Skettenis display_selector (HANDLE thread, DWORD sel)
940b725ae77Skettenis {
941b725ae77Skettenis   LDT_ENTRY info;
942b725ae77Skettenis   if (GetThreadSelectorEntry (thread, sel, &info))
943b725ae77Skettenis     {
944b725ae77Skettenis       int base, limit;
945b725ae77Skettenis       printf_filtered ("0x%03lx: ", sel);
946b725ae77Skettenis       if (!info.HighWord.Bits.Pres)
947b725ae77Skettenis 	{
948b725ae77Skettenis 	  puts_filtered ("Segment not present\n");
949b725ae77Skettenis 	  return 0;
950b725ae77Skettenis 	}
951b725ae77Skettenis       base = (info.HighWord.Bits.BaseHi << 24) +
952b725ae77Skettenis 	     (info.HighWord.Bits.BaseMid << 16)
953b725ae77Skettenis 	     + info.BaseLow;
954b725ae77Skettenis       limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow;
955b725ae77Skettenis       if (info.HighWord.Bits.Granularity)
956b725ae77Skettenis 	limit = (limit << 12) | 0xfff;
957b725ae77Skettenis       printf_filtered ("base=0x%08x limit=0x%08x", base, limit);
958b725ae77Skettenis       if (info.HighWord.Bits.Default_Big)
959b725ae77Skettenis 	puts_filtered(" 32-bit ");
960b725ae77Skettenis       else
961b725ae77Skettenis 	puts_filtered(" 16-bit ");
962b725ae77Skettenis       switch ((info.HighWord.Bits.Type & 0xf) >> 1)
963b725ae77Skettenis 	{
964b725ae77Skettenis 	case 0:
965b725ae77Skettenis 	  puts_filtered ("Data (Read-Only, Exp-up");
966b725ae77Skettenis 	  break;
967b725ae77Skettenis 	case 1:
968b725ae77Skettenis 	  puts_filtered ("Data (Read/Write, Exp-up");
969b725ae77Skettenis 	  break;
970b725ae77Skettenis 	case 2:
971b725ae77Skettenis 	  puts_filtered ("Unused segment (");
972b725ae77Skettenis 	  break;
973b725ae77Skettenis 	case 3:
974b725ae77Skettenis 	  puts_filtered ("Data (Read/Write, Exp-down");
975b725ae77Skettenis 	  break;
976b725ae77Skettenis 	case 4:
977b725ae77Skettenis 	  puts_filtered ("Code (Exec-Only, N.Conf");
978b725ae77Skettenis 	  break;
979b725ae77Skettenis 	case 5:
980b725ae77Skettenis 	  puts_filtered ("Code (Exec/Read, N.Conf");
981b725ae77Skettenis 	  break;
982b725ae77Skettenis 	case 6:
983b725ae77Skettenis 	  puts_filtered ("Code (Exec-Only, Conf");
984b725ae77Skettenis 	  break;
985b725ae77Skettenis 	case 7:
986b725ae77Skettenis 	  puts_filtered ("Code (Exec/Read, Conf");
987b725ae77Skettenis 	  break;
988b725ae77Skettenis 	default:
989b725ae77Skettenis 	  printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type);
990b725ae77Skettenis 	}
991b725ae77Skettenis       if ((info.HighWord.Bits.Type & 0x1) == 0)
992b725ae77Skettenis 	puts_filtered(", N.Acc");
993b725ae77Skettenis       puts_filtered (")\n");
994b725ae77Skettenis       if ((info.HighWord.Bits.Type & 0x10) == 0)
995b725ae77Skettenis 	puts_filtered("System selector ");
996b725ae77Skettenis       printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl);
997b725ae77Skettenis       if (info.HighWord.Bits.Granularity)
998b725ae77Skettenis 	puts_filtered ("Page granular.\n");
999b725ae77Skettenis       else
1000b725ae77Skettenis 	puts_filtered ("Byte granular.\n");
1001b725ae77Skettenis       return 1;
1002b725ae77Skettenis     }
1003b725ae77Skettenis   else
1004b725ae77Skettenis     {
1005b725ae77Skettenis       printf_filtered ("Invalid selector 0x%lx.\n",sel);
1006b725ae77Skettenis       return 0;
1007b725ae77Skettenis     }
1008b725ae77Skettenis }
1009b725ae77Skettenis 
1010b725ae77Skettenis static void
display_selectors(char * args,int from_tty)1011b725ae77Skettenis display_selectors (char * args, int from_tty)
1012b725ae77Skettenis {
1013b725ae77Skettenis   if (!current_thread)
1014b725ae77Skettenis     {
1015b725ae77Skettenis       puts_filtered ("Impossible to display selectors now.\n");
1016b725ae77Skettenis       return;
1017b725ae77Skettenis     }
1018b725ae77Skettenis   if (!args)
1019b725ae77Skettenis     {
1020b725ae77Skettenis 
1021b725ae77Skettenis       puts_filtered ("Selector $cs\n");
1022b725ae77Skettenis       display_selector (current_thread->h,
1023b725ae77Skettenis 	current_thread->context.SegCs);
1024b725ae77Skettenis       puts_filtered ("Selector $ds\n");
1025b725ae77Skettenis       display_selector (current_thread->h,
1026b725ae77Skettenis 	current_thread->context.SegDs);
1027b725ae77Skettenis       puts_filtered ("Selector $es\n");
1028b725ae77Skettenis       display_selector (current_thread->h,
1029b725ae77Skettenis 	current_thread->context.SegEs);
1030b725ae77Skettenis       puts_filtered ("Selector $ss\n");
1031b725ae77Skettenis       display_selector (current_thread->h,
1032b725ae77Skettenis 	current_thread->context.SegSs);
1033b725ae77Skettenis       puts_filtered ("Selector $fs\n");
1034b725ae77Skettenis       display_selector (current_thread->h,
1035b725ae77Skettenis 	current_thread->context.SegFs);
1036b725ae77Skettenis       puts_filtered ("Selector $gs\n");
1037b725ae77Skettenis       display_selector (current_thread->h,
1038b725ae77Skettenis 	current_thread->context.SegGs);
1039b725ae77Skettenis     }
1040b725ae77Skettenis   else
1041b725ae77Skettenis     {
1042b725ae77Skettenis       int sel;
1043b725ae77Skettenis       sel = parse_and_eval_long (args);
1044b725ae77Skettenis       printf_filtered ("Selector \"%s\"\n",args);
1045b725ae77Skettenis       display_selector (current_thread->h, sel);
1046b725ae77Skettenis     }
1047b725ae77Skettenis }
1048b725ae77Skettenis 
1049b725ae77Skettenis static struct cmd_list_element *info_w32_cmdlist = NULL;
1050b725ae77Skettenis 
1051b725ae77Skettenis static void
info_w32_command(char * args,int from_tty)1052b725ae77Skettenis info_w32_command (char *args, int from_tty)
1053b725ae77Skettenis {
1054b725ae77Skettenis   help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
1055b725ae77Skettenis }
1056b725ae77Skettenis 
1057b725ae77Skettenis 
1058b725ae77Skettenis #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
1059b725ae77Skettenis   printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \
1060b725ae77Skettenis   (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress)
1061b725ae77Skettenis 
1062b725ae77Skettenis static int
handle_exception(struct target_waitstatus * ourstatus)1063b725ae77Skettenis handle_exception (struct target_waitstatus *ourstatus)
1064b725ae77Skettenis {
1065b725ae77Skettenis   thread_info *th;
1066b725ae77Skettenis   DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1067b725ae77Skettenis 
1068b725ae77Skettenis   ourstatus->kind = TARGET_WAITKIND_STOPPED;
1069b725ae77Skettenis 
1070b725ae77Skettenis   /* Record the context of the current thread */
1071b725ae77Skettenis   th = thread_rec (current_event.dwThreadId, -1);
1072b725ae77Skettenis 
1073b725ae77Skettenis   switch (code)
1074b725ae77Skettenis     {
1075b725ae77Skettenis     case EXCEPTION_ACCESS_VIOLATION:
1076b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
1077b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1078b725ae77Skettenis       break;
1079b725ae77Skettenis     case STATUS_STACK_OVERFLOW:
1080b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
1081b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1082b725ae77Skettenis       break;
1083b725ae77Skettenis     case STATUS_FLOAT_DENORMAL_OPERAND:
1084b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
1085b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1086b725ae77Skettenis       break;
1087b725ae77Skettenis     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1088b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
1089b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1090b725ae77Skettenis       break;
1091b725ae77Skettenis     case STATUS_FLOAT_INEXACT_RESULT:
1092b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
1093b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1094b725ae77Skettenis       break;
1095b725ae77Skettenis     case STATUS_FLOAT_INVALID_OPERATION:
1096b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
1097b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1098b725ae77Skettenis       break;
1099b725ae77Skettenis     case STATUS_FLOAT_OVERFLOW:
1100b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
1101b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1102b725ae77Skettenis       break;
1103b725ae77Skettenis     case STATUS_FLOAT_STACK_CHECK:
1104b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
1105b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1106b725ae77Skettenis       break;
1107b725ae77Skettenis     case STATUS_FLOAT_UNDERFLOW:
1108b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
1109b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1110b725ae77Skettenis       break;
1111b725ae77Skettenis     case STATUS_FLOAT_DIVIDE_BY_ZERO:
1112b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
1113b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1114b725ae77Skettenis       break;
1115b725ae77Skettenis     case STATUS_INTEGER_DIVIDE_BY_ZERO:
1116b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
1117b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1118b725ae77Skettenis       break;
1119b725ae77Skettenis     case STATUS_INTEGER_OVERFLOW:
1120b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
1121b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_FPE;
1122b725ae77Skettenis       break;
1123b725ae77Skettenis     case EXCEPTION_BREAKPOINT:
1124b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
1125b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1126b725ae77Skettenis       break;
1127b725ae77Skettenis     case DBG_CONTROL_C:
1128b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
1129b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_INT;
1130b725ae77Skettenis       break;
1131b725ae77Skettenis     case DBG_CONTROL_BREAK:
1132b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
1133b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_INT;
1134b725ae77Skettenis       break;
1135b725ae77Skettenis     case EXCEPTION_SINGLE_STEP:
1136b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
1137b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1138b725ae77Skettenis       break;
1139b725ae77Skettenis     case EXCEPTION_ILLEGAL_INSTRUCTION:
1140b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
1141b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_ILL;
1142b725ae77Skettenis       break;
1143b725ae77Skettenis     case EXCEPTION_PRIV_INSTRUCTION:
1144b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
1145b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_ILL;
1146b725ae77Skettenis       break;
1147b725ae77Skettenis     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1148b725ae77Skettenis       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
1149b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_ILL;
1150b725ae77Skettenis       break;
1151b725ae77Skettenis     default:
1152b725ae77Skettenis       if (current_event.u.Exception.dwFirstChance)
1153b725ae77Skettenis 	return 0;
1154b725ae77Skettenis       printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
1155b725ae77Skettenis 		    current_event.u.Exception.ExceptionRecord.ExceptionCode,
1156b725ae77Skettenis 	(DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
1157b725ae77Skettenis       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1158b725ae77Skettenis       break;
1159b725ae77Skettenis     }
1160b725ae77Skettenis   exception_count++;
1161b725ae77Skettenis   last_sig = ourstatus->value.sig;
1162b725ae77Skettenis   return 1;
1163b725ae77Skettenis }
1164b725ae77Skettenis 
1165b725ae77Skettenis /* Resume all artificially suspended threads if we are continuing
1166b725ae77Skettenis    execution */
1167b725ae77Skettenis static BOOL
child_continue(DWORD continue_status,int id)1168b725ae77Skettenis child_continue (DWORD continue_status, int id)
1169b725ae77Skettenis {
1170b725ae77Skettenis   int i;
1171b725ae77Skettenis   thread_info *th;
1172b725ae77Skettenis   BOOL res;
1173b725ae77Skettenis 
1174b725ae77Skettenis   DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n",
1175b725ae77Skettenis 		  current_event.dwProcessId, current_event.dwThreadId,
1176b725ae77Skettenis 		  continue_status == DBG_CONTINUE ?
1177b725ae77Skettenis 		  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
1178b725ae77Skettenis   res = ContinueDebugEvent (current_event.dwProcessId,
1179b725ae77Skettenis 			    current_event.dwThreadId,
1180b725ae77Skettenis 			    continue_status);
1181b725ae77Skettenis   continue_status = 0;
1182b725ae77Skettenis   if (res)
1183b725ae77Skettenis     for (th = &thread_head; (th = th->next) != NULL;)
1184b725ae77Skettenis       if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
1185b725ae77Skettenis 	{
1186b725ae77Skettenis 
1187b725ae77Skettenis 	  for (i = 0; i < th->suspend_count; i++)
1188b725ae77Skettenis 	    (void) ResumeThread (th->h);
1189b725ae77Skettenis 	  th->suspend_count = 0;
1190b725ae77Skettenis 	  if (debug_registers_changed)
1191b725ae77Skettenis 	    {
1192b725ae77Skettenis 	      /* Only change the value of the debug registers */
1193b725ae77Skettenis 	      th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
1194b725ae77Skettenis 	      th->context.Dr0 = dr[0];
1195b725ae77Skettenis 	      th->context.Dr1 = dr[1];
1196b725ae77Skettenis 	      th->context.Dr2 = dr[2];
1197b725ae77Skettenis 	      th->context.Dr3 = dr[3];
1198b725ae77Skettenis 	      /* th->context.Dr6 = dr[6];
1199b725ae77Skettenis 		 FIXME: should we set dr6 also ?? */
1200b725ae77Skettenis 	      th->context.Dr7 = dr[7];
1201b725ae77Skettenis 	      CHECK (SetThreadContext (th->h, &th->context));
1202b725ae77Skettenis 	      th->context.ContextFlags = 0;
1203b725ae77Skettenis 	    }
1204b725ae77Skettenis 	}
1205b725ae77Skettenis 
1206b725ae77Skettenis   debug_registers_changed = 0;
1207b725ae77Skettenis   return res;
1208b725ae77Skettenis }
1209b725ae77Skettenis 
1210b725ae77Skettenis /* Called in pathological case where Windows fails to send a
1211b725ae77Skettenis    CREATE_PROCESS_DEBUG_EVENT after an attach.  */
1212b725ae77Skettenis DWORD
fake_create_process(void)1213b725ae77Skettenis fake_create_process (void)
1214b725ae77Skettenis {
1215b725ae77Skettenis   current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
1216b725ae77Skettenis 					current_event.dwProcessId);
1217b725ae77Skettenis   main_thread_id = current_event.dwThreadId;
1218b725ae77Skettenis   current_thread = child_add_thread (main_thread_id,
1219b725ae77Skettenis 				     current_event.u.CreateThread.hThread);
1220b725ae77Skettenis   return main_thread_id;
1221b725ae77Skettenis }
1222b725ae77Skettenis 
1223b725ae77Skettenis /* Get the next event from the child.  Return 1 if the event requires
1224b725ae77Skettenis    handling by WFI (or whatever).
1225b725ae77Skettenis  */
1226b725ae77Skettenis static int
get_child_debug_event(int pid,struct target_waitstatus * ourstatus)1227b725ae77Skettenis get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
1228b725ae77Skettenis {
1229b725ae77Skettenis   BOOL debug_event;
1230b725ae77Skettenis   DWORD continue_status, event_code;
1231b725ae77Skettenis   thread_info *th;
1232b725ae77Skettenis   static thread_info dummy_thread_info;
1233b725ae77Skettenis   int retval = 0;
1234b725ae77Skettenis 
1235b725ae77Skettenis   last_sig = TARGET_SIGNAL_0;
1236b725ae77Skettenis 
1237b725ae77Skettenis   if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
1238b725ae77Skettenis     goto out;
1239b725ae77Skettenis 
1240b725ae77Skettenis   event_count++;
1241b725ae77Skettenis   continue_status = DBG_CONTINUE;
1242b725ae77Skettenis 
1243b725ae77Skettenis   event_code = current_event.dwDebugEventCode;
1244b725ae77Skettenis   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1245b725ae77Skettenis   th = NULL;
1246b725ae77Skettenis 
1247b725ae77Skettenis   switch (event_code)
1248b725ae77Skettenis     {
1249b725ae77Skettenis     case CREATE_THREAD_DEBUG_EVENT:
1250b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
1251b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1252b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1253b725ae77Skettenis 		     "CREATE_THREAD_DEBUG_EVENT"));
1254b725ae77Skettenis       if (saw_create != 1)
1255b725ae77Skettenis 	{
1256b725ae77Skettenis 	  if (!saw_create && attach_flag)
1257b725ae77Skettenis 	    {
1258b725ae77Skettenis 	      /* Kludge around a Windows bug where first event is a create
1259b725ae77Skettenis 		 thread event.  Caused when attached process does not have
1260b725ae77Skettenis 		 a main thread. */
1261b725ae77Skettenis 	      retval = ourstatus->value.related_pid = fake_create_process ();
1262b725ae77Skettenis 	      saw_create++;
1263b725ae77Skettenis 	    }
1264b725ae77Skettenis 	  break;
1265b725ae77Skettenis 	}
1266b725ae77Skettenis       /* Record the existence of this thread */
1267b725ae77Skettenis       th = child_add_thread (current_event.dwThreadId,
1268b725ae77Skettenis 			     current_event.u.CreateThread.hThread);
1269b725ae77Skettenis       if (info_verbose)
1270b725ae77Skettenis 	printf_unfiltered ("[New %s]\n",
1271b725ae77Skettenis 			   target_pid_to_str (
1272b725ae77Skettenis 			     pid_to_ptid (current_event.dwThreadId)));
1273b725ae77Skettenis       retval = current_event.dwThreadId;
1274b725ae77Skettenis       break;
1275b725ae77Skettenis 
1276b725ae77Skettenis     case EXIT_THREAD_DEBUG_EVENT:
1277b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1278b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1279b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1280b725ae77Skettenis 		     "EXIT_THREAD_DEBUG_EVENT"));
1281b725ae77Skettenis       if (current_event.dwThreadId != main_thread_id)
1282b725ae77Skettenis 	{
1283b725ae77Skettenis 	  child_delete_thread (current_event.dwThreadId);
1284b725ae77Skettenis 	  th = &dummy_thread_info;
1285b725ae77Skettenis 	}
1286b725ae77Skettenis       break;
1287b725ae77Skettenis 
1288b725ae77Skettenis     case CREATE_PROCESS_DEBUG_EVENT:
1289b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1290b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1291b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1292b725ae77Skettenis 		     "CREATE_PROCESS_DEBUG_EVENT"));
1293b725ae77Skettenis       CloseHandle (current_event.u.CreateProcessInfo.hFile);
1294b725ae77Skettenis       if (++saw_create != 1)
1295b725ae77Skettenis 	{
1296b725ae77Skettenis 	  CloseHandle (current_event.u.CreateProcessInfo.hProcess);
1297b725ae77Skettenis 	  break;
1298b725ae77Skettenis 	}
1299b725ae77Skettenis 
1300b725ae77Skettenis       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1301b725ae77Skettenis       if (main_thread_id)
1302b725ae77Skettenis 	child_delete_thread (main_thread_id);
1303b725ae77Skettenis       main_thread_id = current_event.dwThreadId;
1304b725ae77Skettenis       /* Add the main thread */
1305b725ae77Skettenis       th = child_add_thread (main_thread_id,
1306b725ae77Skettenis 			     current_event.u.CreateProcessInfo.hThread);
1307b725ae77Skettenis       retval = ourstatus->value.related_pid = current_event.dwThreadId;
1308b725ae77Skettenis       break;
1309b725ae77Skettenis 
1310b725ae77Skettenis     case EXIT_PROCESS_DEBUG_EVENT:
1311b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1312b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1313b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1314b725ae77Skettenis 		     "EXIT_PROCESS_DEBUG_EVENT"));
1315b725ae77Skettenis       if (saw_create != 1)
1316b725ae77Skettenis 	break;
1317b725ae77Skettenis       ourstatus->kind = TARGET_WAITKIND_EXITED;
1318b725ae77Skettenis       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1319b725ae77Skettenis       CloseHandle (current_process_handle);
1320b725ae77Skettenis       retval = main_thread_id;
1321b725ae77Skettenis       break;
1322b725ae77Skettenis 
1323b725ae77Skettenis     case LOAD_DLL_DEBUG_EVENT:
1324b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1325b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1326b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1327b725ae77Skettenis 		     "LOAD_DLL_DEBUG_EVENT"));
1328b725ae77Skettenis       CloseHandle (current_event.u.LoadDll.hFile);
1329b725ae77Skettenis       if (saw_create != 1)
1330b725ae77Skettenis 	break;
1331b725ae77Skettenis       catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
1332b725ae77Skettenis       registers_changed ();	/* mark all regs invalid */
1333b725ae77Skettenis       ourstatus->kind = TARGET_WAITKIND_LOADED;
1334b725ae77Skettenis       ourstatus->value.integer = 0;
1335b725ae77Skettenis       retval = main_thread_id;
1336b725ae77Skettenis       re_enable_breakpoints_in_shlibs ();
1337b725ae77Skettenis       break;
1338b725ae77Skettenis 
1339b725ae77Skettenis     case UNLOAD_DLL_DEBUG_EVENT:
1340b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1341b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1342b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1343b725ae77Skettenis 		     "UNLOAD_DLL_DEBUG_EVENT"));
1344b725ae77Skettenis       if (saw_create != 1)
1345b725ae77Skettenis 	break;
1346b725ae77Skettenis       catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
1347b725ae77Skettenis       registers_changed ();	/* mark all regs invalid */
1348b725ae77Skettenis       /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
1349b725ae77Skettenis 	 does not exist yet. */
1350b725ae77Skettenis       break;
1351b725ae77Skettenis 
1352b725ae77Skettenis     case EXCEPTION_DEBUG_EVENT:
1353b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1354b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1355b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1356b725ae77Skettenis 		     "EXCEPTION_DEBUG_EVENT"));
1357b725ae77Skettenis       if (saw_create != 1)
1358b725ae77Skettenis 	break;
1359b725ae77Skettenis       if (handle_exception (ourstatus))
1360b725ae77Skettenis 	retval = current_event.dwThreadId;
1361b725ae77Skettenis       break;
1362b725ae77Skettenis 
1363b725ae77Skettenis     case OUTPUT_DEBUG_STRING_EVENT:	/* message from the kernel */
1364b725ae77Skettenis       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1365b725ae77Skettenis 		     (unsigned) current_event.dwProcessId,
1366b725ae77Skettenis 		     (unsigned) current_event.dwThreadId,
1367b725ae77Skettenis 		     "OUTPUT_DEBUG_STRING_EVENT"));
1368b725ae77Skettenis       if (saw_create != 1)
1369b725ae77Skettenis 	break;
1370b725ae77Skettenis       if (handle_output_debug_string (ourstatus))
1371b725ae77Skettenis 	retval = main_thread_id;
1372b725ae77Skettenis       break;
1373b725ae77Skettenis 
1374b725ae77Skettenis     default:
1375b725ae77Skettenis       if (saw_create != 1)
1376b725ae77Skettenis 	break;
1377b725ae77Skettenis       printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
1378b725ae77Skettenis 			 (DWORD) current_event.dwProcessId,
1379b725ae77Skettenis 			 (DWORD) current_event.dwThreadId);
1380b725ae77Skettenis       printf_unfiltered ("                 unknown event code %ld\n",
1381b725ae77Skettenis 			 current_event.dwDebugEventCode);
1382b725ae77Skettenis       break;
1383b725ae77Skettenis     }
1384b725ae77Skettenis 
1385b725ae77Skettenis   if (!retval || saw_create != 1)
1386b725ae77Skettenis     CHECK (child_continue (continue_status, -1));
1387b725ae77Skettenis   else
1388b725ae77Skettenis     {
1389b725ae77Skettenis       inferior_ptid = pid_to_ptid (retval);
1390b725ae77Skettenis       current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
1391b725ae77Skettenis     }
1392b725ae77Skettenis 
1393b725ae77Skettenis out:
1394b725ae77Skettenis   return retval;
1395b725ae77Skettenis }
1396b725ae77Skettenis 
1397b725ae77Skettenis /* Wait for interesting events to occur in the target process. */
1398b725ae77Skettenis static ptid_t
child_wait(ptid_t ptid,struct target_waitstatus * ourstatus)1399b725ae77Skettenis child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
1400b725ae77Skettenis {
1401b725ae77Skettenis   int pid = PIDGET (ptid);
1402b725ae77Skettenis 
1403e93f7393Sniklas   /* We loop when we get a non-standard exception rather than return
1404e93f7393Sniklas      with a SPURIOUS because resume can try and step or modify things,
1405b725ae77Skettenis      which needs a current_thread->h.  But some of these exceptions mark
1406e93f7393Sniklas      the birth or death of threads, which mean that the current thread
1407e93f7393Sniklas      isn't necessarily what you think it is. */
1408e93f7393Sniklas 
1409e93f7393Sniklas   while (1)
1410e93f7393Sniklas     {
1411b725ae77Skettenis       int retval = get_child_debug_event (pid, ourstatus);
1412b725ae77Skettenis       if (retval)
1413b725ae77Skettenis 	return pid_to_ptid (retval);
1414b725ae77Skettenis       else
1415e93f7393Sniklas 	{
1416b725ae77Skettenis 	  int detach = 0;
1417e93f7393Sniklas 
1418*63addd46Skettenis 	  if (deprecated_ui_loop_hook != NULL)
1419*63addd46Skettenis 	    detach = deprecated_ui_loop_hook (0);
1420e93f7393Sniklas 
1421b725ae77Skettenis 	  if (detach)
1422b725ae77Skettenis 	    child_kill_inferior ();
1423b725ae77Skettenis 	}
1424b725ae77Skettenis     }
1425b725ae77Skettenis }
1426e93f7393Sniklas 
1427b725ae77Skettenis static void
do_initial_child_stuff(DWORD pid)1428b725ae77Skettenis do_initial_child_stuff (DWORD pid)
1429e93f7393Sniklas {
1430b725ae77Skettenis   extern int stop_after_trap;
1431b725ae77Skettenis   int i;
1432b725ae77Skettenis 
1433b725ae77Skettenis   last_sig = TARGET_SIGNAL_0;
1434b725ae77Skettenis   event_count = 0;
1435b725ae77Skettenis   exception_count = 0;
1436b725ae77Skettenis   debug_registers_changed = 0;
1437b725ae77Skettenis   debug_registers_used = 0;
1438b725ae77Skettenis   for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
1439b725ae77Skettenis     dr[i] = 0;
1440b725ae77Skettenis   current_event.dwProcessId = pid;
1441b725ae77Skettenis   memset (&current_event, 0, sizeof (current_event));
1442*63addd46Skettenis   push_target (&deprecated_child_ops);
1443b725ae77Skettenis   child_init_thread_list ();
1444b725ae77Skettenis   disable_breakpoints_in_shlibs (1);
1445b725ae77Skettenis   child_clear_solibs ();
1446b725ae77Skettenis   clear_proceed_status ();
1447b725ae77Skettenis   init_wait_for_inferior ();
1448b725ae77Skettenis 
1449b725ae77Skettenis   target_terminal_init ();
1450b725ae77Skettenis   target_terminal_inferior ();
1451b725ae77Skettenis 
1452b725ae77Skettenis   while (1)
1453b725ae77Skettenis     {
1454b725ae77Skettenis       stop_after_trap = 1;
1455b725ae77Skettenis       wait_for_inferior ();
1456b725ae77Skettenis       if (stop_signal != TARGET_SIGNAL_TRAP)
1457b725ae77Skettenis 	resume (0, stop_signal);
1458b725ae77Skettenis       else
1459e93f7393Sniklas 	break;
1460e93f7393Sniklas     }
1461b725ae77Skettenis   stop_after_trap = 0;
1462b725ae77Skettenis   return;
1463e93f7393Sniklas }
1464b725ae77Skettenis 
1465b725ae77Skettenis /* Since Windows XP, detaching from a process is supported by Windows.
1466b725ae77Skettenis    The following code tries loading the appropriate functions dynamically.
1467b725ae77Skettenis    If loading these functions succeeds use them to actually detach from
1468b725ae77Skettenis    the inferior process, otherwise behave as usual, pretending that
1469b725ae77Skettenis    detach has worked. */
1470b725ae77Skettenis static BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL);
1471b725ae77Skettenis static BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
1472b725ae77Skettenis 
1473b725ae77Skettenis static int
has_detach_ability(void)1474b725ae77Skettenis has_detach_ability (void)
1475b725ae77Skettenis {
1476b725ae77Skettenis   static HMODULE kernel32 = NULL;
1477b725ae77Skettenis 
1478b725ae77Skettenis   if (!kernel32)
1479b725ae77Skettenis     kernel32 = LoadLibrary ("kernel32.dll");
1480b725ae77Skettenis   if (kernel32)
1481b725ae77Skettenis     {
1482b725ae77Skettenis       if (!DebugSetProcessKillOnExit)
1483b725ae77Skettenis 	DebugSetProcessKillOnExit = GetProcAddress (kernel32,
1484b725ae77Skettenis 						 "DebugSetProcessKillOnExit");
1485b725ae77Skettenis       if (!DebugActiveProcessStop)
1486b725ae77Skettenis 	DebugActiveProcessStop = GetProcAddress (kernel32,
1487b725ae77Skettenis 						 "DebugActiveProcessStop");
1488b725ae77Skettenis       if (DebugSetProcessKillOnExit && DebugActiveProcessStop)
1489b725ae77Skettenis 	return 1;
1490b725ae77Skettenis     }
1491b725ae77Skettenis   return 0;
1492b725ae77Skettenis }
1493b725ae77Skettenis 
1494b725ae77Skettenis /* Try to set or remove a user privilege to the current process.  Return -1
1495b725ae77Skettenis    if that fails, the previous setting of that privilege otherwise.
1496b725ae77Skettenis 
1497b725ae77Skettenis    This code is copied from the Cygwin source code and rearranged to allow
1498b725ae77Skettenis    dynamically loading of the needed symbols from advapi32 which is only
1499b725ae77Skettenis    available on NT/2K/XP. */
1500b725ae77Skettenis static int
set_process_privilege(const char * privilege,BOOL enable)1501b725ae77Skettenis set_process_privilege (const char *privilege, BOOL enable)
1502b725ae77Skettenis {
1503b725ae77Skettenis   static HMODULE advapi32 = NULL;
1504b725ae77Skettenis   static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
1505b725ae77Skettenis   static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
1506b725ae77Skettenis   static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
1507b725ae77Skettenis 					      DWORD, PTOKEN_PRIVILEGES, PDWORD);
1508b725ae77Skettenis 
1509b725ae77Skettenis   HANDLE token_hdl = NULL;
1510b725ae77Skettenis   LUID restore_priv;
1511b725ae77Skettenis   TOKEN_PRIVILEGES new_priv, orig_priv;
1512b725ae77Skettenis   int ret = -1;
1513b725ae77Skettenis   DWORD size;
1514b725ae77Skettenis 
1515b725ae77Skettenis   if (GetVersion () >= 0x80000000)  /* No security availbale on 9x/Me */
1516b725ae77Skettenis     return 0;
1517b725ae77Skettenis 
1518b725ae77Skettenis   if (!advapi32)
1519b725ae77Skettenis     {
1520b725ae77Skettenis       if (!(advapi32 = LoadLibrary ("advapi32.dll")))
1521b725ae77Skettenis 	goto out;
1522b725ae77Skettenis       if (!OpenProcessToken)
1523b725ae77Skettenis 	OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken");
1524b725ae77Skettenis       if (!LookupPrivilegeValue)
1525b725ae77Skettenis 	LookupPrivilegeValue = GetProcAddress (advapi32,
1526b725ae77Skettenis 					       "LookupPrivilegeValueA");
1527b725ae77Skettenis       if (!AdjustTokenPrivileges)
1528b725ae77Skettenis 	AdjustTokenPrivileges = GetProcAddress (advapi32,
1529b725ae77Skettenis 						"AdjustTokenPrivileges");
1530b725ae77Skettenis       if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
1531b725ae77Skettenis 	{
1532b725ae77Skettenis 	  advapi32 = NULL;
1533b725ae77Skettenis 	  goto out;
1534b725ae77Skettenis 	}
1535b725ae77Skettenis     }
1536b725ae77Skettenis 
1537b725ae77Skettenis   if (!OpenProcessToken (GetCurrentProcess (),
1538b725ae77Skettenis 			 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
1539b725ae77Skettenis 			 &token_hdl))
1540b725ae77Skettenis     goto out;
1541b725ae77Skettenis 
1542b725ae77Skettenis   if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
1543b725ae77Skettenis     goto out;
1544b725ae77Skettenis 
1545b725ae77Skettenis   new_priv.PrivilegeCount = 1;
1546b725ae77Skettenis   new_priv.Privileges[0].Luid = restore_priv;
1547b725ae77Skettenis   new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
1548b725ae77Skettenis 
1549b725ae77Skettenis   if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv,
1550b725ae77Skettenis 			      sizeof orig_priv, &orig_priv, &size))
1551b725ae77Skettenis     goto out;
1552b725ae77Skettenis #if 0
1553b725ae77Skettenis   /* Disabled, otherwise every `attach' in an unprivileged user session
1554b725ae77Skettenis      would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
1555b725ae77Skettenis      child_attach(). */
1556b725ae77Skettenis   /* AdjustTokenPrivileges returns TRUE even if the privilege could not
1557b725ae77Skettenis      be enabled. GetLastError () returns an correct error code, though. */
1558b725ae77Skettenis   if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
1559b725ae77Skettenis     goto out;
1560b725ae77Skettenis #endif
1561b725ae77Skettenis 
1562b725ae77Skettenis   ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
1563b725ae77Skettenis 
1564b725ae77Skettenis out:
1565b725ae77Skettenis   if (token_hdl)
1566b725ae77Skettenis     CloseHandle (token_hdl);
1567b725ae77Skettenis 
1568b725ae77Skettenis   return ret;
1569e93f7393Sniklas }
1570e93f7393Sniklas 
1571e93f7393Sniklas /* Attach to process PID, then initialize for debugging it.  */
1572e93f7393Sniklas static void
child_attach(char * args,int from_tty)1573b725ae77Skettenis child_attach (char *args, int from_tty)
1574e93f7393Sniklas {
1575e93f7393Sniklas   BOOL ok;
1576b725ae77Skettenis   DWORD pid;
1577e93f7393Sniklas 
1578e93f7393Sniklas   if (!args)
1579e93f7393Sniklas     error_no_arg ("process-id to attach");
1580e93f7393Sniklas 
1581b725ae77Skettenis   if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
1582b725ae77Skettenis     {
1583b725ae77Skettenis       printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n");
1584b725ae77Skettenis       printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n");
1585b725ae77Skettenis     }
1586e93f7393Sniklas 
1587b725ae77Skettenis   pid = strtoul (args, 0, 0);		/* Windows pid */
1588b725ae77Skettenis 
1589b725ae77Skettenis   ok = DebugActiveProcess (pid);
1590b725ae77Skettenis   saw_create = 0;
1591b725ae77Skettenis 
1592b725ae77Skettenis   if (!ok)
1593b725ae77Skettenis     {
1594b725ae77Skettenis       /* Try fall back to Cygwin pid */
1595b725ae77Skettenis       pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
1596b725ae77Skettenis 
1597b725ae77Skettenis       if (pid > 0)
1598b725ae77Skettenis 	ok = DebugActiveProcess (pid);
1599e93f7393Sniklas 
1600e93f7393Sniklas       if (!ok)
1601e93f7393Sniklas 	error ("Can't attach to process.");
1602b725ae77Skettenis     }
1603e93f7393Sniklas 
1604b725ae77Skettenis   if (has_detach_ability ())
1605b725ae77Skettenis     DebugSetProcessKillOnExit (FALSE);
1606b725ae77Skettenis 
1607b725ae77Skettenis   attach_flag = 1;
1608e93f7393Sniklas 
1609e93f7393Sniklas   if (from_tty)
1610e93f7393Sniklas     {
1611e93f7393Sniklas       char *exec_file = (char *) get_exec_file (0);
1612e93f7393Sniklas 
1613e93f7393Sniklas       if (exec_file)
1614e93f7393Sniklas 	printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
1615b725ae77Skettenis 			   target_pid_to_str (pid_to_ptid (pid)));
1616e93f7393Sniklas       else
1617e93f7393Sniklas 	printf_unfiltered ("Attaching to %s\n",
1618b725ae77Skettenis 			   target_pid_to_str (pid_to_ptid (pid)));
1619e93f7393Sniklas 
1620e93f7393Sniklas       gdb_flush (gdb_stdout);
1621e93f7393Sniklas     }
1622e93f7393Sniklas 
1623b725ae77Skettenis   do_initial_child_stuff (pid);
1624b725ae77Skettenis   target_terminal_ours ();
1625e93f7393Sniklas }
1626e93f7393Sniklas 
1627e93f7393Sniklas static void
child_detach(char * args,int from_tty)1628b725ae77Skettenis child_detach (char *args, int from_tty)
1629e93f7393Sniklas {
1630b725ae77Skettenis   int detached = 1;
1631b725ae77Skettenis 
1632b725ae77Skettenis   if (has_detach_ability ())
1633b725ae77Skettenis     {
1634b725ae77Skettenis       delete_command (NULL, 0);
1635b725ae77Skettenis       child_continue (DBG_CONTINUE, -1);
1636b725ae77Skettenis       if (!DebugActiveProcessStop (current_event.dwProcessId))
1637b725ae77Skettenis 	{
1638b725ae77Skettenis 	  error ("Can't detach process %lu (error %lu)",
1639b725ae77Skettenis 		 current_event.dwProcessId, GetLastError ());
1640b725ae77Skettenis 	  detached = 0;
1641b725ae77Skettenis 	}
1642b725ae77Skettenis       DebugSetProcessKillOnExit (FALSE);
1643b725ae77Skettenis     }
1644b725ae77Skettenis   if (detached && from_tty)
1645e93f7393Sniklas     {
1646e93f7393Sniklas       char *exec_file = get_exec_file (0);
1647e93f7393Sniklas       if (exec_file == 0)
1648e93f7393Sniklas 	exec_file = "";
1649b725ae77Skettenis       printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file,
1650b725ae77Skettenis 			 current_event.dwProcessId);
1651e93f7393Sniklas       gdb_flush (gdb_stdout);
1652e93f7393Sniklas     }
1653b725ae77Skettenis   inferior_ptid = null_ptid;
1654*63addd46Skettenis   unpush_target (&deprecated_child_ops);
1655*63addd46Skettenis }
1656*63addd46Skettenis 
1657*63addd46Skettenis char *
child_pid_to_exec_file(int pid)1658*63addd46Skettenis child_pid_to_exec_file (int pid)
1659*63addd46Skettenis {
1660*63addd46Skettenis   /* Try to find the process path using the Cygwin internal process list
1661*63addd46Skettenis      pid isn't a valid pid, unfortunately.  Use current_event.dwProcessId
1662*63addd46Skettenis      instead.  */
1663*63addd46Skettenis   /* TODO: Also find native Windows processes using CW_GETPINFO_FULL.  */
1664*63addd46Skettenis 
1665*63addd46Skettenis   static char path[MAX_PATH + 1];
1666*63addd46Skettenis   char *path_ptr = NULL;
1667*63addd46Skettenis   int cpid;
1668*63addd46Skettenis   struct external_pinfo *pinfo;
1669*63addd46Skettenis 
1670*63addd46Skettenis   cygwin_internal (CW_LOCK_PINFO, 1000);
1671*63addd46Skettenis   for (cpid = 0;
1672*63addd46Skettenis        (pinfo = (struct external_pinfo *)
1673*63addd46Skettenis                        cygwin_internal (CW_GETPINFO, cpid | CW_NEXTPID));
1674*63addd46Skettenis        cpid = pinfo->pid)
1675*63addd46Skettenis     {
1676*63addd46Skettenis       if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */
1677*63addd46Skettenis        {
1678*63addd46Skettenis          cygwin_conv_to_full_posix_path (pinfo->progname, path);
1679*63addd46Skettenis          path_ptr = path;
1680*63addd46Skettenis          break;
1681*63addd46Skettenis        }
1682*63addd46Skettenis     }
1683*63addd46Skettenis   cygwin_internal (CW_UNLOCK_PINFO);
1684*63addd46Skettenis   return path_ptr;
1685e93f7393Sniklas }
1686e93f7393Sniklas 
1687e93f7393Sniklas /* Print status information about what we're accessing.  */
1688e93f7393Sniklas 
1689e93f7393Sniklas static void
child_files_info(struct target_ops * ignore)1690b725ae77Skettenis child_files_info (struct target_ops *ignore)
1691e93f7393Sniklas {
1692e93f7393Sniklas   printf_unfiltered ("\tUsing the running image of %s %s.\n",
1693b725ae77Skettenis       attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
1694e93f7393Sniklas }
1695e93f7393Sniklas 
1696e93f7393Sniklas static void
child_open(char * arg,int from_tty)1697b725ae77Skettenis child_open (char *arg, int from_tty)
1698e93f7393Sniklas {
1699e93f7393Sniklas   error ("Use the \"run\" command to start a Unix child process.");
1700e93f7393Sniklas }
1701e93f7393Sniklas 
1702b725ae77Skettenis /* Start an inferior win32 child process and sets inferior_ptid to its pid.
1703e93f7393Sniklas    EXEC_FILE is the file to run.
1704e93f7393Sniklas    ALLARGS is a string containing the arguments to the program.
1705e93f7393Sniklas    ENV is the environment vector to pass.  Errors reported with error().  */
1706e93f7393Sniklas 
1707e93f7393Sniklas static void
child_create_inferior(char * exec_file,char * allargs,char ** env,int from_tty)1708*63addd46Skettenis child_create_inferior (char *exec_file, char *allargs, char **env,
1709*63addd46Skettenis 		       int from_tty)
1710e93f7393Sniklas {
1711e93f7393Sniklas   char *winenv;
1712e93f7393Sniklas   char *temp;
1713e93f7393Sniklas   int envlen;
1714e93f7393Sniklas   int i;
1715e93f7393Sniklas   STARTUPINFO si;
1716e93f7393Sniklas   PROCESS_INFORMATION pi;
1717e93f7393Sniklas   BOOL ret;
1718e93f7393Sniklas   DWORD flags;
1719e93f7393Sniklas   char *args;
1720b725ae77Skettenis   char real_path[MAXPATHLEN];
1721b725ae77Skettenis   char *toexec;
1722b725ae77Skettenis   char shell[MAX_PATH + 1]; /* Path to shell */
1723b725ae77Skettenis   const char *sh;
1724b725ae77Skettenis   int tty;
1725b725ae77Skettenis   int ostdin, ostdout, ostderr;
1726e93f7393Sniklas 
1727e93f7393Sniklas   if (!exec_file)
1728e93f7393Sniklas     error ("No executable specified, use `target exec'.\n");
1729e93f7393Sniklas 
1730e93f7393Sniklas   memset (&si, 0, sizeof (si));
1731e93f7393Sniklas   si.cb = sizeof (si);
1732e93f7393Sniklas 
1733b725ae77Skettenis   if (!useshell)
1734b725ae77Skettenis     {
1735e93f7393Sniklas       flags = DEBUG_ONLY_THIS_PROCESS;
1736b725ae77Skettenis       cygwin_conv_to_win32_path (exec_file, real_path);
1737b725ae77Skettenis       toexec = real_path;
1738b725ae77Skettenis     }
1739b725ae77Skettenis   else
1740b725ae77Skettenis     {
1741b725ae77Skettenis       char *newallargs;
1742b725ae77Skettenis       sh = getenv ("SHELL");
1743b725ae77Skettenis       if (!sh)
1744b725ae77Skettenis 	sh = "/bin/sh";
1745b725ae77Skettenis       cygwin_conv_to_win32_path (sh, shell);
1746b725ae77Skettenis       newallargs = alloca (sizeof (" -c 'exec  '") + strlen (exec_file)
1747b725ae77Skettenis 			   + strlen (allargs) + 2);
1748b725ae77Skettenis       sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
1749b725ae77Skettenis       allargs = newallargs;
1750b725ae77Skettenis       toexec = shell;
1751b725ae77Skettenis       flags = DEBUG_PROCESS;
1752b725ae77Skettenis     }
1753e93f7393Sniklas 
1754e93f7393Sniklas   if (new_group)
1755e93f7393Sniklas     flags |= CREATE_NEW_PROCESS_GROUP;
1756e93f7393Sniklas 
1757e93f7393Sniklas   if (new_console)
1758e93f7393Sniklas     flags |= CREATE_NEW_CONSOLE;
1759e93f7393Sniklas 
1760b725ae77Skettenis   attach_flag = 0;
1761e93f7393Sniklas 
1762b725ae77Skettenis   args = alloca (strlen (toexec) + strlen (allargs) + 2);
1763b725ae77Skettenis   strcpy (args, toexec);
1764e93f7393Sniklas   strcat (args, " ");
1765e93f7393Sniklas   strcat (args, allargs);
1766e93f7393Sniklas 
1767e93f7393Sniklas   /* Prepare the environment vars for CreateProcess.  */
1768e93f7393Sniklas   {
1769b725ae77Skettenis     /* This code used to assume all env vars were file names and would
1770e93f7393Sniklas        translate them all to win32 style.  That obviously doesn't work in the
1771e93f7393Sniklas        general case.  The current rule is that we only translate PATH.
1772e93f7393Sniklas        We need to handle PATH because we're about to call CreateProcess and
1773e93f7393Sniklas        it uses PATH to find DLL's.  Fortunately PATH has a well-defined value
1774e93f7393Sniklas        in both posix and win32 environments.  cygwin.dll will change it back
1775e93f7393Sniklas        to posix style if necessary.  */
1776e93f7393Sniklas 
1777e93f7393Sniklas     static const char *conv_path_names[] =
1778e93f7393Sniklas     {
1779e93f7393Sniklas       "PATH=",
1780e93f7393Sniklas       0
1781e93f7393Sniklas     };
1782e93f7393Sniklas 
1783e93f7393Sniklas     /* CreateProcess takes the environment list as a null terminated set of
1784e93f7393Sniklas        strings (i.e. two nulls terminate the list).  */
1785e93f7393Sniklas 
1786e93f7393Sniklas     /* Get total size for env strings.  */
1787e93f7393Sniklas     for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1788e93f7393Sniklas       {
1789e93f7393Sniklas 	int j, len;
1790e93f7393Sniklas 
1791e93f7393Sniklas 	for (j = 0; conv_path_names[j]; j++)
1792e93f7393Sniklas 	  {
1793e93f7393Sniklas 	    len = strlen (conv_path_names[j]);
1794e93f7393Sniklas 	    if (strncmp (conv_path_names[j], env[i], len) == 0)
1795e93f7393Sniklas 	      {
1796b725ae77Skettenis 		if (cygwin_posix_path_list_p (env[i] + len))
1797e93f7393Sniklas 		  envlen += len
1798b725ae77Skettenis 		    + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
1799e93f7393Sniklas 		else
1800e93f7393Sniklas 		  envlen += strlen (env[i]) + 1;
1801e93f7393Sniklas 		break;
1802e93f7393Sniklas 	      }
1803e93f7393Sniklas 	  }
1804e93f7393Sniklas 	if (conv_path_names[j] == NULL)
1805e93f7393Sniklas 	  envlen += strlen (env[i]) + 1;
1806e93f7393Sniklas       }
1807e93f7393Sniklas 
1808e93f7393Sniklas     winenv = alloca (envlen + 1);
1809e93f7393Sniklas 
1810e93f7393Sniklas     /* Copy env strings into new buffer.  */
1811e93f7393Sniklas     for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1812e93f7393Sniklas       {
1813e93f7393Sniklas 	int j, len;
1814e93f7393Sniklas 
1815e93f7393Sniklas 	for (j = 0; conv_path_names[j]; j++)
1816e93f7393Sniklas 	  {
1817e93f7393Sniklas 	    len = strlen (conv_path_names[j]);
1818e93f7393Sniklas 	    if (strncmp (conv_path_names[j], env[i], len) == 0)
1819e93f7393Sniklas 	      {
1820b725ae77Skettenis 		if (cygwin_posix_path_list_p (env[i] + len))
1821e93f7393Sniklas 		  {
1822e93f7393Sniklas 		    memcpy (temp, env[i], len);
1823b725ae77Skettenis 		    cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
1824e93f7393Sniklas 		  }
1825e93f7393Sniklas 		else
1826e93f7393Sniklas 		  strcpy (temp, env[i]);
1827e93f7393Sniklas 		break;
1828e93f7393Sniklas 	      }
1829e93f7393Sniklas 	  }
1830e93f7393Sniklas 	if (conv_path_names[j] == NULL)
1831e93f7393Sniklas 	  strcpy (temp, env[i]);
1832e93f7393Sniklas 
1833e93f7393Sniklas 	temp += strlen (temp) + 1;
1834e93f7393Sniklas       }
1835e93f7393Sniklas 
1836e93f7393Sniklas     /* Final nil string to terminate new env.  */
1837e93f7393Sniklas     *temp = 0;
1838e93f7393Sniklas   }
1839e93f7393Sniklas 
1840b725ae77Skettenis   if (!inferior_io_terminal)
1841b725ae77Skettenis     tty = ostdin = ostdout = ostderr = -1;
1842b725ae77Skettenis   else
1843b725ae77Skettenis     {
1844b725ae77Skettenis       tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
1845b725ae77Skettenis       if (tty < 0)
1846b725ae77Skettenis 	{
1847b725ae77Skettenis 	  print_sys_errmsg (inferior_io_terminal, errno);
1848b725ae77Skettenis 	  ostdin = ostdout = ostderr = -1;
1849b725ae77Skettenis 	}
1850b725ae77Skettenis       else
1851b725ae77Skettenis 	{
1852b725ae77Skettenis 	  ostdin = dup (0);
1853b725ae77Skettenis 	  ostdout = dup (1);
1854b725ae77Skettenis 	  ostderr = dup (2);
1855b725ae77Skettenis 	  dup2 (tty, 0);
1856b725ae77Skettenis 	  dup2 (tty, 1);
1857b725ae77Skettenis 	  dup2 (tty, 2);
1858b725ae77Skettenis 	}
1859b725ae77Skettenis     }
1860b725ae77Skettenis 
1861e93f7393Sniklas   ret = CreateProcess (0,
1862e93f7393Sniklas 		       args,	/* command line */
1863e93f7393Sniklas 		       NULL,	/* Security */
1864e93f7393Sniklas 		       NULL,	/* thread */
1865e93f7393Sniklas 		       TRUE,	/* inherit handles */
1866e93f7393Sniklas 		       flags,	/* start flags */
1867e93f7393Sniklas 		       winenv,
1868e93f7393Sniklas 		       NULL,	/* current directory */
1869e93f7393Sniklas 		       &si,
1870e93f7393Sniklas 		       &pi);
1871b725ae77Skettenis   if (tty >= 0)
1872b725ae77Skettenis     {
1873b725ae77Skettenis       close (tty);
1874b725ae77Skettenis       dup2 (ostdin, 0);
1875b725ae77Skettenis       dup2 (ostdout, 1);
1876b725ae77Skettenis       dup2 (ostderr, 2);
1877b725ae77Skettenis       close (ostdin);
1878b725ae77Skettenis       close (ostdout);
1879b725ae77Skettenis       close (ostderr);
1880b725ae77Skettenis     }
1881b725ae77Skettenis 
1882e93f7393Sniklas   if (!ret)
1883b725ae77Skettenis     error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ());
1884e93f7393Sniklas 
1885b725ae77Skettenis   CloseHandle (pi.hThread);
1886b725ae77Skettenis   CloseHandle (pi.hProcess);
1887e93f7393Sniklas 
1888b725ae77Skettenis   if (useshell && shell[0] != '\0')
1889b725ae77Skettenis     saw_create = -1;
1890b725ae77Skettenis   else
1891b725ae77Skettenis     saw_create = 0;
1892e93f7393Sniklas 
1893b725ae77Skettenis   do_initial_child_stuff (pi.dwProcessId);
1894e93f7393Sniklas 
1895b725ae77Skettenis   /* child_continue (DBG_CONTINUE, -1); */
1896e93f7393Sniklas   proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
1897e93f7393Sniklas }
1898e93f7393Sniklas 
1899e93f7393Sniklas static void
child_mourn_inferior(void)1900b725ae77Skettenis child_mourn_inferior (void)
1901e93f7393Sniklas {
1902b725ae77Skettenis   (void) child_continue (DBG_CONTINUE, -1);
1903b725ae77Skettenis   i386_cleanup_dregs();
1904*63addd46Skettenis   unpush_target (&deprecated_child_ops);
1905e93f7393Sniklas   generic_mourn_inferior ();
1906e93f7393Sniklas }
1907e93f7393Sniklas 
1908e93f7393Sniklas /* Send a SIGINT to the process group.  This acts just like the user typed a
1909e93f7393Sniklas    ^C on the controlling terminal. */
1910e93f7393Sniklas 
1911e93f7393Sniklas static void
child_stop(void)1912b725ae77Skettenis child_stop (void)
1913e93f7393Sniklas {
1914e93f7393Sniklas   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
1915b725ae77Skettenis   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
1916e93f7393Sniklas   registers_changed ();		/* refresh register state */
1917e93f7393Sniklas }
1918e93f7393Sniklas 
1919e93f7393Sniklas int
child_xfer_memory(CORE_ADDR memaddr,char * our,int len,int write,struct mem_attrib * mem,struct target_ops * target)1920e93f7393Sniklas child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
1921b725ae77Skettenis 		   int write, struct mem_attrib *mem,
1922b725ae77Skettenis 		   struct target_ops *target)
1923e93f7393Sniklas {
1924b725ae77Skettenis   DWORD done = 0;
1925e93f7393Sniklas   if (write)
1926e93f7393Sniklas     {
1927b725ae77Skettenis       DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1928b725ae77Skettenis 		  len, (DWORD) memaddr));
1929b725ae77Skettenis       if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1930b725ae77Skettenis 			       len, &done))
1931b725ae77Skettenis 	done = 0;
1932b725ae77Skettenis       FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
1933e93f7393Sniklas     }
1934e93f7393Sniklas   else
1935e93f7393Sniklas     {
1936b725ae77Skettenis       DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1937b725ae77Skettenis 		  len, (DWORD) memaddr));
1938b725ae77Skettenis       if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our,
1939b725ae77Skettenis 			      len, &done))
1940b725ae77Skettenis 	done = 0;
1941e93f7393Sniklas     }
1942e93f7393Sniklas   return done;
1943e93f7393Sniklas }
1944e93f7393Sniklas 
1945e93f7393Sniklas void
child_kill_inferior(void)1946e93f7393Sniklas child_kill_inferior (void)
1947e93f7393Sniklas {
1948b725ae77Skettenis   CHECK (TerminateProcess (current_process_handle, 0));
1949b725ae77Skettenis 
1950b725ae77Skettenis   for (;;)
1951b725ae77Skettenis     {
1952b725ae77Skettenis       if (!child_continue (DBG_CONTINUE, -1))
1953b725ae77Skettenis 	break;
1954b725ae77Skettenis       if (!WaitForDebugEvent (&current_event, INFINITE))
1955b725ae77Skettenis 	break;
1956b725ae77Skettenis       if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1957b725ae77Skettenis 	break;
1958b725ae77Skettenis     }
1959b725ae77Skettenis 
1960b725ae77Skettenis   CHECK (CloseHandle (current_process_handle));
1961b725ae77Skettenis 
1962b725ae77Skettenis   /* this may fail in an attached process so don't check. */
1963b725ae77Skettenis   if (current_thread && current_thread->h)
1964b725ae77Skettenis     (void) CloseHandle (current_thread->h);
1965e93f7393Sniklas   target_mourn_inferior ();	/* or just child_mourn_inferior? */
1966e93f7393Sniklas }
1967e93f7393Sniklas 
1968e93f7393Sniklas void
child_resume(ptid_t ptid,int step,enum target_signal sig)1969b725ae77Skettenis child_resume (ptid_t ptid, int step, enum target_signal sig)
1970e93f7393Sniklas {
1971b725ae77Skettenis   thread_info *th;
1972b725ae77Skettenis   DWORD continue_status = DBG_CONTINUE;
1973e93f7393Sniklas 
1974b725ae77Skettenis   int pid = PIDGET (ptid);
1975b725ae77Skettenis 
1976b725ae77Skettenis   if (sig != TARGET_SIGNAL_0)
1977b725ae77Skettenis     {
1978b725ae77Skettenis       if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
1979b725ae77Skettenis 	{
1980b725ae77Skettenis 	  DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
1981b725ae77Skettenis 	}
1982b725ae77Skettenis       else if (sig == last_sig)
1983b725ae77Skettenis 	continue_status = DBG_EXCEPTION_NOT_HANDLED;
1984b725ae77Skettenis       else
1985b725ae77Skettenis #if 0
1986b725ae77Skettenis /* This code does not seem to work, because
1987b725ae77Skettenis   the kernel does probably not consider changes in the ExceptionRecord
1988b725ae77Skettenis   structure when passing the exception to the inferior.
1989b725ae77Skettenis   Note that this seems possible in the exception handler itself.  */
1990b725ae77Skettenis 	{
1991b725ae77Skettenis 	  int i;
1992b725ae77Skettenis 	  for (i = 0; xlate[i].them != -1; i++)
1993b725ae77Skettenis 	    if (xlate[i].us == sig)
1994b725ae77Skettenis 	      {
1995b725ae77Skettenis 		current_event.u.Exception.ExceptionRecord.ExceptionCode =
1996b725ae77Skettenis 		  xlate[i].them;
1997b725ae77Skettenis 		continue_status = DBG_EXCEPTION_NOT_HANDLED;
1998b725ae77Skettenis 		break;
1999b725ae77Skettenis 	      }
2000b725ae77Skettenis 	  if (continue_status == DBG_CONTINUE)
2001b725ae77Skettenis 	    {
2002b725ae77Skettenis 	      DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
2003b725ae77Skettenis 	    }
2004b725ae77Skettenis 	}
2005b725ae77Skettenis #endif
2006b725ae77Skettenis 	DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
2007b725ae77Skettenis 	  last_sig));
2008b725ae77Skettenis     }
2009b725ae77Skettenis 
2010b725ae77Skettenis   last_sig = TARGET_SIGNAL_0;
2011b725ae77Skettenis 
2012b725ae77Skettenis   DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
2013b725ae77Skettenis 	       pid, step, sig));
2014b725ae77Skettenis 
2015b725ae77Skettenis   /* Get context for currently selected thread */
2016b725ae77Skettenis   th = thread_rec (current_event.dwThreadId, FALSE);
2017b725ae77Skettenis   if (th)
2018b725ae77Skettenis     {
2019e93f7393Sniklas       if (step)
2020e93f7393Sniklas 	{
2021e93f7393Sniklas 	  /* Single step by setting t bit */
2022e93f7393Sniklas 	  child_fetch_inferior_registers (PS_REGNUM);
2023b725ae77Skettenis 	  th->context.EFlags |= FLAG_TRACE_BIT;
2024e93f7393Sniklas 	}
2025e93f7393Sniklas 
2026b725ae77Skettenis       if (th->context.ContextFlags)
2027e93f7393Sniklas 	{
2028b725ae77Skettenis 	  if (debug_registers_changed)
2029e93f7393Sniklas 	    {
2030b725ae77Skettenis 	      th->context.Dr0 = dr[0];
2031b725ae77Skettenis 	      th->context.Dr1 = dr[1];
2032b725ae77Skettenis 	      th->context.Dr2 = dr[2];
2033b725ae77Skettenis 	      th->context.Dr3 = dr[3];
2034b725ae77Skettenis 	      /* th->context.Dr6 = dr[6];
2035b725ae77Skettenis 	       FIXME: should we set dr6 also ?? */
2036b725ae77Skettenis 	      th->context.Dr7 = dr[7];
2037b725ae77Skettenis 	    }
2038b725ae77Skettenis 	  CHECK (SetThreadContext (th->h, &th->context));
2039b725ae77Skettenis 	  th->context.ContextFlags = 0;
2040b725ae77Skettenis 	}
2041e93f7393Sniklas     }
2042e93f7393Sniklas 
2043b725ae77Skettenis   /* Allow continuing with the same signal that interrupted us.
2044b725ae77Skettenis      Otherwise complain. */
2045b725ae77Skettenis 
2046b725ae77Skettenis   child_continue (continue_status, pid);
2047e93f7393Sniklas }
2048e93f7393Sniklas 
2049e93f7393Sniklas static void
child_prepare_to_store(void)2050b725ae77Skettenis child_prepare_to_store (void)
2051e93f7393Sniklas {
2052e93f7393Sniklas   /* Do nothing, since we can store individual regs */
2053e93f7393Sniklas }
2054e93f7393Sniklas 
2055e93f7393Sniklas static int
child_can_run(void)2056b725ae77Skettenis child_can_run (void)
2057e93f7393Sniklas {
2058e93f7393Sniklas   return 1;
2059e93f7393Sniklas }
2060e93f7393Sniklas 
2061e93f7393Sniklas static void
child_close(int x)2062b725ae77Skettenis child_close (int x)
2063e93f7393Sniklas {
2064b725ae77Skettenis   DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
2065b725ae77Skettenis 		PIDGET (inferior_ptid)));
2066e93f7393Sniklas }
2067e93f7393Sniklas 
2068b725ae77Skettenis static void
init_child_ops(void)2069b725ae77Skettenis init_child_ops (void)
2070e93f7393Sniklas {
2071*63addd46Skettenis   deprecated_child_ops.to_shortname = "child";
2072*63addd46Skettenis   deprecated_child_ops.to_longname = "Win32 child process";
2073*63addd46Skettenis   deprecated_child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
2074*63addd46Skettenis   deprecated_child_ops.to_open = child_open;
2075*63addd46Skettenis   deprecated_child_ops.to_close = child_close;
2076*63addd46Skettenis   deprecated_child_ops.to_attach = child_attach;
2077*63addd46Skettenis   deprecated_child_ops.to_detach = child_detach;
2078*63addd46Skettenis   deprecated_child_ops.to_resume = child_resume;
2079*63addd46Skettenis   deprecated_child_ops.to_wait = child_wait;
2080*63addd46Skettenis   deprecated_child_ops.to_fetch_registers = child_fetch_inferior_registers;
2081*63addd46Skettenis   deprecated_child_ops.to_store_registers = child_store_inferior_registers;
2082*63addd46Skettenis   deprecated_child_ops.to_prepare_to_store = child_prepare_to_store;
2083*63addd46Skettenis   deprecated_child_ops.deprecated_xfer_memory = child_xfer_memory;
2084*63addd46Skettenis   deprecated_child_ops.to_files_info = child_files_info;
2085*63addd46Skettenis   deprecated_child_ops.to_insert_breakpoint = memory_insert_breakpoint;
2086*63addd46Skettenis   deprecated_child_ops.to_remove_breakpoint = memory_remove_breakpoint;
2087*63addd46Skettenis   deprecated_child_ops.to_terminal_init = terminal_init_inferior;
2088*63addd46Skettenis   deprecated_child_ops.to_terminal_inferior = terminal_inferior;
2089*63addd46Skettenis   deprecated_child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
2090*63addd46Skettenis   deprecated_child_ops.to_terminal_ours = terminal_ours;
2091*63addd46Skettenis   deprecated_child_ops.to_terminal_save_ours = terminal_save_ours;
2092*63addd46Skettenis   deprecated_child_ops.to_terminal_info = child_terminal_info;
2093*63addd46Skettenis   deprecated_child_ops.to_kill = child_kill_inferior;
2094*63addd46Skettenis   deprecated_child_ops.to_create_inferior = child_create_inferior;
2095*63addd46Skettenis   deprecated_child_ops.to_mourn_inferior = child_mourn_inferior;
2096*63addd46Skettenis   deprecated_child_ops.to_can_run = child_can_run;
2097*63addd46Skettenis   deprecated_child_ops.to_thread_alive = win32_child_thread_alive;
2098*63addd46Skettenis   deprecated_child_ops.to_pid_to_str = cygwin_pid_to_str;
2099*63addd46Skettenis   deprecated_child_ops.to_stop = child_stop;
2100*63addd46Skettenis   deprecated_child_ops.to_stratum = process_stratum;
2101*63addd46Skettenis   deprecated_child_ops.to_has_all_memory = 1;
2102*63addd46Skettenis   deprecated_child_ops.to_has_memory = 1;
2103*63addd46Skettenis   deprecated_child_ops.to_has_stack = 1;
2104*63addd46Skettenis   deprecated_child_ops.to_has_registers = 1;
2105*63addd46Skettenis   deprecated_child_ops.to_has_execution = 1;
2106*63addd46Skettenis   deprecated_child_ops.to_magic = OPS_MAGIC;
2107*63addd46Skettenis   deprecated_child_ops.to_pid_to_exec_file = child_pid_to_exec_file;
2108b725ae77Skettenis }
2109e93f7393Sniklas 
2110e93f7393Sniklas void
_initialize_win32_nat(void)2111b725ae77Skettenis _initialize_win32_nat (void)
2112e93f7393Sniklas {
2113e93f7393Sniklas   struct cmd_list_element *c;
2114e93f7393Sniklas 
2115b725ae77Skettenis   init_child_ops ();
2116b725ae77Skettenis 
2117b725ae77Skettenis   c = add_com ("dll-symbols", class_files, dll_symbol_command,
2118b725ae77Skettenis 	       "Load dll library symbols from FILE.");
2119b725ae77Skettenis   set_cmd_completer (c, filename_completer);
2120b725ae77Skettenis 
2121b725ae77Skettenis   add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
2122b725ae77Skettenis 
2123*63addd46Skettenis   deprecated_add_show_from_set
2124*63addd46Skettenis     (add_set_cmd ("shell", class_support, var_boolean,
2125b725ae77Skettenis 		  (char *) &useshell,
2126b725ae77Skettenis 		  "Set use of shell to start subprocess.",
2127b725ae77Skettenis 		  &setlist),
2128b725ae77Skettenis      &showlist);
2129b725ae77Skettenis 
2130*63addd46Skettenis   deprecated_add_show_from_set
2131*63addd46Skettenis     (add_set_cmd ("new-console", class_support, var_boolean,
2132e93f7393Sniklas 		  (char *) &new_console,
2133e93f7393Sniklas 		  "Set creation of new console when creating child process.",
2134e93f7393Sniklas 		  &setlist),
2135e93f7393Sniklas      &showlist);
2136e93f7393Sniklas 
2137*63addd46Skettenis   deprecated_add_show_from_set
2138*63addd46Skettenis     (add_set_cmd ("new-group", class_support, var_boolean,
2139e93f7393Sniklas 		  (char *) &new_group,
2140e93f7393Sniklas 		  "Set creation of new group when creating child process.",
2141e93f7393Sniklas 		  &setlist),
2142e93f7393Sniklas      &showlist);
2143e93f7393Sniklas 
2144*63addd46Skettenis   deprecated_add_show_from_set
2145*63addd46Skettenis     (add_set_cmd ("debugexec", class_support, var_boolean,
2146e93f7393Sniklas 		  (char *) &debug_exec,
2147e93f7393Sniklas 		  "Set whether to display execution in child process.",
2148e93f7393Sniklas 		  &setlist),
2149e93f7393Sniklas      &showlist);
2150e93f7393Sniklas 
2151*63addd46Skettenis   deprecated_add_show_from_set
2152*63addd46Skettenis     (add_set_cmd ("debugevents", class_support, var_boolean,
2153e93f7393Sniklas 		  (char *) &debug_events,
2154e93f7393Sniklas 		  "Set whether to display kernel events in child process.",
2155e93f7393Sniklas 		  &setlist),
2156e93f7393Sniklas      &showlist);
2157e93f7393Sniklas 
2158*63addd46Skettenis   deprecated_add_show_from_set
2159*63addd46Skettenis     (add_set_cmd ("debugmemory", class_support, var_boolean,
2160e93f7393Sniklas 		  (char *) &debug_memory,
2161e93f7393Sniklas 		  "Set whether to display memory accesses in child process.",
2162e93f7393Sniklas 		  &setlist),
2163e93f7393Sniklas      &showlist);
2164e93f7393Sniklas 
2165*63addd46Skettenis   deprecated_add_show_from_set
2166*63addd46Skettenis     (add_set_cmd ("debugexceptions", class_support, var_boolean,
2167e93f7393Sniklas 		  (char *) &debug_exceptions,
2168e93f7393Sniklas 		  "Set whether to display kernel exceptions in child process.",
2169e93f7393Sniklas 		  &setlist),
2170e93f7393Sniklas      &showlist);
2171e93f7393Sniklas 
2172b725ae77Skettenis   add_info ("dll", info_dll_command, "Status of loaded DLLs.");
2173b725ae77Skettenis   add_info_alias ("sharedlibrary", "dll", 1);
2174b725ae77Skettenis 
2175b725ae77Skettenis   add_prefix_cmd ("w32", class_info, info_w32_command,
2176b725ae77Skettenis 		  "Print information specific to Win32 debugging.",
2177b725ae77Skettenis 		  &info_w32_cmdlist, "info w32 ", 0, &infolist);
2178b725ae77Skettenis 
2179b725ae77Skettenis   add_cmd ("selector", class_info, display_selectors,
2180b725ae77Skettenis 	   "Display selectors infos.",
2181b725ae77Skettenis 	   &info_w32_cmdlist);
2182b725ae77Skettenis 
2183*63addd46Skettenis   add_target (&deprecated_child_ops);
2184e93f7393Sniklas }
2185b725ae77Skettenis 
2186b725ae77Skettenis /* Hardware watchpoint support, adapted from go32-nat.c code.  */
2187b725ae77Skettenis 
2188b725ae77Skettenis /* Pass the address ADDR to the inferior in the I'th debug register.
2189b725ae77Skettenis    Here we just store the address in dr array, the registers will be
2190b725ae77Skettenis    actually set up when child_continue is called.  */
2191b725ae77Skettenis void
cygwin_set_dr(int i,CORE_ADDR addr)2192b725ae77Skettenis cygwin_set_dr (int i, CORE_ADDR addr)
2193b725ae77Skettenis {
2194b725ae77Skettenis   if (i < 0 || i > 3)
2195b725ae77Skettenis     internal_error (__FILE__, __LINE__,
2196b725ae77Skettenis 		    "Invalid register %d in cygwin_set_dr.\n", i);
2197b725ae77Skettenis   dr[i] = (unsigned) addr;
2198b725ae77Skettenis   debug_registers_changed = 1;
2199b725ae77Skettenis   debug_registers_used = 1;
2200b725ae77Skettenis }
2201b725ae77Skettenis 
2202b725ae77Skettenis /* Pass the value VAL to the inferior in the DR7 debug control
2203b725ae77Skettenis    register.  Here we just store the address in D_REGS, the watchpoint
2204b725ae77Skettenis    will be actually set up in child_wait.  */
2205b725ae77Skettenis void
cygwin_set_dr7(unsigned val)2206b725ae77Skettenis cygwin_set_dr7 (unsigned val)
2207b725ae77Skettenis {
2208b725ae77Skettenis   dr[7] = val;
2209b725ae77Skettenis   debug_registers_changed = 1;
2210b725ae77Skettenis   debug_registers_used = 1;
2211b725ae77Skettenis }
2212b725ae77Skettenis 
2213b725ae77Skettenis /* Get the value of the DR6 debug status register from the inferior.
2214b725ae77Skettenis    Here we just return the value stored in dr[6]
2215b725ae77Skettenis    by the last call to thread_rec for current_event.dwThreadId id.  */
2216b725ae77Skettenis unsigned
cygwin_get_dr6(void)2217b725ae77Skettenis cygwin_get_dr6 (void)
2218b725ae77Skettenis {
2219b725ae77Skettenis   return dr[6];
2220b725ae77Skettenis }
2221b725ae77Skettenis 
2222b725ae77Skettenis /* Determine if the thread referenced by "pid" is alive
2223b725ae77Skettenis    by "polling" it.  If WaitForSingleObject returns WAIT_OBJECT_0
2224b725ae77Skettenis    it means that the pid has died.  Otherwise it is assumed to be alive. */
2225b725ae77Skettenis static int
win32_child_thread_alive(ptid_t ptid)2226b725ae77Skettenis win32_child_thread_alive (ptid_t ptid)
2227b725ae77Skettenis {
2228b725ae77Skettenis   int pid = PIDGET (ptid);
2229b725ae77Skettenis 
2230b725ae77Skettenis   return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
2231b725ae77Skettenis     FALSE : TRUE;
2232b725ae77Skettenis }
2233b725ae77Skettenis 
2234b725ae77Skettenis /* Convert pid to printable format. */
2235b725ae77Skettenis char *
cygwin_pid_to_str(ptid_t ptid)2236b725ae77Skettenis cygwin_pid_to_str (ptid_t ptid)
2237b725ae77Skettenis {
2238b725ae77Skettenis   static char buf[80];
2239b725ae77Skettenis   int pid = PIDGET (ptid);
2240b725ae77Skettenis 
2241b725ae77Skettenis   if ((DWORD) pid == current_event.dwProcessId)
2242b725ae77Skettenis     sprintf (buf, "process %d", pid);
2243b725ae77Skettenis   else
2244b725ae77Skettenis     sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
2245b725ae77Skettenis   return buf;
2246b725ae77Skettenis }
2247b725ae77Skettenis 
2248b725ae77Skettenis static int
core_dll_symbols_add(char * dll_name,DWORD base_addr)2249b725ae77Skettenis core_dll_symbols_add (char *dll_name, DWORD base_addr)
2250b725ae77Skettenis {
2251b725ae77Skettenis   struct objfile *objfile;
2252b725ae77Skettenis   char *objfile_basename;
2253b725ae77Skettenis   const char *dll_basename;
2254b725ae77Skettenis 
2255b725ae77Skettenis   if (!(dll_basename = strrchr (dll_name, '/')))
2256b725ae77Skettenis     dll_basename = dll_name;
2257b725ae77Skettenis   else
2258b725ae77Skettenis     dll_basename++;
2259b725ae77Skettenis 
2260b725ae77Skettenis   ALL_OBJFILES (objfile)
2261b725ae77Skettenis   {
2262b725ae77Skettenis     objfile_basename = strrchr (objfile->name, '/');
2263b725ae77Skettenis 
2264b725ae77Skettenis     if (objfile_basename &&
2265b725ae77Skettenis 	strcmp (dll_basename, objfile_basename + 1) == 0)
2266b725ae77Skettenis       {
2267b725ae77Skettenis 	printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
2268b725ae77Skettenis 			   base_addr, dll_name);
2269b725ae77Skettenis 	goto out;
2270b725ae77Skettenis       }
2271b725ae77Skettenis   }
2272b725ae77Skettenis 
2273b725ae77Skettenis   register_loaded_dll (dll_name, base_addr + 0x1000);
2274b725ae77Skettenis   solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
2275b725ae77Skettenis 
2276b725ae77Skettenis  out:
2277b725ae77Skettenis   return 1;
2278b725ae77Skettenis }
2279b725ae77Skettenis 
2280b725ae77Skettenis typedef struct
2281b725ae77Skettenis {
2282b725ae77Skettenis   struct target_ops *target;
2283b725ae77Skettenis   bfd_vma addr;
2284b725ae77Skettenis } map_code_section_args;
2285b725ae77Skettenis 
2286b725ae77Skettenis static void
map_single_dll_code_section(bfd * abfd,asection * sect,void * obj)2287b725ae77Skettenis map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
2288b725ae77Skettenis {
2289b725ae77Skettenis   int old;
2290b725ae77Skettenis   int update_coreops;
2291b725ae77Skettenis   struct section_table *new_target_sect_ptr;
2292b725ae77Skettenis 
2293b725ae77Skettenis   map_code_section_args *args = (map_code_section_args *) obj;
2294b725ae77Skettenis   struct target_ops *target = args->target;
2295b725ae77Skettenis   if (sect->flags & SEC_CODE)
2296b725ae77Skettenis     {
2297b725ae77Skettenis       update_coreops = core_ops.to_sections == target->to_sections;
2298b725ae77Skettenis 
2299b725ae77Skettenis       if (target->to_sections)
2300b725ae77Skettenis 	{
2301b725ae77Skettenis 	  old = target->to_sections_end - target->to_sections;
2302b725ae77Skettenis 	  target->to_sections = (struct section_table *)
2303b725ae77Skettenis 	    xrealloc ((char *) target->to_sections,
2304b725ae77Skettenis 		      (sizeof (struct section_table)) * (1 + old));
2305b725ae77Skettenis 	}
2306b725ae77Skettenis       else
2307b725ae77Skettenis 	{
2308b725ae77Skettenis 	  old = 0;
2309b725ae77Skettenis 	  target->to_sections = (struct section_table *)
2310b725ae77Skettenis 	    xmalloc ((sizeof (struct section_table)));
2311b725ae77Skettenis 	}
2312b725ae77Skettenis       target->to_sections_end = target->to_sections + (1 + old);
2313b725ae77Skettenis 
2314b725ae77Skettenis       /* Update the to_sections field in the core_ops structure
2315b725ae77Skettenis 	 if needed.  */
2316b725ae77Skettenis       if (update_coreops)
2317b725ae77Skettenis 	{
2318b725ae77Skettenis 	  core_ops.to_sections = target->to_sections;
2319b725ae77Skettenis 	  core_ops.to_sections_end = target->to_sections_end;
2320b725ae77Skettenis 	}
2321b725ae77Skettenis       new_target_sect_ptr = target->to_sections + old;
2322b725ae77Skettenis       new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
2323b725ae77Skettenis       new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
2324b725ae77Skettenis 	bfd_section_size (abfd, sect);;
2325b725ae77Skettenis       new_target_sect_ptr->the_bfd_section = sect;
2326b725ae77Skettenis       new_target_sect_ptr->bfd = abfd;
2327b725ae77Skettenis     }
2328b725ae77Skettenis }
2329b725ae77Skettenis 
2330b725ae77Skettenis static int
dll_code_sections_add(const char * dll_name,int base_addr,struct target_ops * target)2331b725ae77Skettenis dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
2332b725ae77Skettenis {
2333b725ae77Skettenis   bfd *dll_bfd;
2334b725ae77Skettenis   map_code_section_args map_args;
2335b725ae77Skettenis   asection *lowest_sect;
2336b725ae77Skettenis   char *name;
2337b725ae77Skettenis   if (dll_name == NULL || target == NULL)
2338b725ae77Skettenis     return 0;
2339b725ae77Skettenis   name = xstrdup (dll_name);
2340b725ae77Skettenis   dll_bfd = bfd_openr (name, "pei-i386");
2341b725ae77Skettenis   if (dll_bfd == NULL)
2342b725ae77Skettenis     return 0;
2343b725ae77Skettenis 
2344b725ae77Skettenis   if (bfd_check_format (dll_bfd, bfd_object))
2345b725ae77Skettenis     {
2346b725ae77Skettenis       lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
2347b725ae77Skettenis       if (lowest_sect == NULL)
2348b725ae77Skettenis 	return 0;
2349b725ae77Skettenis       map_args.target = target;
2350b725ae77Skettenis       map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
2351b725ae77Skettenis 
2352b725ae77Skettenis       bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
2353b725ae77Skettenis     }
2354b725ae77Skettenis 
2355b725ae77Skettenis   return 1;
2356b725ae77Skettenis }
2357b725ae77Skettenis 
2358b725ae77Skettenis static void
core_section_load_dll_symbols(bfd * abfd,asection * sect,void * obj)2359b725ae77Skettenis core_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
2360b725ae77Skettenis {
2361b725ae77Skettenis   struct target_ops *target = (struct target_ops *) obj;
2362b725ae77Skettenis 
2363b725ae77Skettenis   DWORD base_addr;
2364b725ae77Skettenis 
2365b725ae77Skettenis   int dll_name_size;
2366b725ae77Skettenis   char *dll_name = NULL;
2367b725ae77Skettenis   char *buf = NULL;
2368b725ae77Skettenis   struct win32_pstatus *pstatus;
2369b725ae77Skettenis   char *p;
2370b725ae77Skettenis 
2371b725ae77Skettenis   if (strncmp (sect->name, ".module", 7))
2372b725ae77Skettenis     return;
2373b725ae77Skettenis 
2374*63addd46Skettenis   buf = (char *) xmalloc (bfd_get_section_size (sect) + 1);
2375b725ae77Skettenis   if (!buf)
2376b725ae77Skettenis     {
2377b725ae77Skettenis       printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2378b725ae77Skettenis       goto out;
2379b725ae77Skettenis     }
2380*63addd46Skettenis   if (!bfd_get_section_contents (abfd, sect, buf, 0, bfd_get_section_size (sect)))
2381b725ae77Skettenis     goto out;
2382b725ae77Skettenis 
2383b725ae77Skettenis   pstatus = (struct win32_pstatus *) buf;
2384b725ae77Skettenis 
2385b725ae77Skettenis   memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
2386b725ae77Skettenis   dll_name_size = pstatus->data.module_info.module_name_size;
2387*63addd46Skettenis   if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > bfd_get_section_size (sect))
2388b725ae77Skettenis       goto out;
2389b725ae77Skettenis 
2390b725ae77Skettenis   dll_name = (char *) xmalloc (dll_name_size + 1);
2391b725ae77Skettenis   if (!dll_name)
2392b725ae77Skettenis     {
2393b725ae77Skettenis       printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2394b725ae77Skettenis       goto out;
2395b725ae77Skettenis     }
2396b725ae77Skettenis   strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
2397b725ae77Skettenis 
2398b725ae77Skettenis   while ((p = strchr (dll_name, '\\')))
2399b725ae77Skettenis     *p = '/';
2400b725ae77Skettenis 
2401b725ae77Skettenis   if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
2402b725ae77Skettenis     printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
2403b725ae77Skettenis 
2404b725ae77Skettenis   if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
2405b725ae77Skettenis     printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
2406b725ae77Skettenis 
2407b725ae77Skettenis out:
2408b725ae77Skettenis   if (buf)
2409b725ae77Skettenis     xfree (buf);
2410b725ae77Skettenis   if (dll_name)
2411b725ae77Skettenis     xfree (dll_name);
2412b725ae77Skettenis   return;
2413b725ae77Skettenis }
2414b725ae77Skettenis 
2415b725ae77Skettenis void
child_solib_add(char * filename,int from_tty,struct target_ops * target,int readsyms)2416b725ae77Skettenis child_solib_add (char *filename, int from_tty, struct target_ops *target,
2417b725ae77Skettenis 		 int readsyms)
2418b725ae77Skettenis {
2419b725ae77Skettenis   if (!readsyms)
2420b725ae77Skettenis     return;
2421b725ae77Skettenis   if (core_bfd)
2422b725ae77Skettenis     {
2423b725ae77Skettenis       child_clear_solibs ();
2424b725ae77Skettenis       bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
2425b725ae77Skettenis     }
2426b725ae77Skettenis   else
2427b725ae77Skettenis     {
2428b725ae77Skettenis       if (solib_end && solib_end->name)
2429b725ae77Skettenis 	     solib_end->objfile = solib_symbols_add (solib_end->name, from_tty,
2430b725ae77Skettenis 						solib_end->load_addr);
2431b725ae77Skettenis     }
2432b725ae77Skettenis }
2433b725ae77Skettenis 
2434b725ae77Skettenis static void
fetch_elf_core_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR reg_addr)2435b725ae77Skettenis fetch_elf_core_registers (char *core_reg_sect,
2436b725ae77Skettenis 			  unsigned core_reg_size,
2437b725ae77Skettenis 			  int which,
2438b725ae77Skettenis 			  CORE_ADDR reg_addr)
2439b725ae77Skettenis {
2440b725ae77Skettenis   int r;
2441b725ae77Skettenis   if (core_reg_size < sizeof (CONTEXT))
2442b725ae77Skettenis     {
2443b725ae77Skettenis       error ("Core file register section too small (%u bytes).", core_reg_size);
2444b725ae77Skettenis       return;
2445b725ae77Skettenis     }
2446b725ae77Skettenis   for (r = 0; r < NUM_REGS; r++)
2447*63addd46Skettenis     regcache_raw_supply (current_regcache, r, core_reg_sect + mappings[r]);
2448b725ae77Skettenis }
2449b725ae77Skettenis 
2450b725ae77Skettenis static struct core_fns win32_elf_core_fns =
2451b725ae77Skettenis {
2452b725ae77Skettenis   bfd_target_elf_flavour,
2453b725ae77Skettenis   default_check_format,
2454b725ae77Skettenis   default_core_sniffer,
2455b725ae77Skettenis   fetch_elf_core_registers,
2456b725ae77Skettenis   NULL
2457b725ae77Skettenis };
2458b725ae77Skettenis 
2459b725ae77Skettenis void
_initialize_core_win32(void)2460b725ae77Skettenis _initialize_core_win32 (void)
2461b725ae77Skettenis {
2462*63addd46Skettenis   deprecated_add_core_fns (&win32_elf_core_fns);
2463b725ae77Skettenis }
2464b725ae77Skettenis 
2465b725ae77Skettenis void
_initialize_check_for_gdb_ini(void)2466b725ae77Skettenis _initialize_check_for_gdb_ini (void)
2467b725ae77Skettenis {
2468b725ae77Skettenis   char *homedir;
2469b725ae77Skettenis   if (inhibit_gdbinit)
2470b725ae77Skettenis     return;
2471b725ae77Skettenis 
2472b725ae77Skettenis   homedir = getenv ("HOME");
2473b725ae77Skettenis   if (homedir)
2474b725ae77Skettenis     {
2475b725ae77Skettenis       char *p;
2476b725ae77Skettenis       char *oldini = (char *) alloca (strlen (homedir) +
2477b725ae77Skettenis 				      sizeof ("/gdb.ini"));
2478b725ae77Skettenis       strcpy (oldini, homedir);
2479b725ae77Skettenis       p = strchr (oldini, '\0');
2480b725ae77Skettenis       if (p > oldini && p[-1] != '/')
2481b725ae77Skettenis 	*p++ = '/';
2482b725ae77Skettenis       strcpy (p, "gdb.ini");
2483b725ae77Skettenis       if (access (oldini, 0) == 0)
2484b725ae77Skettenis 	{
2485b725ae77Skettenis 	  int len = strlen (oldini);
2486b725ae77Skettenis 	  char *newini = alloca (len + 1);
2487b725ae77Skettenis 	  sprintf (newini, "%.*s.gdbinit",
2488b725ae77Skettenis 	    (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
2489b725ae77Skettenis 	  warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini);
2490b725ae77Skettenis 	}
2491b725ae77Skettenis     }
2492b725ae77Skettenis }
2493