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