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