*** empty log message ***
[deliverable/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
1626/* ARGSUSED */
1627static void
0a65a603 1628child_open (char *arg, int from_tty)
c906108c
SS
1629{
1630 error ("Use the \"run\" command to start a Unix child process.");
1631}
1632
39f77062 1633/* Start an inferior win32 child process and sets inferior_ptid to its pid.
c906108c
SS
1634 EXEC_FILE is the file to run.
1635 ALLARGS is a string containing the arguments to the program.
1636 ENV is the environment vector to pass. Errors reported with error(). */
1637
1638static void
fba45db2 1639child_create_inferior (char *exec_file, char *allargs, char **env)
c906108c 1640{
c906108c
SS
1641 char *winenv;
1642 char *temp;
c5aa993b 1643 int envlen;
c906108c 1644 int i;
c906108c
SS
1645 STARTUPINFO si;
1646 PROCESS_INFORMATION pi;
c906108c
SS
1647 BOOL ret;
1648 DWORD flags;
1649 char *args;
dfe7f3ac
CF
1650 char real_path[MAXPATHLEN];
1651 char *toexec;
349b409f
CF
1652 char shell[MAX_PATH + 1]; /* Path to shell */
1653 const char *sh;
2becadee
CF
1654 int tty;
1655 int ostdin, ostdout, ostderr;
c906108c
SS
1656
1657 if (!exec_file)
450005e7 1658 error ("No executable specified, use `target exec'.\n");
c906108c
SS
1659
1660 memset (&si, 0, sizeof (si));
1661 si.cb = sizeof (si);
1662
349b409f 1663 if (!useshell)
dfe7f3ac
CF
1664 {
1665 flags = DEBUG_ONLY_THIS_PROCESS;
1666 cygwin_conv_to_win32_path (exec_file, real_path);
1667 toexec = real_path;
1668 }
1669 else
1670 {
349b409f
CF
1671 char *newallargs;
1672 sh = getenv ("SHELL");
1673 if (!sh)
1674 sh = "/bin/sh";
1675 cygwin_conv_to_win32_path (sh, shell);
1676 newallargs = alloca (sizeof (" -c 'exec '") + strlen (exec_file)
1677 + strlen (allargs) + 2);
dfe7f3ac
CF
1678 sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
1679 allargs = newallargs;
1680 toexec = shell;
1681 flags = DEBUG_PROCESS;
1682 }
c906108c 1683
eeb25b8a
PM
1684 if (new_group)
1685 flags |= CREATE_NEW_PROCESS_GROUP;
1686
1687 if (new_console)
1688 flags |= CREATE_NEW_CONSOLE;
1689
dfe7f3ac
CF
1690 args = alloca (strlen (toexec) + strlen (allargs) + 2);
1691 strcpy (args, toexec);
c906108c
SS
1692 strcat (args, " ");
1693 strcat (args, allargs);
1694
1695 /* Prepare the environment vars for CreateProcess. */
1696 {
349b409f 1697 /* This code used to assume all env vars were file names and would
c906108c
SS
1698 translate them all to win32 style. That obviously doesn't work in the
1699 general case. The current rule is that we only translate PATH.
1700 We need to handle PATH because we're about to call CreateProcess and
1701 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
1702 in both posix and win32 environments. cygwin.dll will change it back
1703 to posix style if necessary. */
1704
1705 static const char *conv_path_names[] =
c5aa993b
JM
1706 {
1707 "PATH=",
1708 0
1709 };
c906108c
SS
1710
1711 /* CreateProcess takes the environment list as a null terminated set of
1712 strings (i.e. two nulls terminate the list). */
1713
1714 /* Get total size for env strings. */
1715 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1716 {
1717 int j, len;
1718
1719 for (j = 0; conv_path_names[j]; j++)
1720 {
1721 len = strlen (conv_path_names[j]);
1722 if (strncmp (conv_path_names[j], env[i], len) == 0)
1723 {
29fe111d 1724 if (cygwin_posix_path_list_p (env[i] + len))
c906108c 1725 envlen += len
29fe111d 1726 + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
c906108c
SS
1727 else
1728 envlen += strlen (env[i]) + 1;
1729 break;
1730 }
1731 }
1732 if (conv_path_names[j] == NULL)
1733 envlen += strlen (env[i]) + 1;
1734 }
1735
1736 winenv = alloca (envlen + 1);
1737
1738 /* Copy env strings into new buffer. */
1739 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1740 {
1741 int j, len;
1742
1743 for (j = 0; conv_path_names[j]; j++)
1744 {
1745 len = strlen (conv_path_names[j]);
1746 if (strncmp (conv_path_names[j], env[i], len) == 0)
1747 {
29fe111d 1748 if (cygwin_posix_path_list_p (env[i] + len))
c906108c
SS
1749 {
1750 memcpy (temp, env[i], len);
29fe111d 1751 cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
c906108c
SS
1752 }
1753 else
1754 strcpy (temp, env[i]);
1755 break;
1756 }
1757 }
1758 if (conv_path_names[j] == NULL)
1759 strcpy (temp, env[i]);
1760
1761 temp += strlen (temp) + 1;
1762 }
1763
1764 /* Final nil string to terminate new env. */
1765 *temp = 0;
1766 }
1767
2becadee
CF
1768 if (!inferior_io_terminal)
1769 tty = ostdin = ostdout = ostderr = -1;
1770 else
1771 {
1772 tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
1773 if (tty < 0)
1774 {
1775 print_sys_errmsg (inferior_io_terminal, errno);
1776 ostdin = ostdout = ostderr = -1;
1777 }
1778 else
1779 {
1780 ostdin = dup (0);
1781 ostdout = dup (1);
1782 ostderr = dup (2);
1783 dup2 (tty, 0);
1784 dup2 (tty, 1);
1785 dup2 (tty, 2);
1786 }
1787 }
1788
c906108c 1789 ret = CreateProcess (0,
c5aa993b 1790 args, /* command line */
c906108c
SS
1791 NULL, /* Security */
1792 NULL, /* thread */
1793 TRUE, /* inherit handles */
1794 flags, /* start flags */
1795 winenv,
1796 NULL, /* current directory */
1797 &si,
1798 &pi);
2becadee
CF
1799 if (tty >= 0)
1800 {
1801 close (tty);
1802 dup2 (ostdin, 0);
1803 dup2 (ostdout, 1);
1804 dup2 (ostderr, 2);
1805 close (ostdin);
1806 close (ostdout);
1807 close (ostderr);
1808 }
1809
c906108c 1810 if (!ret)
5633f842 1811 error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ());
c906108c 1812
700b351b
CF
1813 CloseHandle (pi.hThread);
1814 CloseHandle (pi.hProcess);
dfe7f3ac
CF
1815
1816 if (useshell && shell[0] != '\0')
1817 saw_create = -1;
1818 else
1819 saw_create = 0;
1820
9d3789f7 1821 do_initial_child_stuff (pi.dwProcessId);
ed9a39eb 1822
8e860359 1823 /* child_continue (DBG_CONTINUE, -1); */
c2d11a7d 1824 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
c906108c
SS
1825}
1826
1827static void
fba45db2 1828child_mourn_inferior (void)
c906108c 1829{
8a892701 1830 (void) child_continue (DBG_CONTINUE, -1);
fa4ba8da 1831 i386_cleanup_dregs();
c906108c
SS
1832 unpush_target (&child_ops);
1833 generic_mourn_inferior ();
1834}
1835
1836/* Send a SIGINT to the process group. This acts just like the user typed a
1837 ^C on the controlling terminal. */
1838
1839static void
fba45db2 1840child_stop (void)
c906108c
SS
1841{
1842 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
c2d11a7d 1843 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
c5aa993b 1844 registers_changed (); /* refresh register state */
c906108c
SS
1845}
1846
1847int
1848child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
0a65a603
AC
1849 int write, struct mem_attrib *mem,
1850 struct target_ops *target)
c906108c 1851{
6f17862b 1852 DWORD done = 0;
c906108c
SS
1853 if (write)
1854 {
29fe111d
CF
1855 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1856 len, (DWORD) memaddr));
6f17862b
CF
1857 if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1858 len, &done))
1859 done = 0;
c906108c
SS
1860 FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
1861 }
1862 else
1863 {
29fe111d
CF
1864 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1865 len, (DWORD) memaddr));
6f17862b
CF
1866 if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our,
1867 len, &done))
1868 done = 0;
c906108c
SS
1869 }
1870 return done;
1871}
1872
1873void
1874child_kill_inferior (void)
1875{
1876 CHECK (TerminateProcess (current_process_handle, 0));
1877
1878 for (;;)
1879 {
8a892701 1880 if (!child_continue (DBG_CONTINUE, -1))
c906108c
SS
1881 break;
1882 if (!WaitForDebugEvent (&current_event, INFINITE))
1883 break;
1884 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1885 break;
1886 }
1887
1888 CHECK (CloseHandle (current_process_handle));
1889
1890 /* this may fail in an attached process so don't check. */
1891 (void) CloseHandle (current_thread->h);
c5aa993b 1892 target_mourn_inferior (); /* or just child_mourn_inferior? */
c906108c
SS
1893}
1894
1895void
39f77062 1896child_resume (ptid_t ptid, int step, enum target_signal sig)
c906108c 1897{
c906108c 1898 thread_info *th;
7393af7c
PM
1899 DWORD continue_status = DBG_CONTINUE;
1900
39f77062 1901 int pid = PIDGET (ptid);
8a892701 1902
7393af7c
PM
1903 if (sig != TARGET_SIGNAL_0)
1904 {
1905 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
1906 {
1907 DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
1908 }
1909 else if (sig == last_sig)
1910 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1911 else
1912#if 0
1913/* This code does not seem to work, because
1914 the kernel does probably not consider changes in the ExceptionRecord
dfe7f3ac 1915 structure when passing the exception to the inferior.
7393af7c
PM
1916 Note that this seems possible in the exception handler itself. */
1917 {
1918 int i;
1919 for (i = 0; xlate[i].them != -1; i++)
1920 if (xlate[i].us == sig)
1921 {
1922 current_event.u.Exception.ExceptionRecord.ExceptionCode =
1923 xlate[i].them;
1924 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1925 break;
1926 }
1927 if (continue_status == DBG_CONTINUE)
1928 {
1929 DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
1930 }
1931 }
1932#endif
dfe7f3ac 1933 DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
7393af7c
PM
1934 last_sig));
1935 }
1936
1937 last_sig = TARGET_SIGNAL_0;
c906108c
SS
1938
1939 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1940 pid, step, sig));
1941
1942 /* Get context for currently selected thread */
1943 th = thread_rec (current_event.dwThreadId, FALSE);
450005e7 1944 if (th)
c906108c 1945 {
450005e7
CF
1946 if (step)
1947 {
1948 /* Single step by setting t bit */
1949 child_fetch_inferior_registers (PS_REGNUM);
1950 th->context.EFlags |= FLAG_TRACE_BIT;
1951 }
c906108c 1952
450005e7
CF
1953 if (th->context.ContextFlags)
1954 {
caad7706
CF
1955 if (debug_registers_changed)
1956 {
1957 th->context.Dr0 = dr[0];
1958 th->context.Dr1 = dr[1];
1959 th->context.Dr2 = dr[2];
1960 th->context.Dr3 = dr[3];
1961 /* th->context.Dr6 = dr[6];
1962 FIXME: should we set dr6 also ?? */
1963 th->context.Dr7 = dr[7];
1964 }
450005e7
CF
1965 CHECK (SetThreadContext (th->h, &th->context));
1966 th->context.ContextFlags = 0;
1967 }
c906108c
SS
1968 }
1969
1970 /* Allow continuing with the same signal that interrupted us.
1971 Otherwise complain. */
c906108c 1972
8a892701 1973 child_continue (continue_status, pid);
c906108c
SS
1974}
1975
1976static void
fba45db2 1977child_prepare_to_store (void)
c906108c
SS
1978{
1979 /* Do nothing, since we can store individual regs */
1980}
1981
1982static int
fba45db2 1983child_can_run (void)
c906108c
SS
1984{
1985 return 1;
1986}
1987
1988static void
0a65a603 1989child_close (int x)
c906108c 1990{
39f77062 1991 DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
3bccec63 1992 PIDGET (inferior_ptid)));
c906108c
SS
1993}
1994
c5aa993b 1995struct target_ops child_ops;
c906108c 1996
c5aa993b
JM
1997static void
1998init_child_ops (void)
c906108c 1999{
c5aa993b
JM
2000 child_ops.to_shortname = "child";
2001 child_ops.to_longname = "Win32 child process";
2002 child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
2003 child_ops.to_open = child_open;
2004 child_ops.to_close = child_close;
2005 child_ops.to_attach = child_attach;
2006 child_ops.to_detach = child_detach;
2007 child_ops.to_resume = child_resume;
2008 child_ops.to_wait = child_wait;
2009 child_ops.to_fetch_registers = child_fetch_inferior_registers;
2010 child_ops.to_store_registers = child_store_inferior_registers;
2011 child_ops.to_prepare_to_store = child_prepare_to_store;
2012 child_ops.to_xfer_memory = child_xfer_memory;
2013 child_ops.to_files_info = child_files_info;
2014 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
2015 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
2016 child_ops.to_terminal_init = terminal_init_inferior;
2017 child_ops.to_terminal_inferior = terminal_inferior;
2018 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
2019 child_ops.to_terminal_ours = terminal_ours;
a790ad35 2020 child_ops.to_terminal_save_ours = terminal_save_ours;
c5aa993b
JM
2021 child_ops.to_terminal_info = child_terminal_info;
2022 child_ops.to_kill = child_kill_inferior;
c5aa993b
JM
2023 child_ops.to_create_inferior = child_create_inferior;
2024 child_ops.to_mourn_inferior = child_mourn_inferior;
2025 child_ops.to_can_run = child_can_run;
c5aa993b 2026 child_ops.to_thread_alive = win32_child_thread_alive;
ed9a39eb 2027 child_ops.to_pid_to_str = cygwin_pid_to_str;
c5aa993b
JM
2028 child_ops.to_stop = child_stop;
2029 child_ops.to_stratum = process_stratum;
c5aa993b
JM
2030 child_ops.to_has_all_memory = 1;
2031 child_ops.to_has_memory = 1;
2032 child_ops.to_has_stack = 1;
2033 child_ops.to_has_registers = 1;
2034 child_ops.to_has_execution = 1;
c5aa993b 2035 child_ops.to_magic = OPS_MAGIC;
c906108c
SS
2036}
2037
2038void
a6b6b089 2039_initialize_win32_nat (void)
c906108c 2040{
fa58ee11
EZ
2041 struct cmd_list_element *c;
2042
c5aa993b 2043 init_child_ops ();
c906108c 2044
fa58ee11
EZ
2045 c = add_com ("dll-symbols", class_files, dll_symbol_command,
2046 "Load dll library symbols from FILE.");
5ba2abeb 2047 set_cmd_completer (c, filename_completer);
450005e7
CF
2048
2049 add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
2050
dfe7f3ac
CF
2051 add_show_from_set (add_set_cmd ("shell", class_support, var_boolean,
2052 (char *) &useshell,
2053 "Set use of shell to start subprocess.",
2054 &setlist),
2055 &showlist);
2056
450005e7 2057 add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
8e860359
CF
2058 (char *) &new_console,
2059 "Set creation of new console when creating child process.",
2060 &setlist),
2061 &showlist);
c906108c 2062
450005e7 2063 add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
8e860359
CF
2064 (char *) &new_group,
2065 "Set creation of new group when creating child process.",
2066 &setlist),
2067 &showlist);
c906108c 2068
450005e7 2069 add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
8e860359
CF
2070 (char *) &debug_exec,
2071 "Set whether to display execution in child process.",
2072 &setlist),
2073 &showlist);
c906108c 2074
450005e7 2075 add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
8e860359
CF
2076 (char *) &debug_events,
2077 "Set whether to display kernel events in child process.",
2078 &setlist),
2079 &showlist);
c906108c 2080
450005e7 2081 add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
8e860359
CF
2082 (char *) &debug_memory,
2083 "Set whether to display memory accesses in child process.",
2084 &setlist),
2085 &showlist);
c906108c 2086
450005e7 2087 add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
8e860359
CF
2088 (char *) &debug_exceptions,
2089 "Set whether to display kernel exceptions in child process.",
2090 &setlist),
2091 &showlist);
c906108c 2092
450005e7
CF
2093 add_info ("dll", info_dll_command, "Status of loaded DLLs.");
2094 add_info_alias ("sharedlibrary", "dll", 1);
2095
c1748f97 2096 add_prefix_cmd ("w32", class_info, info_w32_command,
baa93fa6
CF
2097 "Print information specific to Win32 debugging.",
2098 &info_w32_cmdlist, "info w32 ", 0, &infolist);
c1748f97
PM
2099
2100 add_cmd ("selector", class_info, display_selectors,
baa93fa6 2101 "Display selectors infos.",
c1748f97
PM
2102 &info_w32_cmdlist);
2103
c906108c
SS
2104 add_target (&child_ops);
2105}
2106
fa4ba8da
PM
2107/* Hardware watchpoint support, adapted from go32-nat.c code. */
2108
2109/* Pass the address ADDR to the inferior in the I'th debug register.
2110 Here we just store the address in dr array, the registers will be
2111 actually set up when child_continue is called. */
2112void
2113cygwin_set_dr (int i, CORE_ADDR addr)
2114{
2115 if (i < 0 || i > 3)
2116 internal_error (__FILE__, __LINE__,
2117 "Invalid register %d in cygwin_set_dr.\n", i);
2118 dr[i] = (unsigned) addr;
2119 debug_registers_changed = 1;
2120 debug_registers_used = 1;
2121}
2122
2123/* Pass the value VAL to the inferior in the DR7 debug control
2124 register. Here we just store the address in D_REGS, the watchpoint
2125 will be actually set up in child_wait. */
2126void
2127cygwin_set_dr7 (unsigned val)
2128{
2129 dr[7] = val;
2130 debug_registers_changed = 1;
2131 debug_registers_used = 1;
2132}
2133
2134/* Get the value of the DR6 debug status register from the inferior.
2135 Here we just return the value stored in dr[6]
2136 by the last call to thread_rec for current_event.dwThreadId id. */
2137unsigned
2138cygwin_get_dr6 (void)
2139{
2140 return dr[6];
2141}
2142
2143
c906108c
SS
2144/* Determine if the thread referenced by "pid" is alive
2145 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
2146 it means that the pid has died. Otherwise it is assumed to be alive. */
2147static int
39f77062 2148win32_child_thread_alive (ptid_t ptid)
c906108c 2149{
39f77062
KB
2150 int pid = PIDGET (ptid);
2151
c5aa993b
JM
2152 return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
2153 FALSE : TRUE;
c906108c
SS
2154}
2155
2156/* Convert pid to printable format. */
2157char *
39f77062 2158cygwin_pid_to_str (ptid_t ptid)
c906108c
SS
2159{
2160 static char buf[80];
39f77062
KB
2161 int pid = PIDGET (ptid);
2162
29fe111d 2163 if ((DWORD) pid == current_event.dwProcessId)
b69571f5 2164 sprintf (buf, "process %d", pid);
c906108c 2165 else
b69571f5 2166 sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
c906108c
SS
2167 return buf;
2168}
8e860359
CF
2169
2170static int
2171core_dll_symbols_add (char *dll_name, DWORD base_addr)
2172{
2173 struct objfile *objfile;
2174 char *objfile_basename;
2175 const char *dll_basename;
2176
2177 if (!(dll_basename = strrchr (dll_name, '/')))
2178 dll_basename = dll_name;
2179 else
2180 dll_basename++;
2181
2182 ALL_OBJFILES (objfile)
2183 {
2184 objfile_basename = strrchr (objfile->name, '/');
2185
2186 if (objfile_basename &&
2187 strcmp (dll_basename, objfile_basename + 1) == 0)
2188 {
2189 printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
2190 base_addr, dll_name);
2191 goto out;
2192 }
2193 }
2194
2195 register_loaded_dll (dll_name, base_addr + 0x1000);
02e423b9 2196 solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
8e860359
CF
2197
2198out:
2199 return 1;
2200}
2201
2202typedef struct
2203{
2204 struct target_ops *target;
2205 bfd_vma addr;
9f476a01 2206} map_code_section_args;
8e860359
CF
2207
2208static void
554cb486 2209map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
8e860359
CF
2210{
2211 int old;
2212 int update_coreops;
2213 struct section_table *new_target_sect_ptr;
2214
2215 map_code_section_args *args = (map_code_section_args *) obj;
2216 struct target_ops *target = args->target;
2217 if (sect->flags & SEC_CODE)
2218 {
2219 update_coreops = core_ops.to_sections == target->to_sections;
2220
2221 if (target->to_sections)
2222 {
2223 old = target->to_sections_end - target->to_sections;
2224 target->to_sections = (struct section_table *)
2225 xrealloc ((char *) target->to_sections,
2226 (sizeof (struct section_table)) * (1 + old));
2227 }
2228 else
2229 {
2230 old = 0;
2231 target->to_sections = (struct section_table *)
2232 xmalloc ((sizeof (struct section_table)));
2233 }
2234 target->to_sections_end = target->to_sections + (1 + old);
2235
2236 /* Update the to_sections field in the core_ops structure
3bccec63 2237 if needed. */
8e860359
CF
2238 if (update_coreops)
2239 {
2240 core_ops.to_sections = target->to_sections;
2241 core_ops.to_sections_end = target->to_sections_end;
2242 }
2243 new_target_sect_ptr = target->to_sections + old;
2244 new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
2245 new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
2246 bfd_section_size (abfd, sect);;
2247 new_target_sect_ptr->the_bfd_section = sect;
2248 new_target_sect_ptr->bfd = abfd;
2249 }
2250}
2251
2252static int
2253dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
2254{
2255 bfd *dll_bfd;
2256 map_code_section_args map_args;
2257 asection *lowest_sect;
2258 char *name;
2259 if (dll_name == NULL || target == NULL)
2260 return 0;
66ed1d85 2261 name = xstrdup (dll_name);
8e860359
CF
2262 dll_bfd = bfd_openr (name, "pei-i386");
2263 if (dll_bfd == NULL)
2264 return 0;
2265
2266 if (bfd_check_format (dll_bfd, bfd_object))
2267 {
2268 lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
2269 if (lowest_sect == NULL)
2270 return 0;
2271 map_args.target = target;
2272 map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
2273
554cb486 2274 bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
8e860359
CF
2275 }
2276
2277 return 1;
2278}
2279
2280static void
554cb486 2281core_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
8e860359
CF
2282{
2283 struct target_ops *target = (struct target_ops *) obj;
2284
2285 DWORD base_addr;
2286
2287 int dll_name_size;
2288 char *dll_name = NULL;
2289 char *buf = NULL;
2290 struct win32_pstatus *pstatus;
2291 char *p;
2292
2293 if (strncmp (sect->name, ".module", 7))
2294 return;
2295
2296 buf = (char *) xmalloc (sect->_raw_size + 1);
2297 if (!buf)
2298 {
2299 printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2300 goto out;
2301 }
2302 if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size))
2303 goto out;
2304
2305 pstatus = (struct win32_pstatus *) buf;
2306
2307 memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
2308 dll_name_size = pstatus->data.module_info.module_name_size;
2309 if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size)
2310 goto out;
2311
2312 dll_name = (char *) xmalloc (dll_name_size + 1);
2313 if (!dll_name)
2314 {
2315 printf_unfiltered ("memory allocation failed for %s\n", sect->name);
2316 goto out;
2317 }
2318 strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
2319
2320 while ((p = strchr (dll_name, '\\')))
2321 *p = '/';
2322
2323 if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
2324 printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
2325
2326 if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
2327 printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
2328
2329out:
2330 if (buf)
b8c9b27d 2331 xfree (buf);
8e860359 2332 if (dll_name)
b8c9b27d 2333 xfree (dll_name);
8e860359
CF
2334 return;
2335}
2336
2337void
0a65a603
AC
2338child_solib_add (char *filename, int from_tty, struct target_ops *target,
2339 int readsyms)
8e860359 2340{
990f9fe3
FF
2341 if (!readsyms)
2342 return;
8e860359
CF
2343 if (core_bfd)
2344 {
2345 child_clear_solibs ();
2346 bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
2347 }
2348 else
2349 {
2350 if (solib_end && solib_end->name)
d3ff4a77 2351 solib_end->objfile = solib_symbols_add (solib_end->name, from_tty,
3bccec63 2352 solib_end->load_addr);
8e860359
CF
2353 }
2354}
2355
2356static void
2357fetch_elf_core_registers (char *core_reg_sect,
2358 unsigned core_reg_size,
2359 int which,
2360 CORE_ADDR reg_addr)
2361{
2362 int r;
2363 if (core_reg_size < sizeof (CONTEXT))
2364 {
2365 error ("Core file register section too small (%u bytes).", core_reg_size);
2366 return;
2367 }
2368 for (r = 0; r < NUM_REGS; r++)
2369 supply_register (r, core_reg_sect + mappings[r]);
2370}
2371
2372static struct core_fns win32_elf_core_fns =
2373{
2374 bfd_target_elf_flavour,
2375 default_check_format,
2376 default_core_sniffer,
2377 fetch_elf_core_registers,
2378 NULL
2379};
2380
2381void
0613c401 2382_initialize_core_win32 (void)
8e860359
CF
2383{
2384 add_core_fns (&win32_elf_core_fns);
2385}
2a3d5645
CF
2386
2387void
2388_initialize_check_for_gdb_ini (void)
2389{
2390 char *homedir;
2391 if (inhibit_gdbinit)
2392 return;
2393
2394 homedir = getenv ("HOME");
2395 if (homedir)
2396 {
2397 char *p;
2398 char *oldini = (char *) alloca (strlen (homedir) +
2399 sizeof ("/gdb.ini"));
2400 strcpy (oldini, homedir);
2401 p = strchr (oldini, '\0');
2402 if (p > oldini && p[-1] != '/')
2403 *p++ = '/';
2404 strcpy (p, "gdb.ini");
2405 if (access (oldini, 0) == 0)
2406 {
2407 int len = strlen (oldini);
2408 char *newini = alloca (len + 1);
dfe7f3ac 2409 sprintf (newini, "%.*s.gdbinit",
58fa08f0 2410 (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
2a3d5645
CF
2411 warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini);
2412 }
2413 }
2414}
This page took 0.507568 seconds and 4 git commands to generate.