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