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