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