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