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