]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/win32-nat.c
*** empty log message ***
[thirdparty/binutils-gdb.git] / gdb / win32-nat.c
CommitLineData
c906108c 1/* Target-vector operations for controlling win32 child processes, for GDB.
b6ba6518
KB
2 Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
e6433c28 4 Contributed by Cygnus Solutions, A Red Hat Company.
c906108c
SS
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without eve nthe implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
c5aa993b 20 Foundation, Inc., 59 Temple Place - Suite 330,
4e052eda 21 Boston, MA 02111-1307, USA. */
c906108c
SS
22
23/* by Steve Chamberlain, sac@cygnus.com */
24
25/* We assume we're being built with and will be used for cygwin. */
26
27#include "defs.h"
97da3b20 28#include "tm.h" /* required for SSE registers */
c906108c
SS
29#include "frame.h" /* required by inferior.h */
30#include "inferior.h"
31#include "target.h"
c906108c
SS
32#include "gdbcore.h"
33#include "command.h"
fa58ee11 34#include "completer.h"
4e052eda 35#include "regcache.h"
2a3d5645 36#include "top.h"
c906108c
SS
37#include <signal.h>
38#include <sys/types.h>
39#include <fcntl.h>
40#include <stdlib.h>
c906108c 41#include <windows.h>
c2d11a7d 42#include <imagehlp.h>
29fe111d 43#include <sys/cygwin.h>
c906108c
SS
44
45#include "buildsym.h"
46#include "symfile.h"
47#include "objfiles.h"
48#include "gdb_string.h"
49#include "gdbthread.h"
50#include "gdbcmd.h"
51#include <sys/param.h>
c2d11a7d 52#include <unistd.h>
c906108c 53
7a292a7a 54/* The ui's event loop. */
507f3c78 55extern int (*ui_loop_hook) (int signo);
7a292a7a
SS
56
57/* If we're not using the old Cygwin header file set, define the
58 following which never should have been in the generic Win32 API
59 headers in the first place since they were our own invention... */
60#ifndef _GNU_H_WINDOWS_H
9d3789f7 61enum
8e860359
CF
62 {
63 FLAG_TRACE_BIT = 0x100,
64 CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
65 };
7a292a7a 66#endif
8e860359
CF
67#include <sys/procfs.h>
68#include <psapi.h>
7a292a7a 69
97da3b20 70#ifdef HAVE_SSE_REGS
3bccec63 71#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_EXTENDED_REGISTERS
97da3b20
CF
72#else
73#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER
74#endif
75
76
c906108c
SS
77/* The string sent by cygwin when it processes a signal.
78 FIXME: This should be in a cygwin include file. */
79#define CYGWIN_SIGNAL_STRING "cygwin: signal"
80
29fe111d 81#define CHECK(x) check (x, __FILE__,__LINE__)
c906108c
SS
82#define DEBUG_EXEC(x) if (debug_exec) printf x
83#define DEBUG_EVENTS(x) if (debug_events) printf x
84#define DEBUG_MEM(x) if (debug_memory) printf x
85#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
86
87/* Forward declaration */
88extern struct target_ops child_ops;
89
a14ed312 90static void child_stop (void);
39f77062 91static int win32_child_thread_alive (ptid_t);
a14ed312 92void child_kill_inferior (void);
c906108c 93
8a892701
CF
94static int last_sig = 0; /* Set if a signal was received from the
95 debugged process */
c906108c
SS
96/* Thread information structure used to track information that is
97 not available in gdb's thread structure. */
98typedef struct thread_info_struct
c5aa993b
JM
99 {
100 struct thread_info_struct *next;
101 DWORD id;
102 HANDLE h;
103 char *name;
104 int suspend_count;
105 CONTEXT context;
c2d11a7d 106 STACKFRAME sf;
8e860359
CF
107 }
108thread_info;
c2d11a7d 109
29fe111d 110static thread_info thread_head;
c906108c 111
c906108c
SS
112/* The process and thread handles for the above context. */
113
114static DEBUG_EVENT current_event; /* The current debug event from
115 WaitForDebugEvent */
116static HANDLE current_process_handle; /* Currently executing process */
117static thread_info *current_thread; /* Info on currently selected thread */
c5aa993b 118static DWORD main_thread_id; /* Thread ID of the main thread */
c906108c
SS
119
120/* Counts of things. */
121static int exception_count = 0;
122static int event_count = 0;
123
124/* User options. */
125static int new_console = 0;
c2d11a7d 126static int new_group = 1;
c5aa993b
JM
127static int debug_exec = 0; /* show execution */
128static int debug_events = 0; /* show events from kernel */
129static int debug_memory = 0; /* show target memory accesses */
c906108c
SS
130static int debug_exceptions = 0; /* show target exceptions */
131
132/* This vector maps GDB's idea of a register's number into an address
133 in the win32 exception context vector.
134
135 It also contains the bit mask needed to load the register in question.
136
137 One day we could read a reg, we could inspect the context we
138 already have loaded, if it doesn't have the bit set that we need,
139 we read that set of registers in using GetThreadContext. If the
140 context already contains what we need, we just unpack it. Then to
141 write a register, first we have to ensure that the context contains
142 the other regs of the group, and then we copy the info in and set
143 out bit. */
144
145#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
146static const int mappings[] =
147{
c5aa993b
JM
148 context_offset (Eax),
149 context_offset (Ecx),
150 context_offset (Edx),
151 context_offset (Ebx),
152 context_offset (Esp),
153 context_offset (Ebp),
154 context_offset (Esi),
155 context_offset (Edi),
156 context_offset (Eip),
157 context_offset (EFlags),
158 context_offset (SegCs),
159 context_offset (SegSs),
160 context_offset (SegDs),
161 context_offset (SegEs),
162 context_offset (SegFs),
163 context_offset (SegGs),
164 context_offset (FloatSave.RegisterArea[0 * 10]),
165 context_offset (FloatSave.RegisterArea[1 * 10]),
166 context_offset (FloatSave.RegisterArea[2 * 10]),
167 context_offset (FloatSave.RegisterArea[3 * 10]),
168 context_offset (FloatSave.RegisterArea[4 * 10]),
169 context_offset (FloatSave.RegisterArea[5 * 10]),
170 context_offset (FloatSave.RegisterArea[6 * 10]),
171 context_offset (FloatSave.RegisterArea[7 * 10]),
c2d11a7d
JM
172 context_offset (FloatSave.ControlWord),
173 context_offset (FloatSave.StatusWord),
174 context_offset (FloatSave.TagWord),
175 context_offset (FloatSave.ErrorSelector),
176 context_offset (FloatSave.ErrorOffset),
177 context_offset (FloatSave.DataSelector),
178 context_offset (FloatSave.DataOffset),
ed9a39eb 179 context_offset (FloatSave.ErrorSelector)
97da3b20
CF
180#ifdef HAVE_SSE_REGS
181 /* XMM0-7 */ ,
182 context_offset (ExtendedRegisters[0*16]),
183 context_offset (ExtendedRegisters[1*16]),
184 context_offset (ExtendedRegisters[2*16]),
185 context_offset (ExtendedRegisters[3*16]),
186 context_offset (ExtendedRegisters[4*16]),
187 context_offset (ExtendedRegisters[5*16]),
188 context_offset (ExtendedRegisters[6*16]),
189 context_offset (ExtendedRegisters[7*16]),
190 /* MXCSR untested */
191 context_offset (ExtendedRegisters[8*16])
192#endif
c906108c
SS
193};
194
ed9a39eb
JM
195#undef context_offset
196
c906108c
SS
197/* This vector maps the target's idea of an exception (extracted
198 from the DEBUG_EVENT structure) to GDB's idea. */
199
200struct xlate_exception
201 {
202 int them;
203 enum target_signal us;
204 };
205
206static const struct xlate_exception
207 xlate[] =
208{
209 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
210 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
211 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
212 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
213 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
214 {-1, -1}};
215
216/* Find a thread record given a thread id.
217 If get_context then also retrieve the context for this
218 thread. */
219static thread_info *
220thread_rec (DWORD id, int get_context)
221{
222 thread_info *th;
223
c5aa993b 224 for (th = &thread_head; (th = th->next) != NULL;)
c906108c
SS
225 if (th->id == id)
226 {
227 if (!th->suspend_count && get_context)
228 {
8a892701 229 if (get_context > 0 && id != current_event.dwThreadId)
c906108c
SS
230 th->suspend_count = SuspendThread (th->h) + 1;
231 else if (get_context < 0)
232 th->suspend_count = -1;
233
97da3b20 234 th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
c906108c
SS
235 GetThreadContext (th->h, &th->context);
236 }
237 return th;
238 }
239
240 return NULL;
241}
242
243/* Add a thread to the thread list */
244static thread_info *
c5aa993b 245child_add_thread (DWORD id, HANDLE h)
c906108c
SS
246{
247 thread_info *th;
248
249 if ((th = thread_rec (id, FALSE)))
250 return th;
251
252 th = (thread_info *) xmalloc (sizeof (*th));
c5aa993b 253 memset (th, 0, sizeof (*th));
c906108c
SS
254 th->id = id;
255 th->h = h;
256 th->next = thread_head.next;
257 thread_head.next = th;
39f77062 258 add_thread (pid_to_ptid (id));
c906108c
SS
259 return th;
260}
261
262/* Clear out any old thread list and reintialize it to a
263 pristine state. */
264static void
fba45db2 265child_init_thread_list (void)
c906108c
SS
266{
267 thread_info *th = &thread_head;
268
269 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
270 init_thread_list ();
271 while (th->next != NULL)
272 {
273 thread_info *here = th->next;
274 th->next = here->next;
275 (void) CloseHandle (here->h);
b8c9b27d 276 xfree (here);
c906108c
SS
277 }
278}
279
280/* Delete a thread from the list of threads */
281static void
282child_delete_thread (DWORD id)
283{
284 thread_info *th;
285
286 if (info_verbose)
39f77062
KB
287 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
288 delete_thread (pid_to_ptid (id));
c906108c
SS
289
290 for (th = &thread_head;
291 th->next != NULL && th->next->id != id;
292 th = th->next)
293 continue;
294
295 if (th->next != NULL)
296 {
297 thread_info *here = th->next;
298 th->next = here->next;
299 CloseHandle (here->h);
b8c9b27d 300 xfree (here);
c906108c
SS
301 }
302}
303
304static void
305check (BOOL ok, const char *file, int line)
306{
307 if (!ok)
29fe111d 308 printf_filtered ("error return %s:%d was %lu\n", file, line, GetLastError ());
c906108c
SS
309}
310
311static void
312do_child_fetch_inferior_registers (int r)
313{
c2d11a7d
JM
314 char *context_offset = ((char *) &current_thread->context) + mappings[r];
315 long l;
316 if (r == FCS_REGNUM)
317 {
8e860359 318 l = *((long *) context_offset) & 0xffff;
c2d11a7d
JM
319 supply_register (r, (char *) &l);
320 }
321 else if (r == FOP_REGNUM)
322 {
8e860359 323 l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
c2d11a7d
JM
324 supply_register (r, (char *) &l);
325 }
326 else if (r >= 0)
ed9a39eb 327 supply_register (r, context_offset);
c906108c
SS
328 else
329 {
330 for (r = 0; r < NUM_REGS; r++)
331 do_child_fetch_inferior_registers (r);
332 }
333}
334
335static void
336child_fetch_inferior_registers (int r)
337{
39f77062 338 current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
c906108c
SS
339 do_child_fetch_inferior_registers (r);
340}
341
342static void
343do_child_store_inferior_registers (int r)
344{
345 if (r >= 0)
346 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
347 else
348 {
349 for (r = 0; r < NUM_REGS; r++)
350 do_child_store_inferior_registers (r);
351 }
352}
353
354/* Store a new register value into the current thread context */
355static void
356child_store_inferior_registers (int r)
357{
39f77062 358 current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
c906108c
SS
359 do_child_store_inferior_registers (r);
360}
361
c2d11a7d
JM
362static int psapi_loaded = 0;
363static HMODULE psapi_module_handle = NULL;
8e860359
CF
364static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
365static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
366static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
c2d11a7d 367
3bccec63 368int
8e860359 369psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
c2d11a7d
JM
370{
371 DWORD len;
372 MODULEINFO mi;
373 int i;
8e860359
CF
374 HMODULE dh_buf[1];
375 HMODULE *DllHandle = dh_buf;
c2d11a7d
JM
376 DWORD cbNeeded;
377 BOOL ok;
378
379 if (!psapi_loaded ||
8e860359
CF
380 psapi_EnumProcessModules == NULL ||
381 psapi_GetModuleInformation == NULL ||
382 psapi_GetModuleFileNameExA == NULL)
c2d11a7d 383 {
8e860359
CF
384 if (psapi_loaded)
385 goto failed;
c2d11a7d
JM
386 psapi_loaded = 1;
387 psapi_module_handle = LoadLibrary ("psapi.dll");
388 if (!psapi_module_handle)
8e860359
CF
389 {
390 /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
391 goto failed;
392 }
393 psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
c2d11a7d
JM
394 psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
395 psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
8e860359
CF
396 "GetModuleFileNameExA");
397 if (psapi_EnumProcessModules == NULL ||
398 psapi_GetModuleInformation == NULL ||
399 psapi_GetModuleFileNameExA == NULL)
c2d11a7d
JM
400 goto failed;
401 }
402
403 cbNeeded = 0;
404 ok = (*psapi_EnumProcessModules) (current_process_handle,
8e860359
CF
405 DllHandle,
406 sizeof (HMODULE),
407 &cbNeeded);
c2d11a7d
JM
408
409 if (!ok || !cbNeeded)
410 goto failed;
411
8e860359 412 DllHandle = (HMODULE *) alloca (cbNeeded);
c2d11a7d
JM
413 if (!DllHandle)
414 goto failed;
415
416 ok = (*psapi_EnumProcessModules) (current_process_handle,
8e860359
CF
417 DllHandle,
418 cbNeeded,
419 &cbNeeded);
c2d11a7d
JM
420 if (!ok)
421 goto failed;
422
29fe111d 423 for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
c2d11a7d
JM
424 {
425 if (!(*psapi_GetModuleInformation) (current_process_handle,
8e860359
CF
426 DllHandle[i],
427 &mi,
428 sizeof (mi)))
c2d11a7d
JM
429 error ("Can't get module info");
430
431 len = (*psapi_GetModuleFileNameExA) (current_process_handle,
8e860359
CF
432 DllHandle[i],
433 dll_name_ret,
434 MAX_PATH);
c2d11a7d 435 if (len == 0)
29fe111d 436 error ("Error getting dll name: %u\n", GetLastError ());
c2d11a7d
JM
437
438 if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
439 return 1;
440 }
441
442failed:
443 dll_name_ret[0] = '\0';
444 return 0;
445}
446
450005e7
CF
447/* Encapsulate the information required in a call to
448 symbol_file_add_args */
8a892701
CF
449struct safe_symbol_file_add_args
450{
451 char *name;
452 int from_tty;
453 struct section_addr_info *addrs;
454 int mainline;
455 int flags;
7c5c87c0 456 struct ui_file *err, *out;
8a892701
CF
457 struct objfile *ret;
458};
459
02e423b9
CF
460/* Maintain a linked list of "so" information. */
461struct so_stuff
462{
d3ff4a77 463 struct so_stuff *next;
02e423b9 464 DWORD load_addr;
7470a420 465 int loaded;
d3ff4a77 466 struct objfile *objfile;
7470a420
CF
467 char name[1];
468} solib_start, *solib_end;
02e423b9 469
450005e7
CF
470/* Call symbol_file_add with stderr redirected. We don't care if there
471 are errors. */
8a892701
CF
472static int
473safe_symbol_file_add_stub (void *argv)
474{
475#define p ((struct safe_symbol_file_add_args *)argv)
fefd0a37 476 struct so_stuff *so = &solib_start;
02e423b9
CF
477
478 while ((so = so->next))
7470a420 479 if (so->loaded && strcasecmp (so->name, p->name) == 0)
02e423b9 480 return 0;
8a892701
CF
481 p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
482 return !!p->ret;
483#undef p
484}
485
450005e7 486/* Restore gdb's stderr after calling symbol_file_add */
8a892701 487static void
7c5c87c0 488safe_symbol_file_add_cleanup (void *p)
8a892701 489{
8e860359 490#define sp ((struct safe_symbol_file_add_args *)p)
450005e7 491 gdb_flush (gdb_stderr);
7c5c87c0 492 gdb_flush (gdb_stdout);
d3ff4a77 493 ui_file_delete (gdb_stderr);
7c5c87c0 494 ui_file_delete (gdb_stdout);
d3ff4a77 495 gdb_stderr = sp->err;
9d3789f7 496 gdb_stdout = sp->out;
8e860359 497#undef sp
8a892701
CF
498}
499
450005e7 500/* symbol_file_add wrapper that prevents errors from being displayed. */
8a892701
CF
501static struct objfile *
502safe_symbol_file_add (char *name, int from_tty,
503 struct section_addr_info *addrs,
504 int mainline, int flags)
8a892701
CF
505{
506 struct safe_symbol_file_add_args p;
507 struct cleanup *cleanup;
508
7c5c87c0 509 cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
8a892701 510
7c5c87c0
CF
511 p.err = gdb_stderr;
512 p.out = gdb_stdout;
450005e7 513 gdb_flush (gdb_stderr);
7c5c87c0 514 gdb_flush (gdb_stdout);
d3ff4a77 515 gdb_stderr = ui_file_new ();
7c5c87c0 516 gdb_stdout = ui_file_new ();
8a892701
CF
517 p.name = name;
518 p.from_tty = from_tty;
519 p.addrs = addrs;
520 p.mainline = mainline;
521 p.flags = flags;
522 catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
523
524 do_cleanups (cleanup);
525 return p.ret;
526}
527
450005e7
CF
528/* Remember the maximum DLL length for printing in info dll command. */
529int max_dll_name_len;
530
8e860359
CF
531static void
532register_loaded_dll (const char *name, DWORD load_addr)
533{
534 struct so_stuff *so;
7470a420 535 char ppath[MAX_PATH + 1];
3f8ad85b
CF
536 char buf[MAX_PATH + 1];
537 char cwd[MAX_PATH + 1];
538 char *p;
539 WIN32_FIND_DATA w32_fd;
540 HANDLE h = FindFirstFile(name, &w32_fd);
541 size_t len;
542
543 FindClose (h);
544 strcpy (buf, name);
545 if (GetCurrentDirectory (MAX_PATH + 1, cwd))
546 {
547 p = strrchr (buf, '\\');
548 if (p)
549 p[1] = '\0';
550 SetCurrentDirectory (buf);
551 GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
552 SetCurrentDirectory (cwd);
553 }
554
555 cygwin_conv_to_posix_path (buf, ppath);
7470a420
CF
556 so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
557 so->loaded = 0;
8e860359 558 so->load_addr = load_addr;
d3ff4a77
CF
559 so->next = NULL;
560 so->objfile = NULL;
7470a420 561 strcpy (so->name, ppath);
8e860359
CF
562
563 solib_end->next = so;
564 solib_end = so;
3f8ad85b
CF
565 len = strlen (ppath);
566 if (len > max_dll_name_len)
567 max_dll_name_len = len;
8e860359
CF
568}
569
c906108c
SS
570/* Wait for child to do something. Return pid of child, or -1 in case
571 of error; store status through argument pointer OURSTATUS. */
c906108c 572static int
554cb486 573handle_load_dll (void *dummy ATTRIBUTE_UNUSED)
c906108c 574{
c5aa993b 575 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
c906108c
SS
576 DWORD dll_name_ptr;
577 DWORD done;
578 char dll_buf[MAX_PATH + 1];
450005e7 579 char *dll_name = NULL;
450005e7 580 char *p;
c906108c 581
c5aa993b 582 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
c906108c 583
c2d11a7d 584 if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
8e860359 585 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
c906108c 586
c2d11a7d 587 dll_name = dll_buf;
c906108c
SS
588
589 /* Attempt to read the name of the dll that was detected.
590 This is documented to work only when actively debugging
591 a program. It will not work for attached processes. */
592 if (dll_name == NULL || *dll_name == '\0')
593 {
29fe111d 594 DWORD size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
c906108c
SS
595 int len = 0;
596 char b[2];
597
598 ReadProcessMemory (current_process_handle,
599 (LPCVOID) event->lpImageName,
600 (char *) &dll_name_ptr,
601 sizeof (dll_name_ptr), &done);
602
603 /* See if we could read the address of a string, and that the
3bccec63 604 address isn't null. */
c906108c
SS
605
606 if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
607 return 1;
608
609 do
610 {
611 ReadProcessMemory (current_process_handle,
612 (LPCVOID) (dll_name_ptr + len * size),
613 &b,
614 size,
615 &done);
616 len++;
617 }
618 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
619
620 dll_name = alloca (len);
621
622 if (event->fUnicode)
623 {
624 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
625 ReadProcessMemory (current_process_handle,
626 (LPCVOID) dll_name_ptr,
627 unicode_dll_name,
628 len * sizeof (WCHAR),
629 &done);
630
631 WideCharToMultiByte (CP_ACP, 0,
632 unicode_dll_name, len,
633 dll_name, len, 0, 0);
634 }
635 else
636 {
637 ReadProcessMemory (current_process_handle,
638 (LPCVOID) dll_name_ptr,
639 dll_name,
640 len,
641 &done);
642 }
643 }
644
645 if (!dll_name)
646 return 1;
647
8e860359 648 register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000);
450005e7
CF
649
650 return 1;
651}
652
d3ff4a77
CF
653static int
654handle_unload_dll (void *dummy ATTRIBUTE_UNUSED)
655{
656 DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
657 struct so_stuff *so;
658
659 for (so = &solib_start; so->next != NULL; so = so->next)
660 if (so->next->load_addr == lpBaseOfDll)
661 {
662 struct so_stuff *sodel = so->next;
663 so->next = sodel->next;
664 if (!so->next)
665 solib_end = so;
666 if (sodel->objfile)
667 free_objfile (sodel->objfile);
668 xfree(sodel);
669 return 1;
670 }
671 error ("Error: dll starting at 0x%lx not found.\n", (DWORD) lpBaseOfDll);
672
673 return 0;
674}
675
450005e7
CF
676/* Return name of last loaded DLL. */
677char *
9d3789f7 678child_solib_loaded_library_pathname (int pid ATTRIBUTE_UNUSED)
450005e7 679{
8e860359 680 return !solib_end || !solib_end->name[0] ? NULL : solib_end->name;
450005e7
CF
681}
682
683/* Clear list of loaded DLLs. */
684void
685child_clear_solibs (void)
686{
687 struct so_stuff *so, *so1 = solib_start.next;
688
689 while ((so = so1) != NULL)
690 {
691 so1 = so->next;
b8c9b27d 692 xfree (so);
450005e7
CF
693 }
694
695 solib_start.next = NULL;
d3ff4a77 696 solib_start.objfile = NULL;
450005e7
CF
697 solib_end = &solib_start;
698 max_dll_name_len = sizeof ("DLL Name") - 1;
699}
700
701/* Add DLL symbol information. */
d3ff4a77 702static struct objfile *
02e423b9 703solib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr)
450005e7
CF
704{
705 struct section_addr_info section_addrs;
706
c906108c
SS
707 /* The symbols in a dll are offset by 0x1000, which is the
708 the offset from 0 of the first byte in an image - because
8a892701 709 of the file header and the section alignment. */
c906108c 710
8e860359 711 if (!name || !name[0])
d3ff4a77 712 return NULL;
450005e7
CF
713
714 memset (&section_addrs, 0, sizeof (section_addrs));
0aa9cf96 715 section_addrs.other[0].name = ".text";
8e860359 716 section_addrs.other[0].addr = load_addr;
d3ff4a77 717 return safe_symbol_file_add (name, from_tty, NULL, 0, OBJF_SHARED);
450005e7
CF
718}
719
720/* Load DLL symbol info. */
721void
7470a420 722dll_symbol_command (char *args, int from_tty)
450005e7 723{
8e860359 724 int n;
450005e7 725 dont_repeat ();
8e860359 726
450005e7
CF
727 if (args == NULL)
728 error ("dll-symbols requires a file name");
729
8e860359
CF
730 n = strlen (args);
731 if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
732 {
733 char *newargs = (char *) alloca (n + 4 + 1);
734 strcpy (newargs, args);
735 strcat (newargs, ".dll");
736 args = newargs;
737 }
738
7470a420 739 safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
8e860359 740}
450005e7
CF
741
742/* List currently loaded DLLs. */
743void
9d3789f7 744info_dll_command (char *ignore ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
450005e7
CF
745{
746 struct so_stuff *so = &solib_start;
747
748 if (!so->next)
749 return;
750
751 printf ("%*s Load Address\n", -max_dll_name_len, "DLL Name");
752 while ((so = so->next) != NULL)
7c5c87c0 753 printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
450005e7
CF
754
755 return;
c906108c
SS
756}
757
758/* Handle DEBUG_STRING output from child process.
759 Cygwin prepends its messages with a "cygwin:". Interpret this as
760 a Cygwin signal. Otherwise just print the string as a warning. */
761static int
762handle_output_debug_string (struct target_waitstatus *ourstatus)
763{
764 char *s;
765 int gotasig = FALSE;
766
767 if (!target_read_string
c5aa993b 768 ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
c906108c
SS
769 || !s || !*s)
770 return gotasig;
771
ed9a39eb 772 if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
c906108c 773 {
ed9a39eb 774 if (strncmp (s, "cYg", 3) != 0)
29fe111d 775 warning ("%s", s);
c906108c 776 }
ed9a39eb 777 else
c906108c
SS
778 {
779 char *p;
c2d11a7d
JM
780 int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
781 gotasig = target_signal_from_host (sig);
7a292a7a
SS
782 ourstatus->value.sig = gotasig;
783 if (gotasig)
c906108c
SS
784 ourstatus->kind = TARGET_WAITKIND_STOPPED;
785 }
786
b8c9b27d 787 xfree (s);
c906108c
SS
788 return gotasig;
789}
790
791static int
450005e7 792handle_exception (struct target_waitstatus *ourstatus)
c906108c 793{
c906108c 794 thread_info *th;
29fe111d 795 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
c906108c 796
29fe111d 797 ourstatus->kind = TARGET_WAITKIND_STOPPED;
8a892701 798
c906108c
SS
799 /* Record the context of the current thread */
800 th = thread_rec (current_event.dwThreadId, -1);
801
29fe111d 802 switch (code)
c906108c
SS
803 {
804 case EXCEPTION_ACCESS_VIOLATION:
29fe111d 805 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
8e860359 806 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
c906108c 807 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
8a892701 808 last_sig = SIGSEGV;
c906108c 809 break;
0d06e24b
JM
810 case STATUS_FLOAT_UNDERFLOW:
811 case STATUS_FLOAT_DIVIDE_BY_ZERO:
812 case STATUS_FLOAT_OVERFLOW:
813 case STATUS_INTEGER_DIVIDE_BY_ZERO:
29fe111d 814 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
8e860359 815 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
0d06e24b 816 ourstatus->value.sig = TARGET_SIGNAL_FPE;
29fe111d 817 last_sig = SIGFPE;
0d06e24b 818 break;
c906108c 819 case STATUS_STACK_OVERFLOW:
29fe111d 820 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
8e860359 821 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
c906108c
SS
822 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
823 break;
824 case EXCEPTION_BREAKPOINT:
29fe111d 825 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
8e860359 826 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
c906108c
SS
827 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
828 break;
829 case DBG_CONTROL_C:
29fe111d 830 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
8e860359 831 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
c906108c 832 ourstatus->value.sig = TARGET_SIGNAL_INT;
8a892701 833 last_sig = SIGINT; /* FIXME - should check pass state */
c906108c
SS
834 break;
835 case EXCEPTION_SINGLE_STEP:
29fe111d 836 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
8e860359 837 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
c906108c
SS
838 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
839 break;
8227c82d 840 case EXCEPTION_ILLEGAL_INSTRUCTION:
29fe111d 841 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
8e860359 842 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
8227c82d 843 ourstatus->value.sig = TARGET_SIGNAL_ILL;
8a892701 844 last_sig = SIGILL;
8227c82d 845 break;
c906108c 846 default:
02e423b9
CF
847 if (current_event.u.Exception.dwFirstChance)
848 return 0;
29fe111d 849 printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
c5aa993b 850 current_event.u.Exception.ExceptionRecord.ExceptionCode,
8e860359 851 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
c906108c
SS
852 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
853 break;
854 }
855 exception_count++;
856 return 1;
857}
858
859/* Resume all artificially suspended threads if we are continuing
860 execution */
861static BOOL
8a892701 862child_continue (DWORD continue_status, int id)
c906108c
SS
863{
864 int i;
865 thread_info *th;
866 BOOL res;
867
29fe111d 868 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, DBG_CONTINUE);\n",
c906108c 869 current_event.dwProcessId, current_event.dwThreadId));
7a292a7a
SS
870 res = ContinueDebugEvent (current_event.dwProcessId,
871 current_event.dwThreadId,
872 continue_status);
c2d11a7d 873 continue_status = 0;
7a292a7a 874 if (res)
c5aa993b 875 for (th = &thread_head; (th = th->next) != NULL;)
29fe111d 876 if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
c906108c
SS
877 {
878 for (i = 0; i < th->suspend_count; i++)
879 (void) ResumeThread (th->h);
880 th->suspend_count = 0;
881 }
882
883 return res;
884}
885
8a892701
CF
886/* Get the next event from the child. Return 1 if the event requires
887 handling by WFI (or whatever).
888 */
c2d11a7d 889static int
450005e7 890get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
c2d11a7d
JM
891{
892 BOOL debug_event;
8a892701
CF
893 DWORD continue_status, event_code;
894 thread_info *th = NULL;
895 static thread_info dummy_thread_info;
450005e7 896 int retval = 0;
c2d11a7d 897
9d3789f7
CF
898 last_sig = 0;
899
8a892701 900 if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
29fe111d 901 goto out;
c2d11a7d
JM
902
903 event_count++;
904 continue_status = DBG_CONTINUE;
c2d11a7d 905
8a892701 906 event_code = current_event.dwDebugEventCode;
450005e7 907 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
8a892701
CF
908
909 switch (event_code)
c2d11a7d
JM
910 {
911 case CREATE_THREAD_DEBUG_EVENT:
912 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
913 (unsigned) current_event.dwProcessId,
914 (unsigned) current_event.dwThreadId,
915 "CREATE_THREAD_DEBUG_EVENT"));
c2d11a7d 916 /* Record the existence of this thread */
8a892701
CF
917 th = child_add_thread (current_event.dwThreadId,
918 current_event.u.CreateThread.hThread);
c2d11a7d
JM
919 if (info_verbose)
920 printf_unfiltered ("[New %s]\n",
39f77062
KB
921 target_pid_to_str (
922 pid_to_ptid (current_event.dwThreadId)));
450005e7 923 retval = current_event.dwThreadId;
c2d11a7d
JM
924 break;
925
926 case EXIT_THREAD_DEBUG_EVENT:
927 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
928 (unsigned) current_event.dwProcessId,
929 (unsigned) current_event.dwThreadId,
930 "EXIT_THREAD_DEBUG_EVENT"));
c2d11a7d 931 child_delete_thread (current_event.dwThreadId);
8a892701 932 th = &dummy_thread_info;
c2d11a7d
JM
933 break;
934
935 case CREATE_PROCESS_DEBUG_EVENT:
936 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
937 (unsigned) current_event.dwProcessId,
938 (unsigned) current_event.dwThreadId,
939 "CREATE_PROCESS_DEBUG_EVENT"));
700b351b 940 CloseHandle (current_event.u.CreateProcessInfo.hFile);
c2d11a7d
JM
941 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
942
9d3789f7 943 main_thread_id = current_event.dwThreadId;
c2d11a7d 944 /* Add the main thread */
9d3789f7 945#if 0
450005e7
CF
946 th = child_add_thread (current_event.dwProcessId,
947 current_event.u.CreateProcessInfo.hProcess);
9d3789f7
CF
948#endif
949 th = child_add_thread (main_thread_id,
8a892701 950 current_event.u.CreateProcessInfo.hThread);
9d3789f7 951 retval = ourstatus->value.related_pid = current_event.dwThreadId;
c2d11a7d
JM
952 break;
953
954 case EXIT_PROCESS_DEBUG_EVENT:
955 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
956 (unsigned) current_event.dwProcessId,
957 (unsigned) current_event.dwThreadId,
958 "EXIT_PROCESS_DEBUG_EVENT"));
c2d11a7d
JM
959 ourstatus->kind = TARGET_WAITKIND_EXITED;
960 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
961 CloseHandle (current_process_handle);
9d3789f7 962 retval = main_thread_id;
8a892701 963 break;
c2d11a7d
JM
964
965 case LOAD_DLL_DEBUG_EVENT:
966 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
967 (unsigned) current_event.dwProcessId,
968 (unsigned) current_event.dwThreadId,
969 "LOAD_DLL_DEBUG_EVENT"));
700b351b 970 CloseHandle (current_event.u.LoadDll.hFile);
8a892701 971 catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
c2d11a7d 972 registers_changed (); /* mark all regs invalid */
450005e7
CF
973 ourstatus->kind = TARGET_WAITKIND_LOADED;
974 ourstatus->value.integer = 0;
9d3789f7 975 retval = main_thread_id;
c2d11a7d
JM
976 break;
977
978 case UNLOAD_DLL_DEBUG_EVENT:
979 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
980 (unsigned) current_event.dwProcessId,
981 (unsigned) current_event.dwThreadId,
982 "UNLOAD_DLL_DEBUG_EVENT"));
d3ff4a77
CF
983 catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
984 registers_changed (); /* mark all regs invalid */
985 /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
3bccec63 986 does not exist yet. */
d3ff4a77 987 break;
c2d11a7d
JM
988
989 case EXCEPTION_DEBUG_EVENT:
990 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
991 (unsigned) current_event.dwProcessId,
992 (unsigned) current_event.dwThreadId,
993 "EXCEPTION_DEBUG_EVENT"));
02e423b9
CF
994 if (handle_exception (ourstatus))
995 retval = current_event.dwThreadId;
c2d11a7d
JM
996 break;
997
8a892701 998 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
c2d11a7d 999 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
1000 (unsigned) current_event.dwProcessId,
1001 (unsigned) current_event.dwThreadId,
1002 "OUTPUT_DEBUG_STRING_EVENT"));
8e860359 1003 if (handle_output_debug_string (ourstatus))
9d3789f7 1004 retval = main_thread_id;
c2d11a7d 1005 break;
9d3789f7 1006
c2d11a7d 1007 default:
29fe111d
CF
1008 printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
1009 (DWORD) current_event.dwProcessId,
1010 (DWORD) current_event.dwThreadId);
1011 printf_unfiltered (" unknown event code %ld\n",
c2d11a7d
JM
1012 current_event.dwDebugEventCode);
1013 break;
1014 }
1015
450005e7 1016 if (!retval)
8a892701 1017 CHECK (child_continue (continue_status, -1));
450005e7 1018 else
9d3789f7 1019 {
8e860359 1020 current_thread = th ? : thread_rec (current_event.dwThreadId, TRUE);
39f77062 1021 inferior_ptid = pid_to_ptid (retval);
9d3789f7 1022 }
c2d11a7d
JM
1023
1024out:
450005e7 1025 return retval;
c2d11a7d
JM
1026}
1027
c2d11a7d 1028/* Wait for interesting events to occur in the target process. */
39f77062
KB
1029static ptid_t
1030child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c 1031{
39f77062
KB
1032 int pid = PIDGET (ptid);
1033
c906108c
SS
1034 /* We loop when we get a non-standard exception rather than return
1035 with a SPURIOUS because resume can try and step or modify things,
1036 which needs a current_thread->h. But some of these exceptions mark
1037 the birth or death of threads, which mean that the current thread
1038 isn't necessarily what you think it is. */
1039
1040 while (1)
450005e7
CF
1041 {
1042 int retval = get_child_debug_event (pid, ourstatus);
1043 if (retval)
39f77062 1044 return pid_to_ptid (retval);
450005e7
CF
1045 else
1046 {
1047 int detach = 0;
c906108c 1048
450005e7
CF
1049 if (ui_loop_hook != NULL)
1050 detach = ui_loop_hook (0);
7a292a7a 1051
450005e7
CF
1052 if (detach)
1053 child_kill_inferior ();
1054 }
1055 }
c906108c
SS
1056}
1057
9d3789f7
CF
1058static void
1059do_initial_child_stuff (DWORD pid)
1060{
1061 extern int stop_after_trap;
1062
1063 last_sig = 0;
1064 event_count = 0;
1065 exception_count = 0;
1066 current_event.dwProcessId = pid;
1067 memset (&current_event, 0, sizeof (current_event));
1068 push_target (&child_ops);
1069 child_init_thread_list ();
1070 child_clear_solibs ();
1071 clear_proceed_status ();
1072 init_wait_for_inferior ();
1073
1074 target_terminal_init ();
1075 target_terminal_inferior ();
1076
1077 while (1)
1078 {
1079 stop_after_trap = 1;
1080 wait_for_inferior ();
1081 if (stop_signal != TARGET_SIGNAL_TRAP)
1082 resume (0, stop_signal);
1083 else
1084 break;
1085 }
1086 stop_after_trap = 0;
1087 return;
1088}
1089
02cc9f49
CV
1090/* Since Windows XP, detaching from a process is supported by Windows.
1091 The following code tries loading the appropriate functions dynamically.
1092 If loading these functions succeeds use them to actually detach from
1093 the inferior process, otherwise behave as usual, pretending that
1094 detach has worked. */
1095static BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL);
1096static BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
1097
1098static int
1099has_detach_ability ()
1100{
1101 static HMODULE kernel32 = NULL;
1102
1103 if (!kernel32)
1104 kernel32 = LoadLibrary ("kernel32.dll");
1105 if (kernel32)
1106 {
1107 if (!DebugSetProcessKillOnExit)
1108 DebugSetProcessKillOnExit = GetProcAddress (kernel32,
1109 "DebugSetProcessKillOnExit");
1110 if (!DebugActiveProcessStop)
1111 DebugActiveProcessStop = GetProcAddress (kernel32,
1112 "DebugActiveProcessStop");
1113 if (DebugSetProcessKillOnExit && DebugActiveProcessStop)
1114 return 1;
1115 }
1116 return 0;
1117}
c906108c 1118
02cc9f49 1119/* Attach to process PID, then initialize for debugging it. */
c906108c 1120static void
fba45db2 1121child_attach (char *args, int from_tty)
c906108c
SS
1122{
1123 BOOL ok;
559e75c0 1124 DWORD pid;
c906108c
SS
1125
1126 if (!args)
1127 error_no_arg ("process-id to attach");
1128
559e75c0 1129 pid = strtoul (args, 0, 0);
9d3789f7 1130 ok = DebugActiveProcess (pid);
c906108c
SS
1131
1132 if (!ok)
1133 error ("Can't attach to process.");
1134
02cc9f49
CV
1135 if (has_detach_ability ())
1136 {
1137 attach_flag = 1;
1138 DebugSetProcessKillOnExit (FALSE);
1139 }
1140
c906108c
SS
1141 if (from_tty)
1142 {
1143 char *exec_file = (char *) get_exec_file (0);
1144
1145 if (exec_file)
1146 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
39f77062 1147 target_pid_to_str (pid_to_ptid (pid)));
c906108c
SS
1148 else
1149 printf_unfiltered ("Attaching to %s\n",
39f77062 1150 target_pid_to_str (pid_to_ptid (pid)));
c906108c
SS
1151
1152 gdb_flush (gdb_stdout);
1153 }
1154
9d3789f7
CF
1155 do_initial_child_stuff (pid);
1156 target_terminal_ours ();
c906108c
SS
1157}
1158
1159static void
29fe111d 1160child_detach (char *args ATTRIBUTE_UNUSED, int from_tty)
c906108c 1161{
02cc9f49
CV
1162 int detached = 1;
1163
1164 if (has_detach_ability ())
1165 {
1166 delete_command (NULL, 0);
1167 child_continue (DBG_CONTINUE, -1);
1168 if (!DebugActiveProcessStop (current_event.dwProcessId))
3bccec63 1169 {
02cc9f49
CV
1170 error ("Can't detach process %lu (error %lu)",
1171 current_event.dwProcessId, GetLastError ());
1172 detached = 0;
3bccec63 1173 }
02cc9f49
CV
1174 DebugSetProcessKillOnExit (FALSE);
1175 }
1176 if (detached && from_tty)
c906108c
SS
1177 {
1178 char *exec_file = get_exec_file (0);
1179 if (exec_file == 0)
1180 exec_file = "";
02cc9f49
CV
1181 printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file,
1182 current_event.dwProcessId);
c906108c
SS
1183 gdb_flush (gdb_stdout);
1184 }
39f77062 1185 inferior_ptid = null_ptid;
c906108c
SS
1186 unpush_target (&child_ops);
1187}
1188
1189/* Print status information about what we're accessing. */
1190
1191static void
29fe111d 1192child_files_info (struct target_ops *ignore ATTRIBUTE_UNUSED)
c906108c
SS
1193{
1194 printf_unfiltered ("\tUsing the running image of %s %s.\n",
39f77062 1195 attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
c906108c
SS
1196}
1197
1198/* ARGSUSED */
1199static void
29fe111d 1200child_open (char *arg ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
c906108c
SS
1201{
1202 error ("Use the \"run\" command to start a Unix child process.");
1203}
1204
39f77062 1205/* Start an inferior win32 child process and sets inferior_ptid to its pid.
c906108c
SS
1206 EXEC_FILE is the file to run.
1207 ALLARGS is a string containing the arguments to the program.
1208 ENV is the environment vector to pass. Errors reported with error(). */
1209
1210static void
fba45db2 1211child_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
1212{
1213 char real_path[MAXPATHLEN];
1214 char *winenv;
1215 char *temp;
c5aa993b 1216 int envlen;
c906108c 1217 int i;
c906108c
SS
1218 STARTUPINFO si;
1219 PROCESS_INFORMATION pi;
c906108c
SS
1220 BOOL ret;
1221 DWORD flags;
1222 char *args;
1223
1224 if (!exec_file)
450005e7 1225 error ("No executable specified, use `target exec'.\n");
c906108c
SS
1226
1227 memset (&si, 0, sizeof (si));
1228 si.cb = sizeof (si);
1229
29fe111d 1230 cygwin_conv_to_win32_path (exec_file, real_path);
c906108c
SS
1231
1232 flags = DEBUG_ONLY_THIS_PROCESS;
1233
1234 if (new_group)
1235 flags |= CREATE_NEW_PROCESS_GROUP;
1236
1237 if (new_console)
1238 flags |= CREATE_NEW_CONSOLE;
1239
1240 args = alloca (strlen (real_path) + strlen (allargs) + 2);
1241
1242 strcpy (args, real_path);
1243
1244 strcat (args, " ");
1245 strcat (args, allargs);
1246
1247 /* Prepare the environment vars for CreateProcess. */
1248 {
1249 /* This code use to assume all env vars were file names and would
1250 translate them all to win32 style. That obviously doesn't work in the
1251 general case. The current rule is that we only translate PATH.
1252 We need to handle PATH because we're about to call CreateProcess and
1253 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
1254 in both posix and win32 environments. cygwin.dll will change it back
1255 to posix style if necessary. */
1256
1257 static const char *conv_path_names[] =
c5aa993b
JM
1258 {
1259 "PATH=",
1260 0
1261 };
c906108c
SS
1262
1263 /* CreateProcess takes the environment list as a null terminated set of
1264 strings (i.e. two nulls terminate the list). */
1265
1266 /* Get total size for env strings. */
1267 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1268 {
1269 int j, len;
1270
1271 for (j = 0; conv_path_names[j]; j++)
1272 {
1273 len = strlen (conv_path_names[j]);
1274 if (strncmp (conv_path_names[j], env[i], len) == 0)
1275 {
29fe111d 1276 if (cygwin_posix_path_list_p (env[i] + len))
c906108c 1277 envlen += len
29fe111d 1278 + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
c906108c
SS
1279 else
1280 envlen += strlen (env[i]) + 1;
1281 break;
1282 }
1283 }
1284 if (conv_path_names[j] == NULL)
1285 envlen += strlen (env[i]) + 1;
1286 }
1287
1288 winenv = alloca (envlen + 1);
1289
1290 /* Copy env strings into new buffer. */
1291 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1292 {
1293 int j, len;
1294
1295 for (j = 0; conv_path_names[j]; j++)
1296 {
1297 len = strlen (conv_path_names[j]);
1298 if (strncmp (conv_path_names[j], env[i], len) == 0)
1299 {
29fe111d 1300 if (cygwin_posix_path_list_p (env[i] + len))
c906108c
SS
1301 {
1302 memcpy (temp, env[i], len);
29fe111d 1303 cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
c906108c
SS
1304 }
1305 else
1306 strcpy (temp, env[i]);
1307 break;
1308 }
1309 }
1310 if (conv_path_names[j] == NULL)
1311 strcpy (temp, env[i]);
1312
1313 temp += strlen (temp) + 1;
1314 }
1315
1316 /* Final nil string to terminate new env. */
1317 *temp = 0;
1318 }
1319
1320 ret = CreateProcess (0,
c5aa993b 1321 args, /* command line */
c906108c
SS
1322 NULL, /* Security */
1323 NULL, /* thread */
1324 TRUE, /* inherit handles */
1325 flags, /* start flags */
1326 winenv,
1327 NULL, /* current directory */
1328 &si,
1329 &pi);
1330 if (!ret)
c5aa993b 1331 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
c906108c 1332
700b351b
CF
1333 CloseHandle (pi.hThread);
1334 CloseHandle (pi.hProcess);
9d3789f7 1335 do_initial_child_stuff (pi.dwProcessId);
ed9a39eb 1336
8e860359 1337 /* child_continue (DBG_CONTINUE, -1); */
c2d11a7d 1338 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
c906108c
SS
1339}
1340
1341static void
fba45db2 1342child_mourn_inferior (void)
c906108c 1343{
8a892701 1344 (void) child_continue (DBG_CONTINUE, -1);
c906108c
SS
1345 unpush_target (&child_ops);
1346 generic_mourn_inferior ();
1347}
1348
1349/* Send a SIGINT to the process group. This acts just like the user typed a
1350 ^C on the controlling terminal. */
1351
1352static void
fba45db2 1353child_stop (void)
c906108c
SS
1354{
1355 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
c2d11a7d 1356 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
c5aa993b 1357 registers_changed (); /* refresh register state */
c906108c
SS
1358}
1359
1360int
1361child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
56c40d46 1362 int write, struct mem_attrib *mem ATTRIBUTE_UNUSED,
aea02b6b 1363 struct target_ops *target ATTRIBUTE_UNUSED)
c906108c
SS
1364{
1365 DWORD done;
1366 if (write)
1367 {
29fe111d
CF
1368 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1369 len, (DWORD) memaddr));
c906108c
SS
1370 WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1371 len, &done);
1372 FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
1373 }
1374 else
1375 {
29fe111d
CF
1376 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1377 len, (DWORD) memaddr));
c906108c
SS
1378 ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
1379 &done);
1380 }
1381 return done;
1382}
1383
1384void
1385child_kill_inferior (void)
1386{
1387 CHECK (TerminateProcess (current_process_handle, 0));
1388
1389 for (;;)
1390 {
8a892701 1391 if (!child_continue (DBG_CONTINUE, -1))
c906108c
SS
1392 break;
1393 if (!WaitForDebugEvent (&current_event, INFINITE))
1394 break;
1395 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1396 break;
1397 }
1398
1399 CHECK (CloseHandle (current_process_handle));
1400
1401 /* this may fail in an attached process so don't check. */
1402 (void) CloseHandle (current_thread->h);
c5aa993b 1403 target_mourn_inferior (); /* or just child_mourn_inferior? */
c906108c
SS
1404}
1405
1406void
39f77062 1407child_resume (ptid_t ptid, int step, enum target_signal sig)
c906108c 1408{
c906108c 1409 thread_info *th;
8a892701 1410 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
8e860359 1411 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
39f77062 1412 int pid = PIDGET (ptid);
8a892701
CF
1413
1414 last_sig = 0;
c906108c
SS
1415
1416 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1417 pid, step, sig));
1418
1419 /* Get context for currently selected thread */
1420 th = thread_rec (current_event.dwThreadId, FALSE);
450005e7 1421 if (th)
c906108c 1422 {
450005e7
CF
1423 if (step)
1424 {
1425 /* Single step by setting t bit */
1426 child_fetch_inferior_registers (PS_REGNUM);
1427 th->context.EFlags |= FLAG_TRACE_BIT;
1428 }
c906108c 1429
450005e7
CF
1430 if (th->context.ContextFlags)
1431 {
1432 CHECK (SetThreadContext (th->h, &th->context));
1433 th->context.ContextFlags = 0;
1434 }
c906108c
SS
1435 }
1436
1437 /* Allow continuing with the same signal that interrupted us.
1438 Otherwise complain. */
c906108c 1439
8a892701 1440 child_continue (continue_status, pid);
c906108c
SS
1441}
1442
1443static void
fba45db2 1444child_prepare_to_store (void)
c906108c
SS
1445{
1446 /* Do nothing, since we can store individual regs */
1447}
1448
1449static int
fba45db2 1450child_can_run (void)
c906108c
SS
1451{
1452 return 1;
1453}
1454
1455static void
9d3789f7 1456child_close (int x ATTRIBUTE_UNUSED)
c906108c 1457{
39f77062 1458 DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
3bccec63 1459 PIDGET (inferior_ptid)));
c906108c
SS
1460}
1461
c5aa993b 1462struct target_ops child_ops;
c906108c 1463
c5aa993b
JM
1464static void
1465init_child_ops (void)
c906108c 1466{
c5aa993b
JM
1467 child_ops.to_shortname = "child";
1468 child_ops.to_longname = "Win32 child process";
1469 child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
1470 child_ops.to_open = child_open;
1471 child_ops.to_close = child_close;
1472 child_ops.to_attach = child_attach;
1473 child_ops.to_detach = child_detach;
1474 child_ops.to_resume = child_resume;
1475 child_ops.to_wait = child_wait;
1476 child_ops.to_fetch_registers = child_fetch_inferior_registers;
1477 child_ops.to_store_registers = child_store_inferior_registers;
1478 child_ops.to_prepare_to_store = child_prepare_to_store;
1479 child_ops.to_xfer_memory = child_xfer_memory;
1480 child_ops.to_files_info = child_files_info;
1481 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1482 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1483 child_ops.to_terminal_init = terminal_init_inferior;
1484 child_ops.to_terminal_inferior = terminal_inferior;
1485 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1486 child_ops.to_terminal_ours = terminal_ours;
1487 child_ops.to_terminal_info = child_terminal_info;
1488 child_ops.to_kill = child_kill_inferior;
1489 child_ops.to_load = 0;
1490 child_ops.to_lookup_symbol = 0;
1491 child_ops.to_create_inferior = child_create_inferior;
1492 child_ops.to_mourn_inferior = child_mourn_inferior;
1493 child_ops.to_can_run = child_can_run;
1494 child_ops.to_notice_signals = 0;
1495 child_ops.to_thread_alive = win32_child_thread_alive;
ed9a39eb 1496 child_ops.to_pid_to_str = cygwin_pid_to_str;
c5aa993b
JM
1497 child_ops.to_stop = child_stop;
1498 child_ops.to_stratum = process_stratum;
1499 child_ops.DONT_USE = 0;
1500 child_ops.to_has_all_memory = 1;
1501 child_ops.to_has_memory = 1;
1502 child_ops.to_has_stack = 1;
1503 child_ops.to_has_registers = 1;
1504 child_ops.to_has_execution = 1;
1505 child_ops.to_sections = 0;
1506 child_ops.to_sections_end = 0;
1507 child_ops.to_magic = OPS_MAGIC;
c906108c
SS
1508}
1509
1510void
fba45db2 1511_initialize_inftarg (void)
c906108c 1512{
fa58ee11
EZ
1513 struct cmd_list_element *c;
1514
c5aa993b 1515 init_child_ops ();
c906108c 1516
fa58ee11
EZ
1517 c = add_com ("dll-symbols", class_files, dll_symbol_command,
1518 "Load dll library symbols from FILE.");
1519 c->completer = filename_completer;
450005e7
CF
1520
1521 add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
1522
1523 add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
8e860359
CF
1524 (char *) &new_console,
1525 "Set creation of new console when creating child process.",
1526 &setlist),
1527 &showlist);
c906108c 1528
450005e7 1529 add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
8e860359
CF
1530 (char *) &new_group,
1531 "Set creation of new group when creating child process.",
1532 &setlist),
1533 &showlist);
c906108c 1534
450005e7 1535 add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
8e860359
CF
1536 (char *) &debug_exec,
1537 "Set whether to display execution in child process.",
1538 &setlist),
1539 &showlist);
c906108c 1540
450005e7 1541 add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
8e860359
CF
1542 (char *) &debug_events,
1543 "Set whether to display kernel events in child process.",
1544 &setlist),
1545 &showlist);
c906108c 1546
450005e7 1547 add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
8e860359
CF
1548 (char *) &debug_memory,
1549 "Set whether to display memory accesses in child process.",
1550 &setlist),
1551 &showlist);
c906108c 1552
450005e7 1553 add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
8e860359
CF
1554 (char *) &debug_exceptions,
1555 "Set whether to display kernel exceptions in child process.",
1556 &setlist),
1557 &showlist);
c906108c 1558
450005e7
CF
1559 add_info ("dll", info_dll_command, "Status of loaded DLLs.");
1560 add_info_alias ("sharedlibrary", "dll", 1);
1561
c906108c
SS
1562 add_target (&child_ops);
1563}
1564
1565/* Determine if the thread referenced by "pid" is alive
1566 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
1567 it means that the pid has died. Otherwise it is assumed to be alive. */
1568static int
39f77062 1569win32_child_thread_alive (ptid_t ptid)
c906108c 1570{
39f77062
KB
1571 int pid = PIDGET (ptid);
1572
c5aa993b
JM
1573 return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
1574 FALSE : TRUE;
c906108c
SS
1575}
1576
1577/* Convert pid to printable format. */
1578char *
39f77062 1579cygwin_pid_to_str (ptid_t ptid)
c906108c
SS
1580{
1581 static char buf[80];
39f77062
KB
1582 int pid = PIDGET (ptid);
1583
29fe111d 1584 if ((DWORD) pid == current_event.dwProcessId)
c906108c
SS
1585 sprintf (buf, "process %d", pid);
1586 else
29fe111d 1587 sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
c906108c
SS
1588 return buf;
1589}
8e860359
CF
1590
1591static int
1592core_dll_symbols_add (char *dll_name, DWORD base_addr)
1593{
1594 struct objfile *objfile;
1595 char *objfile_basename;
1596 const char *dll_basename;
1597
1598 if (!(dll_basename = strrchr (dll_name, '/')))
1599 dll_basename = dll_name;
1600 else
1601 dll_basename++;
1602
1603 ALL_OBJFILES (objfile)
1604 {
1605 objfile_basename = strrchr (objfile->name, '/');
1606
1607 if (objfile_basename &&
1608 strcmp (dll_basename, objfile_basename + 1) == 0)
1609 {
1610 printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
1611 base_addr, dll_name);
1612 goto out;
1613 }
1614 }
1615
1616 register_loaded_dll (dll_name, base_addr + 0x1000);
02e423b9 1617 solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
8e860359
CF
1618
1619out:
1620 return 1;
1621}
1622
1623typedef struct
1624{
1625 struct target_ops *target;
1626 bfd_vma addr;
1627}
1628map_code_section_args;
1629
1630static void
554cb486 1631map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
8e860359
CF
1632{
1633 int old;
1634 int update_coreops;
1635 struct section_table *new_target_sect_ptr;
1636
1637 map_code_section_args *args = (map_code_section_args *) obj;
1638 struct target_ops *target = args->target;
1639 if (sect->flags & SEC_CODE)
1640 {
1641 update_coreops = core_ops.to_sections == target->to_sections;
1642
1643 if (target->to_sections)
1644 {
1645 old = target->to_sections_end - target->to_sections;
1646 target->to_sections = (struct section_table *)
1647 xrealloc ((char *) target->to_sections,
1648 (sizeof (struct section_table)) * (1 + old));
1649 }
1650 else
1651 {
1652 old = 0;
1653 target->to_sections = (struct section_table *)
1654 xmalloc ((sizeof (struct section_table)));
1655 }
1656 target->to_sections_end = target->to_sections + (1 + old);
1657
1658 /* Update the to_sections field in the core_ops structure
3bccec63 1659 if needed. */
8e860359
CF
1660 if (update_coreops)
1661 {
1662 core_ops.to_sections = target->to_sections;
1663 core_ops.to_sections_end = target->to_sections_end;
1664 }
1665 new_target_sect_ptr = target->to_sections + old;
1666 new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
1667 new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
1668 bfd_section_size (abfd, sect);;
1669 new_target_sect_ptr->the_bfd_section = sect;
1670 new_target_sect_ptr->bfd = abfd;
1671 }
1672}
1673
1674static int
1675dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
1676{
1677 bfd *dll_bfd;
1678 map_code_section_args map_args;
1679 asection *lowest_sect;
1680 char *name;
1681 if (dll_name == NULL || target == NULL)
1682 return 0;
66ed1d85 1683 name = xstrdup (dll_name);
8e860359
CF
1684 dll_bfd = bfd_openr (name, "pei-i386");
1685 if (dll_bfd == NULL)
1686 return 0;
1687
1688 if (bfd_check_format (dll_bfd, bfd_object))
1689 {
1690 lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
1691 if (lowest_sect == NULL)
1692 return 0;
1693 map_args.target = target;
1694 map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
1695
554cb486 1696 bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
8e860359
CF
1697 }
1698
1699 return 1;
1700}
1701
1702static void
554cb486 1703core_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
8e860359
CF
1704{
1705 struct target_ops *target = (struct target_ops *) obj;
1706
1707 DWORD base_addr;
1708
1709 int dll_name_size;
1710 char *dll_name = NULL;
1711 char *buf = NULL;
1712 struct win32_pstatus *pstatus;
1713 char *p;
1714
1715 if (strncmp (sect->name, ".module", 7))
1716 return;
1717
1718 buf = (char *) xmalloc (sect->_raw_size + 1);
1719 if (!buf)
1720 {
1721 printf_unfiltered ("memory allocation failed for %s\n", sect->name);
1722 goto out;
1723 }
1724 if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size))
1725 goto out;
1726
1727 pstatus = (struct win32_pstatus *) buf;
1728
1729 memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
1730 dll_name_size = pstatus->data.module_info.module_name_size;
1731 if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size)
1732 goto out;
1733
1734 dll_name = (char *) xmalloc (dll_name_size + 1);
1735 if (!dll_name)
1736 {
1737 printf_unfiltered ("memory allocation failed for %s\n", sect->name);
1738 goto out;
1739 }
1740 strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
1741
1742 while ((p = strchr (dll_name, '\\')))
1743 *p = '/';
1744
1745 if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
1746 printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
1747
1748 if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
1749 printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
1750
1751out:
1752 if (buf)
b8c9b27d 1753 xfree (buf);
8e860359 1754 if (dll_name)
b8c9b27d 1755 xfree (dll_name);
8e860359
CF
1756 return;
1757}
1758
1759void
990f9fe3 1760child_solib_add (char *filename ATTRIBUTE_UNUSED, int from_tty, struct target_ops *target, int readsyms)
8e860359 1761{
990f9fe3
FF
1762 if (!readsyms)
1763 return;
8e860359
CF
1764 if (core_bfd)
1765 {
1766 child_clear_solibs ();
1767 bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
1768 }
1769 else
1770 {
1771 if (solib_end && solib_end->name)
d3ff4a77 1772 solib_end->objfile = solib_symbols_add (solib_end->name, from_tty,
3bccec63 1773 solib_end->load_addr);
8e860359
CF
1774 }
1775}
1776
1777static void
1778fetch_elf_core_registers (char *core_reg_sect,
1779 unsigned core_reg_size,
1780 int which,
1781 CORE_ADDR reg_addr)
1782{
1783 int r;
1784 if (core_reg_size < sizeof (CONTEXT))
1785 {
1786 error ("Core file register section too small (%u bytes).", core_reg_size);
1787 return;
1788 }
1789 for (r = 0; r < NUM_REGS; r++)
1790 supply_register (r, core_reg_sect + mappings[r]);
1791}
1792
1793static struct core_fns win32_elf_core_fns =
1794{
1795 bfd_target_elf_flavour,
1796 default_check_format,
1797 default_core_sniffer,
1798 fetch_elf_core_registers,
1799 NULL
1800};
1801
1802void
0613c401 1803_initialize_core_win32 (void)
8e860359
CF
1804{
1805 add_core_fns (&win32_elf_core_fns);
1806}
2a3d5645
CF
1807
1808void
1809_initialize_check_for_gdb_ini (void)
1810{
1811 char *homedir;
1812 if (inhibit_gdbinit)
1813 return;
1814
1815 homedir = getenv ("HOME");
1816 if (homedir)
1817 {
1818 char *p;
1819 char *oldini = (char *) alloca (strlen (homedir) +
1820 sizeof ("/gdb.ini"));
1821 strcpy (oldini, homedir);
1822 p = strchr (oldini, '\0');
1823 if (p > oldini && p[-1] != '/')
1824 *p++ = '/';
1825 strcpy (p, "gdb.ini");
1826 if (access (oldini, 0) == 0)
1827 {
1828 int len = strlen (oldini);
1829 char *newini = alloca (len + 1);
1830 sprintf (newini, "%.*s.gdbinit", len - (sizeof ("gdb.ini") - 1), oldini);
1831 warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini);
1832 }
1833 }
1834}