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