2011-09-28 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
CommitLineData
dc05df57 1/* Target-vector operations for controlling windows child processes, for GDB.
0a65a603 2
281b533b 3 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
7b6bb8da 4 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
0a65a603 5
e6433c28 6 Contributed by Cygnus Solutions, A Red Hat Company.
e88c49c3 7
24e60978
SC
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
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
24e60978
SC
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
a9762ec7 16 but WITHOUT ANY WARRANTY; without even the implied warranty of
24e60978
SC
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
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24e60978 22
dfe7f3ac 23/* Originally by Steve Chamberlain, sac@cygnus.com */
24e60978
SC
24
25#include "defs.h"
26#include "frame.h" /* required by inferior.h */
27#include "inferior.h"
28#include "target.h"
60250e8b 29#include "exceptions.h"
24e60978
SC
30#include "gdbcore.h"
31#include "command.h"
fa58ee11 32#include "completer.h"
4e052eda 33#include "regcache.h"
2a3d5645 34#include "top.h"
403d9909
CF
35#include <signal.h>
36#include <sys/types.h>
37#include <fcntl.h>
38#include <stdlib.h>
39#include <windows.h>
40#include <imagehlp.h>
2b008701 41#include <psapi.h>
10325bc5 42#ifdef __CYGWIN__
403d9909 43#include <sys/cygwin.h>
10325bc5 44#endif
a244bdca 45#include <signal.h>
cad9cd60 46
24e60978 47#include "buildsym.h"
0ba1096a 48#include "filenames.h"
1ef980b9
SC
49#include "symfile.h"
50#include "objfiles.h"
de1b3c3d 51#include "gdb_obstack.h"
24e60978 52#include "gdb_string.h"
fdfa3315 53#include "gdbthread.h"
24e60978 54#include "gdbcmd.h"
1750a5ef 55#include <sys/param.h>
1e37c281 56#include <unistd.h>
4646aa9d 57#include "exec.h"
3ee6f623 58#include "solist.h"
3cb8e7f6 59#include "solib.h"
de1b3c3d 60#include "xml-support.h"
24e60978 61
6c7de422
MK
62#include "i386-tdep.h"
63#include "i387-tdep.h"
64
31b060a2
CF
65#include "windows-tdep.h"
66#include "windows-nat.h"
9bb9e8ad 67#include "i386-nat.h"
ecc13e53 68#include "complaints.h"
de1b3c3d 69
418c6cb3 70#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
2b008701
CF
71#define DebugActiveProcessStop dyn_DebugActiveProcessStop
72#define DebugBreakProcess dyn_DebugBreakProcess
73#define DebugSetProcessKillOnExit dyn_DebugSetProcessKillOnExit
74#define EnumProcessModules dyn_EnumProcessModules
2b008701 75#define GetModuleInformation dyn_GetModuleInformation
418c6cb3
CF
76#define LookupPrivilegeValueA dyn_LookupPrivilegeValueA
77#define OpenProcessToken dyn_OpenProcessToken
cd44747c
PM
78#define GetConsoleFontSize dyn_GetConsoleFontSize
79#define GetCurrentConsoleFont dyn_GetCurrentConsoleFont
2b008701 80
418c6cb3
CF
81static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
82 DWORD, PTOKEN_PRIVILEGES, PDWORD);
2b008701
CF
83static BOOL WINAPI (*DebugActiveProcessStop) (DWORD);
84static BOOL WINAPI (*DebugBreakProcess) (HANDLE);
85static BOOL WINAPI (*DebugSetProcessKillOnExit) (BOOL);
86static BOOL WINAPI (*EnumProcessModules) (HANDLE, HMODULE *, DWORD,
87 LPDWORD);
2b008701
CF
88static BOOL WINAPI (*GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
89 DWORD);
418c6cb3
CF
90static BOOL WINAPI (*LookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
91static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
581e13c1
MS
92static BOOL WINAPI (*GetCurrentConsoleFont) (HANDLE, BOOL,
93 CONSOLE_FONT_INFO *);
cd44747c 94static COORD WINAPI (*GetConsoleFontSize) (HANDLE, DWORD);
2b008701 95
dc05df57 96static struct target_ops windows_ops;
3ee6f623 97
b3c613f2
CF
98#undef STARTUPINFO
99#undef CreateProcess
100#undef GetModuleFileNameEx
101
102#ifndef __CYGWIN__
103# define __PMAX (MAX_PATH + 1)
104 static DWORD WINAPI (*GetModuleFileNameEx) (HANDLE, HMODULE, LPSTR, DWORD);
105# define STARTUPINFO STARTUPINFOA
106# define CreateProcess CreateProcessA
107# define GetModuleFileNameEx_name "GetModuleFileNameExA"
108# define bad_GetModuleFileNameEx bad_GetModuleFileNameExA
109#else
110# define __PMAX PATH_MAX
581e13c1 111/* The starting and ending address of the cygwin1.dll text segment. */
b3c613f2
CF
112 static CORE_ADDR cygwin_load_start;
113 static CORE_ADDR cygwin_load_end;
b3c613f2
CF
114# define __USEWIDE
115 typedef wchar_t cygwin_buf_t;
581e13c1
MS
116 static DWORD WINAPI (*GetModuleFileNameEx) (HANDLE, HMODULE,
117 LPWSTR, DWORD);
b3c613f2
CF
118# define STARTUPINFO STARTUPINFOW
119# define CreateProcess CreateProcessW
120# define GetModuleFileNameEx_name "GetModuleFileNameExW"
121# define bad_GetModuleFileNameEx bad_GetModuleFileNameExW
10325bc5 122#endif
a244bdca 123
581e13c1
MS
124static int have_saved_context; /* True if we've saved context from a
125 cygwin signal. */
126static CONTEXT saved_context; /* Containes the saved context from a
127 cygwin signal. */
a244bdca 128
0714f9bf
SS
129/* If we're not using the old Cygwin header file set, define the
130 following which never should have been in the generic Win32 API
581e13c1 131 headers in the first place since they were our own invention... */
0714f9bf 132#ifndef _GNU_H_WINDOWS_H
9d3789f7 133enum
8e860359
CF
134 {
135 FLAG_TRACE_BIT = 0x100,
136 CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
137 };
0714f9bf
SS
138#endif
139
5851ab76
JB
140#ifndef CONTEXT_EXTENDED_REGISTERS
141/* This macro is only defined on ia32. It only makes sense on this target,
142 so define it as zero if not already defined. */
143#define CONTEXT_EXTENDED_REGISTERS 0
144#endif
145
fa4ba8da
PM
146#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
147 | CONTEXT_EXTENDED_REGISTERS
97da3b20 148
41b4aadc 149static uintptr_t dr[8];
87a45c96
CF
150static int debug_registers_changed;
151static int debug_registers_used;
16d905e2
CF
152
153static int windows_initialization_done;
6537bb24 154#define DR6_CLEAR_VALUE 0xffff0ff0
97da3b20 155
3cee93ac 156/* The string sent by cygwin when it processes a signal.
581e13c1 157 FIXME: This should be in a cygwin include file. */
3929abe9
CF
158#ifndef _CYGWIN_SIGNAL_STRING
159#define _CYGWIN_SIGNAL_STRING "cYgSiGw00f"
160#endif
3cee93ac 161
29fe111d 162#define CHECK(x) check (x, __FILE__,__LINE__)
dfe7f3ac 163#define DEBUG_EXEC(x) if (debug_exec) printf_unfiltered x
4e52d31c
PM
164#define DEBUG_EVENTS(x) if (debug_events) printf_unfiltered x
165#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x
166#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x
24e60978 167
dc05df57 168static void windows_stop (ptid_t);
02529b48 169static int windows_thread_alive (struct target_ops *, ptid_t);
7d85a9c0 170static void windows_kill_inferior (struct target_ops *);
3cee93ac 171
9bb9e8ad
PM
172static void cygwin_set_dr (int i, CORE_ADDR addr);
173static void cygwin_set_dr7 (unsigned long val);
174static unsigned long cygwin_get_dr6 (void);
175
7393af7c 176static enum target_signal last_sig = TARGET_SIGNAL_0;
581e13c1 177/* Set if a signal was received from the debugged process. */
7393af7c 178
3cee93ac 179/* Thread information structure used to track information that is
6537bb24 180 not available in gdb's thread structure. */
3cee93ac 181typedef struct thread_info_struct
3a4b77d8
JM
182 {
183 struct thread_info_struct *next;
184 DWORD id;
185 HANDLE h;
711e434b 186 CORE_ADDR thread_local_base;
3a4b77d8 187 char *name;
6537bb24 188 int suspended;
3ade5333 189 int reload_context;
3a4b77d8 190 CONTEXT context;
1e37c281 191 STACKFRAME sf;
8e860359
CF
192 }
193thread_info;
1e37c281 194
29fe111d 195static thread_info thread_head;
24e60978 196
581e13c1 197/* The process and thread handles for the above context. */
24e60978 198
3cee93ac
CF
199static DEBUG_EVENT current_event; /* The current debug event from
200 WaitForDebugEvent */
201static HANDLE current_process_handle; /* Currently executing process */
202static thread_info *current_thread; /* Info on currently selected thread */
349b409f 203static DWORD main_thread_id; /* Thread ID of the main thread */
24e60978 204
581e13c1 205/* Counts of things. */
24e60978
SC
206static int exception_count = 0;
207static int event_count = 0;
dfe7f3ac 208static int saw_create;
bf25528d 209static int open_process_used = 0;
24e60978 210
581e13c1 211/* User options. */
24e60978 212static int new_console = 0;
10325bc5 213#ifdef __CYGWIN__
09280ddf 214static int cygwin_exceptions = 0;
10325bc5 215#endif
1e37c281 216static int new_group = 1;
dfe7f3ac
CF
217static int debug_exec = 0; /* show execution */
218static int debug_events = 0; /* show events from kernel */
219static int debug_memory = 0; /* show target memory accesses */
1ef980b9 220static int debug_exceptions = 0; /* show target exceptions */
dfe7f3ac
CF
221static int useshell = 0; /* use shell for subprocesses */
222
7e63b4e4 223/* This vector maps GDB's idea of a register's number into an offset
dc05df57 224 in the windows exception context vector.
24e60978 225
3cee93ac 226 It also contains the bit mask needed to load the register in question.
24e60978 227
7e63b4e4
JB
228 The contents of this table can only be computed by the units
229 that provide CPU-specific support for Windows native debugging.
230 These units should set the table by calling
dc05df57 231 windows_set_context_register_offsets.
7e63b4e4 232
24e60978
SC
233 One day we could read a reg, we could inspect the context we
234 already have loaded, if it doesn't have the bit set that we need,
235 we read that set of registers in using GetThreadContext. If the
581e13c1 236 context already contains what we need, we just unpack it. Then to
24e60978
SC
237 write a register, first we have to ensure that the context contains
238 the other regs of the group, and then we copy the info in and set
581e13c1 239 out bit. */
24e60978 240
7e63b4e4 241static const int *mappings;
d3a09475 242
24e60978 243/* This vector maps the target's idea of an exception (extracted
581e13c1 244 from the DEBUG_EVENT structure) to GDB's idea. */
24e60978
SC
245
246struct xlate_exception
247 {
248 int them;
249 enum target_signal us;
250 };
251
24e60978
SC
252static const struct xlate_exception
253 xlate[] =
254{
255 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 256 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
257 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
258 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
259 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
7393af7c 260 {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE},
24e60978
SC
261 {-1, -1}};
262
7e63b4e4
JB
263/* Set the MAPPINGS static global to OFFSETS.
264 See the description of MAPPINGS for more details. */
265
266void
dc05df57 267windows_set_context_register_offsets (const int *offsets)
7e63b4e4
JB
268{
269 mappings = offsets;
270}
271
fa4ba8da
PM
272static void
273check (BOOL ok, const char *file, int line)
274{
275 if (!ok)
dfe7f3ac 276 printf_filtered ("error return %s:%d was %lu\n", file, line,
fa4ba8da
PM
277 GetLastError ());
278}
279
6537bb24
PA
280/* Find a thread record given a thread id. If GET_CONTEXT is not 0,
281 then also retrieve the context for this thread. If GET_CONTEXT is
282 negative, then don't suspend the thread. */
3cee93ac
CF
283static thread_info *
284thread_rec (DWORD id, int get_context)
24e60978 285{
3cee93ac
CF
286 thread_info *th;
287
3a4b77d8 288 for (th = &thread_head; (th = th->next) != NULL;)
3cee93ac
CF
289 if (th->id == id)
290 {
6537bb24 291 if (!th->suspended && get_context)
3cee93ac 292 {
8a892701 293 if (get_context > 0 && id != current_event.dwThreadId)
6537bb24
PA
294 {
295 if (SuspendThread (th->h) == (DWORD) -1)
296 {
297 DWORD err = GetLastError ();
298 warning (_("SuspendThread failed. (winerr %d)"),
299 (int) err);
300 return NULL;
301 }
302 th->suspended = 1;
303 }
3cee93ac 304 else if (get_context < 0)
6537bb24 305 th->suspended = -1;
3ade5333 306 th->reload_context = 1;
3cee93ac
CF
307 }
308 return th;
309 }
310
311 return NULL;
312}
313
2dc38344 314/* Add a thread to the thread list. */
3cee93ac 315static thread_info *
711e434b 316windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
3cee93ac
CF
317{
318 thread_info *th;
2dc38344
PA
319 DWORD id;
320
321 gdb_assert (ptid_get_tid (ptid) != 0);
322
323 id = ptid_get_tid (ptid);
3cee93ac
CF
324
325 if ((th = thread_rec (id, FALSE)))
326 return th;
327
3929abe9 328 th = XZALLOC (thread_info);
3cee93ac
CF
329 th->id = id;
330 th->h = h;
711e434b 331 th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
3cee93ac
CF
332 th->next = thread_head.next;
333 thread_head.next = th;
2dc38344
PA
334 add_thread (ptid);
335 /* Set the debug registers for the new thread if they are used. */
fa4ba8da
PM
336 if (debug_registers_used)
337 {
338 /* Only change the value of the debug registers. */
339 th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
340 CHECK (GetThreadContext (th->h, &th->context));
341 th->context.Dr0 = dr[0];
342 th->context.Dr1 = dr[1];
343 th->context.Dr2 = dr[2];
344 th->context.Dr3 = dr[3];
6537bb24 345 th->context.Dr6 = DR6_CLEAR_VALUE;
fa4ba8da
PM
346 th->context.Dr7 = dr[7];
347 CHECK (SetThreadContext (th->h, &th->context));
348 th->context.ContextFlags = 0;
349 }
3cee93ac 350 return th;
24e60978
SC
351}
352
3cee93ac 353/* Clear out any old thread list and reintialize it to a
581e13c1 354 pristine state. */
24e60978 355static void
dc05df57 356windows_init_thread_list (void)
24e60978 357{
3cee93ac
CF
358 thread_info *th = &thread_head;
359
dc05df57 360 DEBUG_EVENTS (("gdb: windows_init_thread_list\n"));
3cee93ac
CF
361 init_thread_list ();
362 while (th->next != NULL)
24e60978 363 {
3cee93ac
CF
364 thread_info *here = th->next;
365 th->next = here->next;
b8c9b27d 366 xfree (here);
24e60978 367 }
059198c1 368 thread_head.next = NULL;
3cee93ac
CF
369}
370
581e13c1 371/* Delete a thread from the list of threads. */
3cee93ac 372static void
dc05df57 373windows_delete_thread (ptid_t ptid)
3cee93ac
CF
374{
375 thread_info *th;
2dc38344
PA
376 DWORD id;
377
378 gdb_assert (ptid_get_tid (ptid) != 0);
379
380 id = ptid_get_tid (ptid);
3cee93ac
CF
381
382 if (info_verbose)
2dc38344
PA
383 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
384 delete_thread (ptid);
3cee93ac
CF
385
386 for (th = &thread_head;
387 th->next != NULL && th->next->id != id;
388 th = th->next)
389 continue;
390
391 if (th->next != NULL)
24e60978 392 {
3cee93ac
CF
393 thread_info *here = th->next;
394 th->next = here->next;
b8c9b27d 395 xfree (here);
24e60978
SC
396 }
397}
398
3cee93ac 399static void
dc05df57 400do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
24e60978 401{
1e37c281 402 char *context_offset = ((char *) &current_thread->context) + mappings[r];
20a6ec49
MD
403 struct gdbarch *gdbarch = get_regcache_arch (regcache);
404 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1e37c281 405 long l;
6c7de422 406
3ade5333 407 if (!current_thread)
d6dc8049 408 return; /* Windows sometimes uses a non-existent thread id in its
581e13c1 409 events. */
3ade5333
CF
410
411 if (current_thread->reload_context)
412 {
cb832706 413#ifdef __COPY_CONTEXT_SIZE
a244bdca
CF
414 if (have_saved_context)
415 {
581e13c1
MS
416 /* Lie about where the program actually is stopped since
417 cygwin has informed us that we should consider the signal
418 to have occurred at another location which is stored in
419 "saved_context. */
420 memcpy (&current_thread->context, &saved_context,
421 __COPY_CONTEXT_SIZE);
a244bdca
CF
422 have_saved_context = 0;
423 }
424 else
cb832706 425#endif
a244bdca
CF
426 {
427 thread_info *th = current_thread;
428 th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
429 GetThreadContext (th->h, &th->context);
2b008701 430 /* Copy dr values from that thread.
581e13c1
MS
431 But only if there were not modified since last stop.
432 PR gdb/2388 */
88616312
PM
433 if (!debug_registers_changed)
434 {
435 dr[0] = th->context.Dr0;
436 dr[1] = th->context.Dr1;
437 dr[2] = th->context.Dr2;
438 dr[3] = th->context.Dr3;
439 dr[6] = th->context.Dr6;
440 dr[7] = th->context.Dr7;
441 }
a244bdca 442 }
3ade5333
CF
443 current_thread->reload_context = 0;
444 }
445
20a6ec49 446 if (r == I387_FISEG_REGNUM (tdep))
1e37c281 447 {
8e860359 448 l = *((long *) context_offset) & 0xffff;
56be3814 449 regcache_raw_supply (regcache, r, (char *) &l);
1e37c281 450 }
20a6ec49 451 else if (r == I387_FOP_REGNUM (tdep))
1e37c281 452 {
8e860359 453 l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
56be3814 454 regcache_raw_supply (regcache, r, (char *) &l);
1e37c281
JM
455 }
456 else if (r >= 0)
56be3814 457 regcache_raw_supply (regcache, r, context_offset);
3cee93ac 458 else
24e60978 459 {
20a6ec49 460 for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
dc05df57 461 do_windows_fetch_inferior_registers (regcache, r);
24e60978 462 }
3cee93ac
CF
463}
464
465static void
28439f5e
PA
466windows_fetch_inferior_registers (struct target_ops *ops,
467 struct regcache *regcache, int r)
3cee93ac 468{
2dc38344 469 current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
d6dc8049 470 /* Check if current_thread exists. Windows sometimes uses a non-existent
581e13c1 471 thread id in its events. */
3ade5333 472 if (current_thread)
dc05df57 473 do_windows_fetch_inferior_registers (regcache, r);
3cee93ac
CF
474}
475
476static void
dc05df57 477do_windows_store_inferior_registers (const struct regcache *regcache, int r)
3cee93ac 478{
3ade5333 479 if (!current_thread)
581e13c1 480 /* Windows sometimes uses a non-existent thread id in its events. */;
3ade5333 481 else if (r >= 0)
56be3814 482 regcache_raw_collect (regcache, r,
822c9732 483 ((char *) &current_thread->context) + mappings[r]);
24e60978
SC
484 else
485 {
40a6adc1 486 for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
dc05df57 487 do_windows_store_inferior_registers (regcache, r);
24e60978
SC
488 }
489}
490
581e13c1 491/* Store a new register value into the current thread context. */
3cee93ac 492static void
28439f5e
PA
493windows_store_inferior_registers (struct target_ops *ops,
494 struct regcache *regcache, int r)
3cee93ac 495{
2dc38344 496 current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
d6dc8049 497 /* Check if current_thread exists. Windows sometimes uses a non-existent
581e13c1 498 thread id in its events. */
3ade5333 499 if (current_thread)
dc05df57 500 do_windows_store_inferior_registers (regcache, r);
3cee93ac 501}
24e60978 502
7a9dd1b2 503/* Get the name of a given module at given base address. If base_address
33605d39
CF
504 is zero return the first loaded module (which is always the name of the
505 executable). */
3ee6f623 506static int
d3653bf6 507get_module_name (LPVOID base_address, char *dll_name_ret)
1e37c281
JM
508{
509 DWORD len;
510 MODULEINFO mi;
511 int i;
8e860359 512 HMODULE dh_buf[1];
581e13c1
MS
513 HMODULE *DllHandle = dh_buf; /* Set to temporary storage for
514 initial query. */
1e37c281 515 DWORD cbNeeded;
33605d39 516#ifdef __CYGWIN__
b3c613f2
CF
517 cygwin_buf_t pathbuf[__PMAX]; /* Temporary storage prior to converting to
518 posix form. __PMAX is always enough
d0d0ab16 519 as long as SO_NAME_MAX_PATH_SIZE is defined
581e13c1 520 as 512. */
33605d39 521#endif
1e37c281 522
1e37c281 523 cbNeeded = 0;
581e13c1
MS
524 /* Find size of buffer needed to handle list of modules loaded in
525 inferior. */
2b008701
CF
526 if (!EnumProcessModules (current_process_handle, DllHandle,
527 sizeof (HMODULE), &cbNeeded) || !cbNeeded)
1e37c281
JM
528 goto failed;
529
581e13c1 530 /* Allocate correct amount of space for module list. */
8e860359 531 DllHandle = (HMODULE *) alloca (cbNeeded);
1e37c281
JM
532 if (!DllHandle)
533 goto failed;
534
581e13c1 535 /* Get the list of modules. */
2b008701 536 if (!EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
33605d39 537 &cbNeeded))
1e37c281
JM
538 goto failed;
539
29fe111d 540 for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
1e37c281 541 {
581e13c1 542 /* Get information on this module. */
2b008701
CF
543 if (!GetModuleInformation (current_process_handle, DllHandle[i],
544 &mi, sizeof (mi)))
8a3fe4f8 545 error (_("Can't get module info"));
1e37c281 546
d3653bf6 547 if (!base_address || mi.lpBaseOfDll == base_address)
33605d39 548 {
581e13c1 549 /* Try to find the name of the given module. */
d0d0ab16 550#ifdef __CYGWIN__
581e13c1 551 /* Cygwin prefers that the path be in /x/y/z format. */
b3c613f2
CF
552 len = GetModuleFileNameEx (current_process_handle,
553 DllHandle[i], pathbuf, __PMAX);
d0d0ab16
CV
554 if (len == 0)
555 error (_("Error getting dll name: %lu."), GetLastError ());
556 if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, dll_name_ret,
b3c613f2 557 __PMAX) < 0)
d0d0ab16
CV
558 error (_("Error converting dll name to POSIX: %d."), errno);
559#else
b3c613f2
CF
560 len = GetModuleFileNameEx (current_process_handle,
561 DllHandle[i], dll_name_ret, __PMAX);
33605d39 562 if (len == 0)
581e13c1
MS
563 error (_("Error getting dll name: %u."),
564 (unsigned) GetLastError ());
33605d39
CF
565#endif
566 return 1; /* success */
567 }
1e37c281
JM
568 }
569
570failed:
571 dll_name_ret[0] = '\0';
33605d39 572 return 0; /* failure */
1e37c281
JM
573}
574
450005e7 575/* Encapsulate the information required in a call to
581e13c1 576 symbol_file_add_args. */
8a892701
CF
577struct safe_symbol_file_add_args
578{
579 char *name;
580 int from_tty;
581 struct section_addr_info *addrs;
582 int mainline;
583 int flags;
7c5c87c0 584 struct ui_file *err, *out;
8a892701
CF
585 struct objfile *ret;
586};
587
581e13c1 588/* Maintain a linked list of "so" information. */
3ee6f623 589struct lm_info
02e423b9 590{
d3653bf6 591 LPVOID load_addr;
3ee6f623
CF
592};
593
594static struct so_list solib_start, *solib_end;
02e423b9 595
450005e7 596/* Call symbol_file_add with stderr redirected. We don't care if there
581e13c1 597 are errors. */
8a892701
CF
598static int
599safe_symbol_file_add_stub (void *argv)
600{
3ee6f623 601#define p ((struct safe_symbol_file_add_args *) argv)
7eedccfa
PP
602 const int add_flags = ((p->from_tty ? SYMFILE_VERBOSE : 0)
603 | (p->mainline ? SYMFILE_MAINLINE : 0));
604 p->ret = symbol_file_add (p->name, add_flags, p->addrs, p->flags);
8a892701
CF
605 return !!p->ret;
606#undef p
607}
608
581e13c1 609/* Restore gdb's stderr after calling symbol_file_add. */
8a892701 610static void
7c5c87c0 611safe_symbol_file_add_cleanup (void *p)
8a892701 612{
8e860359 613#define sp ((struct safe_symbol_file_add_args *)p)
450005e7 614 gdb_flush (gdb_stderr);
7c5c87c0 615 gdb_flush (gdb_stdout);
d3ff4a77 616 ui_file_delete (gdb_stderr);
7c5c87c0 617 ui_file_delete (gdb_stdout);
d3ff4a77 618 gdb_stderr = sp->err;
9d3789f7 619 gdb_stdout = sp->out;
8e860359 620#undef sp
8a892701
CF
621}
622
581e13c1 623/* symbol_file_add wrapper that prevents errors from being displayed. */
8a892701
CF
624static struct objfile *
625safe_symbol_file_add (char *name, int from_tty,
626 struct section_addr_info *addrs,
627 int mainline, int flags)
8a892701
CF
628{
629 struct safe_symbol_file_add_args p;
630 struct cleanup *cleanup;
631
7c5c87c0 632 cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
8a892701 633
7c5c87c0
CF
634 p.err = gdb_stderr;
635 p.out = gdb_stdout;
450005e7 636 gdb_flush (gdb_stderr);
7c5c87c0 637 gdb_flush (gdb_stdout);
d3ff4a77 638 gdb_stderr = ui_file_new ();
7c5c87c0 639 gdb_stdout = ui_file_new ();
8a892701
CF
640 p.name = name;
641 p.from_tty = from_tty;
642 p.addrs = addrs;
643 p.mainline = mainline;
644 p.flags = flags;
645 catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
646
647 do_cleanups (cleanup);
648 return p.ret;
649}
650
de1b3c3d 651static struct so_list *
dc05df57 652windows_make_so (const char *name, LPVOID load_addr)
8e860359 653{
3ee6f623 654 struct so_list *so;
d0d0ab16
CV
655 char *p;
656#ifndef __CYGWIN__
b3c613f2
CF
657 char buf[__PMAX];
658 char cwd[__PMAX];
3f8ad85b
CF
659 WIN32_FIND_DATA w32_fd;
660 HANDLE h = FindFirstFile(name, &w32_fd);
3f8ad85b 661
6badb179
CF
662 if (h == INVALID_HANDLE_VALUE)
663 strcpy (buf, name);
664 else
3f8ad85b 665 {
c914e0cc
CF
666 FindClose (h);
667 strcpy (buf, name);
668 if (GetCurrentDirectory (MAX_PATH + 1, cwd))
669 {
670 p = strrchr (buf, '\\');
671 if (p)
672 p[1] = '\0';
673 SetCurrentDirectory (buf);
674 GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p);
675 SetCurrentDirectory (cwd);
676 }
3f8ad85b 677 }
3ee6f623
CF
678 if (strcasecmp (buf, "ntdll.dll") == 0)
679 {
680 GetSystemDirectory (buf, sizeof (buf));
681 strcat (buf, "\\ntdll.dll");
682 }
d0d0ab16 683#else
b3c613f2 684 cygwin_buf_t buf[__PMAX];
d0d0ab16 685
b3c613f2 686 buf[0] = 0;
d0d0ab16
CV
687 if (access (name, F_OK) != 0)
688 {
689 if (strcasecmp (name, "ntdll.dll") == 0)
b3c613f2 690#ifdef __USEWIDE
d0d0ab16
CV
691 {
692 GetSystemDirectoryW (buf, sizeof (buf) / sizeof (wchar_t));
693 wcscat (buf, L"\\ntdll.dll");
694 }
b3c613f2
CF
695#else
696 {
697 GetSystemDirectoryA (buf, sizeof (buf) / sizeof (wchar_t));
698 strcat (buf, "\\ntdll.dll");
699 }
700#endif
d0d0ab16
CV
701 }
702#endif
3929abe9 703 so = XZALLOC (struct so_list);
3ee6f623
CF
704 so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
705 so->lm_info->load_addr = load_addr;
de1b3c3d 706 strcpy (so->so_original_name, name);
10325bc5
PA
707#ifndef __CYGWIN__
708 strcpy (so->so_name, buf);
709#else
d0d0ab16
CV
710 if (buf[0])
711 cygwin_conv_path (CCP_WIN_W_TO_POSIX, buf, so->so_name,
712 SO_NAME_MAX_PATH_SIZE);
713 else
714 {
60c5c021 715 char *rname = realpath (name, NULL);
d0d0ab16
CV
716 if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
717 {
718 strcpy (so->so_name, rname);
719 free (rname);
720 }
721 else
722 error (_("dll path too long"));
723 }
de1b3c3d
PA
724 /* Record cygwin1.dll .text start/end. */
725 p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
726 if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
727 {
728 bfd *abfd;
729 asection *text = NULL;
730 CORE_ADDR text_vma;
8e860359 731
610dd7f9 732 abfd = bfd_openr (so->so_name, "pei-i386");
a244bdca 733
de1b3c3d
PA
734 if (!abfd)
735 return so;
736
737 if (bfd_check_format (abfd, bfd_object))
738 text = bfd_get_section_by_name (abfd, ".text");
739
740 if (!text)
741 {
742 bfd_close (abfd);
743 return so;
744 }
745
7a9dd1b2 746 /* The symbols in a dll are offset by 0x1000, which is the
de1b3c3d 747 offset from 0 of the first byte in an image - because of the
581e13c1
MS
748 file header and the section alignment. */
749 cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
750 load_addr + 0x1000);
dc05df57 751 cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
de1b3c3d
PA
752
753 bfd_close (abfd);
754 }
10325bc5 755#endif
de1b3c3d
PA
756
757 return so;
8e860359
CF
758}
759
3ee6f623 760static char *
dfe7f3ac
CF
761get_image_name (HANDLE h, void *address, int unicode)
762{
d0d0ab16 763#ifdef __CYGWIN__
b3c613f2 764 static char buf[__PMAX];
d0d0ab16 765#else
b3c613f2 766 static char buf[(2 * __PMAX) + 1];
d0d0ab16 767#endif
dfe7f3ac
CF
768 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
769 char *address_ptr;
770 int len = 0;
771 char b[2];
5732a500 772 SIZE_T done;
dfe7f3ac
CF
773
774 /* Attempt to read the name of the dll that was detected.
775 This is documented to work only when actively debugging
581e13c1 776 a program. It will not work for attached processes. */
dfe7f3ac
CF
777 if (address == NULL)
778 return NULL;
779
dfe7f3ac 780 /* See if we could read the address of a string, and that the
581e13c1
MS
781 address isn't null. */
782 if (!ReadProcessMemory (h, address, &address_ptr,
783 sizeof (address_ptr), &done)
6f17862b 784 || done != sizeof (address_ptr) || !address_ptr)
dfe7f3ac
CF
785 return NULL;
786
581e13c1 787 /* Find the length of the string. */
6f17862b
CF
788 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
789 && (b[0] != 0 || b[size - 1] != 0) && done == size)
790 continue;
dfe7f3ac
CF
791
792 if (!unicode)
793 ReadProcessMemory (h, address_ptr, buf, len, &done);
794 else
795 {
796 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
797 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
798 &done);
d0d0ab16 799#ifdef __CYGWIN__
b3c613f2 800 wcstombs (buf, unicode_address, __PMAX);
d0d0ab16
CV
801#else
802 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
803 0, 0);
804#endif
dfe7f3ac
CF
805 }
806
807 return buf;
808}
809
24e60978
SC
810/* Wait for child to do something. Return pid of child, or -1 in case
811 of error; store status through argument pointer OURSTATUS. */
1750a5ef 812static int
0a65a603 813handle_load_dll (void *dummy)
24e60978 814{
3a4b77d8 815 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
b3c613f2 816 char dll_buf[__PMAX];
450005e7 817 char *dll_name = NULL;
3cee93ac 818
3a4b77d8 819 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
3cee93ac 820
d3653bf6 821 if (!get_module_name (event->lpBaseOfDll, dll_buf))
8e860359 822 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
3cee93ac 823
1e37c281 824 dll_name = dll_buf;
24e60978 825
dfe7f3ac 826 if (*dll_name == '\0')
de1b3c3d
PA
827 dll_name = get_image_name (current_process_handle,
828 event->lpImageName, event->fUnicode);
3cee93ac
CF
829 if (!dll_name)
830 return 1;
831
dc05df57 832 solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
de1b3c3d 833 solib_end = solib_end->next;
450005e7 834
a74ce742
PM
835 DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
836 host_address_to_string (solib_end->lm_info->load_addr)));
7488902c 837
450005e7
CF
838 return 1;
839}
840
3ee6f623 841static void
dc05df57 842windows_free_so (struct so_list *so)
3ee6f623 843{
3ee6f623
CF
844 if (so->lm_info)
845 xfree (so->lm_info);
de1b3c3d 846 xfree (so);
3cb8e7f6
CF
847}
848
d3ff4a77 849static int
0a65a603 850handle_unload_dll (void *dummy)
d3ff4a77 851{
d3653bf6 852 LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
3ee6f623 853 struct so_list *so;
d3ff4a77
CF
854
855 for (so = &solib_start; so->next != NULL; so = so->next)
3ee6f623 856 if (so->next->lm_info->load_addr == lpBaseOfDll)
d3ff4a77 857 {
3ee6f623 858 struct so_list *sodel = so->next;
d3ff4a77
CF
859 so->next = sodel->next;
860 if (!so->next)
861 solib_end = so;
7488902c
PM
862 DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
863
dc05df57 864 windows_free_so (sodel);
3929abe9 865 solib_add (NULL, 0, NULL, auto_solib_add);
d3ff4a77
CF
866 return 1;
867 }
3929abe9 868
ecc13e53
JB
869 /* We did not find any DLL that was previously loaded at this address,
870 so register a complaint. We do not report an error, because we have
871 observed that this may be happening under some circumstances. For
872 instance, running 32bit applications on x64 Windows causes us to receive
873 4 mysterious UNLOAD_DLL_DEBUG_EVENTs during the startup phase (these
874 events are apparently caused by the WOW layer, the interface between
875 32bit and 64bit worlds). */
876 complaint (&symfile_complaints, _("dll starting at %s not found."),
877 host_address_to_string (lpBaseOfDll));
d3ff4a77
CF
878
879 return 0;
880}
881
581e13c1 882/* Clear list of loaded DLLs. */
3ee6f623 883static void
dc05df57 884windows_clear_solib (void)
450005e7 885{
450005e7
CF
886 solib_start.next = NULL;
887 solib_end = &solib_start;
450005e7 888}
295732ea 889
581e13c1 890/* Load DLL symbol info. */
450005e7 891void
7470a420 892dll_symbol_command (char *args, int from_tty)
450005e7 893{
8e860359 894 int n;
450005e7 895 dont_repeat ();
8e860359 896
450005e7 897 if (args == NULL)
8a3fe4f8 898 error (_("dll-symbols requires a file name"));
450005e7 899
8e860359
CF
900 n = strlen (args);
901 if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
902 {
903 char *newargs = (char *) alloca (n + 4 + 1);
904 strcpy (newargs, args);
905 strcat (newargs, ".dll");
906 args = newargs;
907 }
908
7470a420 909 safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
8e860359 910}
450005e7 911
3cee93ac
CF
912/* Handle DEBUG_STRING output from child process.
913 Cygwin prepends its messages with a "cygwin:". Interpret this as
581e13c1 914 a Cygwin signal. Otherwise just print the string as a warning. */
3cee93ac
CF
915static int
916handle_output_debug_string (struct target_waitstatus *ourstatus)
917{
a244bdca
CF
918 char *s = NULL;
919 int retval = 0;
3cee93ac
CF
920
921 if (!target_read_string
2c647436
PM
922 ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
923 &s, 1024, 0)
3cee93ac 924 || !s || !*s)
a244bdca 925 /* nothing to do */;
581e13c1
MS
926 else if (strncmp (s, _CYGWIN_SIGNAL_STRING,
927 sizeof (_CYGWIN_SIGNAL_STRING) - 1) != 0)
3cee93ac 928 {
10325bc5 929#ifdef __CYGWIN__
d3a09475 930 if (strncmp (s, "cYg", 3) != 0)
10325bc5 931#endif
8a3fe4f8 932 warning (("%s"), s);
3cee93ac 933 }
cb832706 934#ifdef __COPY_CONTEXT_SIZE
d3a09475 935 else
3cee93ac 936 {
581e13c1
MS
937 /* Got a cygwin signal marker. A cygwin signal is followed by
938 the signal number itself and then optionally followed by the
939 thread id and address to saved context within the DLL. If
940 these are supplied, then the given thread is assumed to have
941 issued the signal and the context from the thread is assumed
942 to be stored at the given address in the inferior. Tell gdb
943 to treat this like a real signal. */
3cee93ac 944 char *p;
3929abe9 945 int sig = strtol (s + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
a244bdca 946 int gotasig = target_signal_from_host (sig);
0714f9bf
SS
947 ourstatus->value.sig = gotasig;
948 if (gotasig)
a244bdca
CF
949 {
950 LPCVOID x;
951 DWORD n;
952 ourstatus->kind = TARGET_WAITKIND_STOPPED;
953 retval = strtoul (p, &p, 0);
954 if (!retval)
955 retval = main_thread_id;
956 else if ((x = (LPCVOID) strtoul (p, &p, 0))
957 && ReadProcessMemory (current_process_handle, x,
581e13c1
MS
958 &saved_context,
959 __COPY_CONTEXT_SIZE, &n)
a244bdca
CF
960 && n == __COPY_CONTEXT_SIZE)
961 have_saved_context = 1;
962 current_event.dwThreadId = retval;
963 }
3cee93ac 964 }
cb832706 965#endif
3cee93ac 966
a244bdca
CF
967 if (s)
968 xfree (s);
969 return retval;
3cee93ac 970}
24e60978 971
c1748f97
PM
972static int
973display_selector (HANDLE thread, DWORD sel)
974{
975 LDT_ENTRY info;
976 if (GetThreadSelectorEntry (thread, sel, &info))
977 {
978 int base, limit;
979 printf_filtered ("0x%03lx: ", sel);
980 if (!info.HighWord.Bits.Pres)
baa93fa6
CF
981 {
982 puts_filtered ("Segment not present\n");
983 return 0;
984 }
c1748f97
PM
985 base = (info.HighWord.Bits.BaseHi << 24) +
986 (info.HighWord.Bits.BaseMid << 16)
987 + info.BaseLow;
988 limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow;
989 if (info.HighWord.Bits.Granularity)
caad7706 990 limit = (limit << 12) | 0xfff;
c1748f97
PM
991 printf_filtered ("base=0x%08x limit=0x%08x", base, limit);
992 if (info.HighWord.Bits.Default_Big)
baa93fa6 993 puts_filtered(" 32-bit ");
c1748f97 994 else
baa93fa6 995 puts_filtered(" 16-bit ");
c1748f97
PM
996 switch ((info.HighWord.Bits.Type & 0xf) >> 1)
997 {
998 case 0:
baa93fa6
CF
999 puts_filtered ("Data (Read-Only, Exp-up");
1000 break;
c1748f97 1001 case 1:
baa93fa6
CF
1002 puts_filtered ("Data (Read/Write, Exp-up");
1003 break;
c1748f97 1004 case 2:
baa93fa6
CF
1005 puts_filtered ("Unused segment (");
1006 break;
c1748f97 1007 case 3:
baa93fa6
CF
1008 puts_filtered ("Data (Read/Write, Exp-down");
1009 break;
c1748f97 1010 case 4:
baa93fa6
CF
1011 puts_filtered ("Code (Exec-Only, N.Conf");
1012 break;
c1748f97 1013 case 5:
baa93fa6 1014 puts_filtered ("Code (Exec/Read, N.Conf");
c1748f97
PM
1015 break;
1016 case 6:
baa93fa6 1017 puts_filtered ("Code (Exec-Only, Conf");
c1748f97
PM
1018 break;
1019 case 7:
baa93fa6 1020 puts_filtered ("Code (Exec/Read, Conf");
c1748f97
PM
1021 break;
1022 default:
1023 printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type);
1024 }
1025 if ((info.HighWord.Bits.Type & 0x1) == 0)
baa93fa6 1026 puts_filtered(", N.Acc");
c1748f97
PM
1027 puts_filtered (")\n");
1028 if ((info.HighWord.Bits.Type & 0x10) == 0)
1029 puts_filtered("System selector ");
1030 printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl);
1031 if (info.HighWord.Bits.Granularity)
baa93fa6 1032 puts_filtered ("Page granular.\n");
c1748f97
PM
1033 else
1034 puts_filtered ("Byte granular.\n");
1035 return 1;
1036 }
1037 else
1038 {
5572ce1f
PM
1039 DWORD err = GetLastError ();
1040 if (err == ERROR_NOT_SUPPORTED)
1041 printf_filtered ("Function not supported\n");
1042 else
1043 printf_filtered ("Invalid selector 0x%lx.\n",sel);
c1748f97
PM
1044 return 0;
1045 }
1046}
1047
1048static void
1049display_selectors (char * args, int from_tty)
1050{
1051 if (!current_thread)
1052 {
1053 puts_filtered ("Impossible to display selectors now.\n");
1054 return;
1055 }
1056 if (!args)
1057 {
1058
1059 puts_filtered ("Selector $cs\n");
1060 display_selector (current_thread->h,
baa93fa6 1061 current_thread->context.SegCs);
c1748f97
PM
1062 puts_filtered ("Selector $ds\n");
1063 display_selector (current_thread->h,
baa93fa6 1064 current_thread->context.SegDs);
c1748f97
PM
1065 puts_filtered ("Selector $es\n");
1066 display_selector (current_thread->h,
baa93fa6 1067 current_thread->context.SegEs);
c1748f97
PM
1068 puts_filtered ("Selector $ss\n");
1069 display_selector (current_thread->h,
baa93fa6 1070 current_thread->context.SegSs);
c1748f97
PM
1071 puts_filtered ("Selector $fs\n");
1072 display_selector (current_thread->h,
1073 current_thread->context.SegFs);
1074 puts_filtered ("Selector $gs\n");
1075 display_selector (current_thread->h,
baa93fa6 1076 current_thread->context.SegGs);
c1748f97
PM
1077 }
1078 else
1079 {
1080 int sel;
1081 sel = parse_and_eval_long (args);
1082 printf_filtered ("Selector \"%s\"\n",args);
1083 display_selector (current_thread->h, sel);
1084 }
1085}
1086
7393af7c 1087#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
a74ce742
PM
1088 printf_unfiltered ("gdb: Target exception %s at %s\n", x, \
1089 host_address_to_string (\
1090 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
7393af7c 1091
36339ecd 1092static int
450005e7 1093handle_exception (struct target_waitstatus *ourstatus)
24e60978 1094{
3cee93ac 1095 thread_info *th;
29fe111d 1096 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
3cee93ac 1097
29fe111d 1098 ourstatus->kind = TARGET_WAITKIND_STOPPED;
8a892701 1099
581e13c1 1100 /* Record the context of the current thread. */
3cee93ac 1101 th = thread_rec (current_event.dwThreadId, -1);
24e60978 1102
29fe111d 1103 switch (code)
24e60978 1104 {
1ef980b9 1105 case EXCEPTION_ACCESS_VIOLATION:
7393af7c
PM
1106 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
1107 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
10325bc5 1108#ifdef __CYGWIN__
8da8e0b3 1109 {
581e13c1
MS
1110 /* See if the access violation happened within the cygwin DLL
1111 itself. Cygwin uses a kind of exception handling to deal
1112 with passed-in invalid addresses. gdb should not treat
1113 these as real SEGVs since they will be silently handled by
1114 cygwin. A real SEGV will (theoretically) be caught by
1115 cygwin later in the process and will be sent as a
1116 cygwin-specific-signal. So, ignore SEGVs if they show up
1117 within the text segment of the DLL itself. */
8da8e0b3 1118 char *fn;
581e13c1
MS
1119 CORE_ADDR addr = (CORE_ADDR) (uintptr_t)
1120 current_event.u.Exception.ExceptionRecord.ExceptionAddress;
1121
1122 if ((!cygwin_exceptions && (addr >= cygwin_load_start
1123 && addr < cygwin_load_end))
a244bdca 1124 || (find_pc_partial_function (addr, &fn, NULL, NULL)
581e13c1
MS
1125 && strncmp (fn, "KERNEL32!IsBad",
1126 strlen ("KERNEL32!IsBad")) == 0))
8da8e0b3
CF
1127 return 0;
1128 }
10325bc5 1129#endif
7393af7c
PM
1130 break;
1131 case STATUS_STACK_OVERFLOW:
1132 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
1ef980b9 1133 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
7393af7c
PM
1134 break;
1135 case STATUS_FLOAT_DENORMAL_OPERAND:
1136 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
1137 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1138 break;
1139 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1140 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
1141 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1142 break;
1143 case STATUS_FLOAT_INEXACT_RESULT:
1144 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
1145 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1146 break;
1147 case STATUS_FLOAT_INVALID_OPERATION:
1148 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
1149 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1150 break;
1151 case STATUS_FLOAT_OVERFLOW:
1152 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
1153 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1154 break;
1155 case STATUS_FLOAT_STACK_CHECK:
1156 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
1157 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1ef980b9 1158 break;
3b7c8b74 1159 case STATUS_FLOAT_UNDERFLOW:
7393af7c
PM
1160 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
1161 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1162 break;
3b7c8b74 1163 case STATUS_FLOAT_DIVIDE_BY_ZERO:
7393af7c
PM
1164 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
1165 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1166 break;
3b7c8b74 1167 case STATUS_INTEGER_DIVIDE_BY_ZERO:
7393af7c 1168 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
3b7c8b74 1169 ourstatus->value.sig = TARGET_SIGNAL_FPE;
3b7c8b74 1170 break;
7393af7c
PM
1171 case STATUS_INTEGER_OVERFLOW:
1172 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
1173 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1ef980b9
SC
1174 break;
1175 case EXCEPTION_BREAKPOINT:
7393af7c 1176 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
1ef980b9
SC
1177 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1178 break;
1179 case DBG_CONTROL_C:
7393af7c 1180 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
1ef980b9 1181 ourstatus->value.sig = TARGET_SIGNAL_INT;
5b421780
PM
1182 break;
1183 case DBG_CONTROL_BREAK:
7393af7c 1184 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
5b421780 1185 ourstatus->value.sig = TARGET_SIGNAL_INT;
1ef980b9
SC
1186 break;
1187 case EXCEPTION_SINGLE_STEP:
7393af7c 1188 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
1ef980b9
SC
1189 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1190 break;
8227c82d 1191 case EXCEPTION_ILLEGAL_INSTRUCTION:
7393af7c
PM
1192 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
1193 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1194 break;
1195 case EXCEPTION_PRIV_INSTRUCTION:
1196 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
1197 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1198 break;
1199 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1200 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
8227c82d
CF
1201 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1202 break;
1ef980b9 1203 default:
581e13c1 1204 /* Treat unhandled first chance exceptions specially. */
02e423b9 1205 if (current_event.u.Exception.dwFirstChance)
a244bdca 1206 return -1;
a74ce742
PM
1207 printf_unfiltered ("gdb: unknown target exception 0x%08lx at %s\n",
1208 current_event.u.Exception.ExceptionRecord.ExceptionCode,
1209 host_address_to_string (
1210 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
24e60978 1211 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1ef980b9 1212 break;
24e60978 1213 }
24e60978 1214 exception_count++;
7393af7c 1215 last_sig = ourstatus->value.sig;
36339ecd 1216 return 1;
24e60978
SC
1217}
1218
3cee93ac 1219/* Resume all artificially suspended threads if we are continuing
581e13c1 1220 execution. */
3cee93ac 1221static BOOL
dc05df57 1222windows_continue (DWORD continue_status, int id)
3cee93ac
CF
1223{
1224 int i;
1225 thread_info *th;
1226 BOOL res;
1227
1c1238a5 1228 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%lx, %s);\n",
7393af7c 1229 current_event.dwProcessId, current_event.dwThreadId,
dfe7f3ac 1230 continue_status == DBG_CONTINUE ?
7393af7c 1231 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
6537bb24
PA
1232
1233 for (th = &thread_head; (th = th->next) != NULL;)
1234 if ((id == -1 || id == (int) th->id)
1235 && th->suspended)
1236 {
1237 if (debug_registers_changed)
1238 {
1239 th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
1240 th->context.Dr0 = dr[0];
1241 th->context.Dr1 = dr[1];
1242 th->context.Dr2 = dr[2];
1243 th->context.Dr3 = dr[3];
1244 th->context.Dr6 = DR6_CLEAR_VALUE;
1245 th->context.Dr7 = dr[7];
1246 }
1247 if (th->context.ContextFlags)
1248 {
1249 CHECK (SetThreadContext (th->h, &th->context));
1250 th->context.ContextFlags = 0;
1251 }
1252 if (th->suspended > 0)
1253 (void) ResumeThread (th->h);
1254 th->suspended = 0;
1255 }
1256
0714f9bf
SS
1257 res = ContinueDebugEvent (current_event.dwProcessId,
1258 current_event.dwThreadId,
1259 continue_status);
3cee93ac 1260
fa4ba8da 1261 debug_registers_changed = 0;
3cee93ac
CF
1262 return res;
1263}
1264
d6dc8049
CF
1265/* Called in pathological case where Windows fails to send a
1266 CREATE_PROCESS_DEBUG_EVENT after an attach. */
3ee6f623 1267static DWORD
5439edaa 1268fake_create_process (void)
3ade5333
CF
1269{
1270 current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
1271 current_event.dwProcessId);
bf25528d
CF
1272 if (current_process_handle != NULL)
1273 open_process_used = 1;
1274 else
1275 {
b37520b6 1276 error (_("OpenProcess call failed, GetLastError = %lud"),
bf25528d
CF
1277 GetLastError ());
1278 /* We can not debug anything in that case. */
1279 }
3ade5333 1280 main_thread_id = current_event.dwThreadId;
711e434b
PM
1281 current_thread = windows_add_thread (
1282 ptid_build (current_event.dwProcessId, 0,
1283 current_event.dwThreadId),
1284 current_event.u.CreateThread.hThread,
1285 current_event.u.CreateThread.lpThreadLocalBase);
3ade5333
CF
1286 return main_thread_id;
1287}
1288
a244bdca 1289static void
28439f5e
PA
1290windows_resume (struct target_ops *ops,
1291 ptid_t ptid, int step, enum target_signal sig)
a244bdca
CF
1292{
1293 thread_info *th;
1294 DWORD continue_status = DBG_CONTINUE;
1295
2dc38344
PA
1296 /* A specific PTID means `step only this thread id'. */
1297 int resume_all = ptid_equal (ptid, minus_one_ptid);
1298
1299 /* If we're continuing all threads, it's the current inferior that
1300 should be handled specially. */
1301 if (resume_all)
1302 ptid = inferior_ptid;
a244bdca
CF
1303
1304 if (sig != TARGET_SIGNAL_0)
1305 {
1306 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
1307 {
1308 DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
1309 }
1310 else if (sig == last_sig)
1311 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1312 else
1313#if 0
1314/* This code does not seem to work, because
1315 the kernel does probably not consider changes in the ExceptionRecord
1316 structure when passing the exception to the inferior.
1317 Note that this seems possible in the exception handler itself. */
1318 {
1319 int i;
1320 for (i = 0; xlate[i].them != -1; i++)
1321 if (xlate[i].us == sig)
1322 {
581e13c1
MS
1323 current_event.u.Exception.ExceptionRecord.ExceptionCode
1324 = xlate[i].them;
a244bdca
CF
1325 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1326 break;
1327 }
1328 if (continue_status == DBG_CONTINUE)
1329 {
1330 DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
1331 }
1332 }
1333#endif
1334 DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
1335 last_sig));
1336 }
1337
1338 last_sig = TARGET_SIGNAL_0;
1339
dc05df57 1340 DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
2dc38344 1341 ptid_get_pid (ptid), ptid_get_tid (ptid), step, sig));
a244bdca 1342
581e13c1 1343 /* Get context for currently selected thread. */
2dc38344 1344 th = thread_rec (ptid_get_tid (inferior_ptid), FALSE);
a244bdca
CF
1345 if (th)
1346 {
1347 if (step)
1348 {
581e13c1 1349 /* Single step by setting t bit. */
a97b0ac8
UW
1350 struct regcache *regcache = get_current_regcache ();
1351 struct gdbarch *gdbarch = get_regcache_arch (regcache);
1352 windows_fetch_inferior_registers (ops, regcache,
1353 gdbarch_ps_regnum (gdbarch));
a244bdca
CF
1354 th->context.EFlags |= FLAG_TRACE_BIT;
1355 }
1356
1357 if (th->context.ContextFlags)
1358 {
1359 if (debug_registers_changed)
1360 {
1361 th->context.Dr0 = dr[0];
1362 th->context.Dr1 = dr[1];
1363 th->context.Dr2 = dr[2];
1364 th->context.Dr3 = dr[3];
6537bb24 1365 th->context.Dr6 = DR6_CLEAR_VALUE;
a244bdca
CF
1366 th->context.Dr7 = dr[7];
1367 }
1368 CHECK (SetThreadContext (th->h, &th->context));
1369 th->context.ContextFlags = 0;
1370 }
1371 }
1372
1373 /* Allow continuing with the same signal that interrupted us.
581e13c1 1374 Otherwise complain. */
a244bdca 1375
2dc38344 1376 if (resume_all)
dc05df57 1377 windows_continue (continue_status, -1);
2dc38344 1378 else
dc05df57 1379 windows_continue (continue_status, ptid_get_tid (ptid));
a244bdca
CF
1380}
1381
695de547
CF
1382/* Ctrl-C handler used when the inferior is not run in the same console. The
1383 handler is in charge of interrupting the inferior using DebugBreakProcess.
1384 Note that this function is not available prior to Windows XP. In this case
1385 we emit a warning. */
1386BOOL WINAPI
1387ctrl_c_handler (DWORD event_type)
1388{
1389 const int attach_flag = current_inferior ()->attach_flag;
1390
bb0613a5
PM
1391 /* Only handle Ctrl-C and Ctrl-Break events. Ignore others. */
1392 if (event_type != CTRL_C_EVENT && event_type != CTRL_BREAK_EVENT)
695de547
CF
1393 return FALSE;
1394
1395 /* If the inferior and the debugger share the same console, do nothing as
1396 the inferior has also received the Ctrl-C event. */
1397 if (!new_console && !attach_flag)
1398 return TRUE;
1399
1400 if (!DebugBreakProcess (current_process_handle))
581e13c1
MS
1401 warning (_("Could not interrupt program. "
1402 "Press Ctrl-c in the program console."));
695de547
CF
1403
1404 /* Return true to tell that Ctrl-C has been handled. */
1405 return TRUE;
1406}
1407
8a892701 1408/* Get the next event from the child. Return 1 if the event requires
695de547 1409 handling by WFI (or whatever). */
1e37c281 1410static int
28439f5e
PA
1411get_windows_debug_event (struct target_ops *ops,
1412 int pid, struct target_waitstatus *ourstatus)
1e37c281
JM
1413{
1414 BOOL debug_event;
8a892701 1415 DWORD continue_status, event_code;
87a45c96 1416 thread_info *th;
8a892701 1417 static thread_info dummy_thread_info;
450005e7 1418 int retval = 0;
1e37c281 1419
7393af7c 1420 last_sig = TARGET_SIGNAL_0;
9d3789f7 1421
8a892701 1422 if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
29fe111d 1423 goto out;
1e37c281
JM
1424
1425 event_count++;
1426 continue_status = DBG_CONTINUE;
1e37c281 1427
8a892701 1428 event_code = current_event.dwDebugEventCode;
450005e7 1429 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
87a45c96 1430 th = NULL;
a244bdca 1431 have_saved_context = 0;
8a892701
CF
1432
1433 switch (event_code)
1e37c281
JM
1434 {
1435 case CREATE_THREAD_DEBUG_EVENT:
1436 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1437 (unsigned) current_event.dwProcessId,
1438 (unsigned) current_event.dwThreadId,
1439 "CREATE_THREAD_DEBUG_EVENT"));
dfe7f3ac 1440 if (saw_create != 1)
3ade5333 1441 {
181e7f93
PA
1442 struct inferior *inf;
1443 inf = find_inferior_pid (current_event.dwProcessId);
1444 if (!saw_create && inf->attach_flag)
3ade5333 1445 {
d6dc8049
CF
1446 /* Kludge around a Windows bug where first event is a create
1447 thread event. Caused when attached process does not have
581e13c1 1448 a main thread. */
3a3e9ee3 1449 retval = fake_create_process ();
181e7f93
PA
1450 if (retval)
1451 saw_create++;
3ade5333
CF
1452 }
1453 break;
1454 }
581e13c1 1455 /* Record the existence of this thread. */
450005e7 1456 retval = current_event.dwThreadId;
dc05df57 1457 th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
2dc38344 1458 current_event.dwThreadId),
711e434b
PM
1459 current_event.u.CreateThread.hThread,
1460 current_event.u.CreateThread.lpThreadLocalBase);
1461
1e37c281
JM
1462 break;
1463
1464 case EXIT_THREAD_DEBUG_EVENT:
1c1238a5 1465 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1466 (unsigned) current_event.dwProcessId,
1467 (unsigned) current_event.dwThreadId,
1468 "EXIT_THREAD_DEBUG_EVENT"));
b3c613f2 1469
87a45c96
CF
1470 if (current_event.dwThreadId != main_thread_id)
1471 {
dc05df57 1472 windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
2dc38344 1473 current_event.dwThreadId));
87a45c96
CF
1474 th = &dummy_thread_info;
1475 }
1e37c281
JM
1476 break;
1477
1478 case CREATE_PROCESS_DEBUG_EVENT:
1c1238a5 1479 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1480 (unsigned) current_event.dwProcessId,
1481 (unsigned) current_event.dwThreadId,
1482 "CREATE_PROCESS_DEBUG_EVENT"));
700b351b 1483 CloseHandle (current_event.u.CreateProcessInfo.hFile);
dfe7f3ac 1484 if (++saw_create != 1)
bf25528d 1485 break;
1e37c281 1486
dfe7f3ac 1487 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
87a45c96 1488 if (main_thread_id)
695de547
CF
1489 windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
1490 main_thread_id));
9d3789f7 1491 main_thread_id = current_event.dwThreadId;
581e13c1 1492 /* Add the main thread. */
dc05df57 1493 th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
695de547 1494 current_event.dwThreadId),
711e434b
PM
1495 current_event.u.CreateProcessInfo.hThread,
1496 current_event.u.CreateProcessInfo.lpThreadLocalBase);
3a3e9ee3 1497 retval = current_event.dwThreadId;
1e37c281
JM
1498 break;
1499
1500 case EXIT_PROCESS_DEBUG_EVENT:
1c1238a5 1501 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1502 (unsigned) current_event.dwProcessId,
1503 (unsigned) current_event.dwThreadId,
1504 "EXIT_PROCESS_DEBUG_EVENT"));
16d905e2
CF
1505 if (!windows_initialization_done)
1506 {
1507 target_terminal_ours ();
1508 target_mourn_inferior ();
1509 error (_("During startup program exited with code 0x%x."),
1510 (unsigned int) current_event.u.ExitProcess.dwExitCode);
1511 }
1512 else if (saw_create == 1)
1513 {
1514 ourstatus->kind = TARGET_WAITKIND_EXITED;
1515 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1516 retval = main_thread_id;
1517 }
8a892701 1518 break;
1e37c281
JM
1519
1520 case LOAD_DLL_DEBUG_EVENT:
1c1238a5 1521 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1522 (unsigned) current_event.dwProcessId,
1523 (unsigned) current_event.dwThreadId,
1524 "LOAD_DLL_DEBUG_EVENT"));
700b351b 1525 CloseHandle (current_event.u.LoadDll.hFile);
dfe7f3ac
CF
1526 if (saw_create != 1)
1527 break;
8a892701 1528 catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
450005e7
CF
1529 ourstatus->kind = TARGET_WAITKIND_LOADED;
1530 ourstatus->value.integer = 0;
9d3789f7 1531 retval = main_thread_id;
1e37c281
JM
1532 break;
1533
1534 case UNLOAD_DLL_DEBUG_EVENT:
1c1238a5 1535 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1536 (unsigned) current_event.dwProcessId,
1537 (unsigned) current_event.dwThreadId,
1538 "UNLOAD_DLL_DEBUG_EVENT"));
dfe7f3ac
CF
1539 if (saw_create != 1)
1540 break;
d3ff4a77 1541 catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
de1b3c3d
PA
1542 ourstatus->kind = TARGET_WAITKIND_LOADED;
1543 ourstatus->value.integer = 0;
1544 retval = main_thread_id;
d3ff4a77 1545 break;
1e37c281
JM
1546
1547 case EXCEPTION_DEBUG_EVENT:
1c1238a5 1548 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1549 (unsigned) current_event.dwProcessId,
1550 (unsigned) current_event.dwThreadId,
1551 "EXCEPTION_DEBUG_EVENT"));
dfe7f3ac
CF
1552 if (saw_create != 1)
1553 break;
a244bdca
CF
1554 switch (handle_exception (ourstatus))
1555 {
1556 case 0:
1557 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1558 break;
1559 case 1:
1560 retval = current_event.dwThreadId;
1561 break;
1562 case -1:
1563 last_sig = 1;
1564 continue_status = -1;
1565 break;
1566 }
1e37c281
JM
1567 break;
1568
581e13c1 1569 case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
1c1238a5 1570 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
1571 (unsigned) current_event.dwProcessId,
1572 (unsigned) current_event.dwThreadId,
1573 "OUTPUT_DEBUG_STRING_EVENT"));
dfe7f3ac
CF
1574 if (saw_create != 1)
1575 break;
a244bdca 1576 retval = handle_output_debug_string (ourstatus);
1e37c281 1577 break;
9d3789f7 1578
1e37c281 1579 default:
dfe7f3ac
CF
1580 if (saw_create != 1)
1581 break;
29fe111d
CF
1582 printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
1583 (DWORD) current_event.dwProcessId,
1584 (DWORD) current_event.dwThreadId);
1585 printf_unfiltered (" unknown event code %ld\n",
1e37c281
JM
1586 current_event.dwDebugEventCode);
1587 break;
1588 }
1589
dfe7f3ac 1590 if (!retval || saw_create != 1)
a244bdca
CF
1591 {
1592 if (continue_status == -1)
02529b48 1593 windows_resume (ops, minus_one_ptid, 0, 1);
a244bdca 1594 else
dc05df57 1595 CHECK (windows_continue (continue_status, -1));
a244bdca 1596 }
450005e7 1597 else
9d3789f7 1598 {
2dc38344
PA
1599 inferior_ptid = ptid_build (current_event.dwProcessId, 0,
1600 retval);
3ade5333 1601 current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
9d3789f7 1602 }
1e37c281
JM
1603
1604out:
450005e7 1605 return retval;
1e37c281
JM
1606}
1607
2dc38344 1608/* Wait for interesting events to occur in the target process. */
39f77062 1609static ptid_t
117de6a9 1610windows_wait (struct target_ops *ops,
47608cb1 1611 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
24e60978 1612{
2dc38344 1613 int pid = -1;
39f77062 1614
c44537cf
CV
1615 target_terminal_ours ();
1616
24e60978
SC
1617 /* We loop when we get a non-standard exception rather than return
1618 with a SPURIOUS because resume can try and step or modify things,
3cee93ac 1619 which needs a current_thread->h. But some of these exceptions mark
24e60978 1620 the birth or death of threads, which mean that the current thread
581e13c1 1621 isn't necessarily what you think it is. */
24e60978
SC
1622
1623 while (1)
450005e7 1624 {
c57918b2 1625 int retval;
2b008701 1626
695de547
CF
1627 /* If the user presses Ctrl-c while the debugger is waiting
1628 for an event, he expects the debugger to interrupt his program
1629 and to get the prompt back. There are two possible situations:
1630
1631 - The debugger and the program do not share the console, in
1632 which case the Ctrl-c event only reached the debugger.
1633 In that case, the ctrl_c handler will take care of interrupting
581e13c1
MS
1634 the inferior. Note that this case is working starting with
1635 Windows XP. For Windows 2000, Ctrl-C should be pressed in the
695de547
CF
1636 inferior console.
1637
1638 - The debugger and the program share the same console, in which
1639 case both debugger and inferior will receive the Ctrl-c event.
1640 In that case the ctrl_c handler will ignore the event, as the
1641 Ctrl-c event generated inside the inferior will trigger the
1642 expected debug event.
1643
1644 FIXME: brobecker/2008-05-20: If the inferior receives the
1645 signal first and the delay until GDB receives that signal
1646 is sufficiently long, GDB can sometimes receive the SIGINT
1647 after we have unblocked the CTRL+C handler. This would
1648 lead to the debugger stopping prematurely while handling
1649 the new-thread event that comes with the handling of the SIGINT
1650 inside the inferior, and then stop again immediately when
1651 the user tries to resume the execution in the inferior.
1652 This is a classic race that we should try to fix one day. */
1653 SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
28439f5e 1654 retval = get_windows_debug_event (ops, pid, ourstatus);
695de547 1655 SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
c57918b2 1656
450005e7 1657 if (retval)
2dc38344 1658 return ptid_build (current_event.dwProcessId, 0, retval);
450005e7
CF
1659 else
1660 {
1661 int detach = 0;
3cee93ac 1662
98bbd631
AC
1663 if (deprecated_ui_loop_hook != NULL)
1664 detach = deprecated_ui_loop_hook (0);
0714f9bf 1665
450005e7 1666 if (detach)
7d85a9c0 1667 windows_kill_inferior (ops);
450005e7
CF
1668 }
1669 }
24e60978
SC
1670}
1671
9d3789f7 1672static void
dc05df57 1673do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
9d3789f7
CF
1674{
1675 extern int stop_after_trap;
fa4ba8da 1676 int i;
d6b48e9c 1677 struct inferior *inf;
2020b7ab 1678 struct thread_info *tp;
9d3789f7 1679
7393af7c 1680 last_sig = TARGET_SIGNAL_0;
9d3789f7
CF
1681 event_count = 0;
1682 exception_count = 0;
bf25528d 1683 open_process_used = 0;
fa4ba8da 1684 debug_registers_changed = 0;
dfe7f3ac 1685 debug_registers_used = 0;
fa4ba8da
PM
1686 for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
1687 dr[i] = 0;
10325bc5 1688#ifdef __CYGWIN__
de1b3c3d 1689 cygwin_load_start = cygwin_load_end = 0;
10325bc5 1690#endif
9d3789f7
CF
1691 current_event.dwProcessId = pid;
1692 memset (&current_event, 0, sizeof (current_event));
0795be10 1693 push_target (ops);
cb851954 1694 disable_breakpoints_in_shlibs ();
dc05df57 1695 windows_clear_solib ();
9d3789f7
CF
1696 clear_proceed_status ();
1697 init_wait_for_inferior ();
1698
6c95b8df
PA
1699 inf = current_inferior ();
1700 inferior_appeared (inf, pid);
181e7f93 1701 inf->attach_flag = attaching;
7f9f62ba 1702
9f9d052e
PM
1703 /* Make the new process the current inferior, so terminal handling
1704 can rely on it. When attaching, we don't know about any thread
1705 id here, but that's OK --- nothing should be referencing the
dc05df57 1706 current thread until we report an event out of windows_wait. */
9f9d052e
PM
1707 inferior_ptid = pid_to_ptid (pid);
1708
c44537cf 1709 terminal_init_inferior_with_pgrp (pid);
9d3789f7
CF
1710 target_terminal_inferior ();
1711
16d905e2 1712 windows_initialization_done = 0;
16c381f0 1713 inf->control.stop_soon = STOP_QUIETLY;
9d3789f7
CF
1714 while (1)
1715 {
1716 stop_after_trap = 1;
e4c8541f 1717 wait_for_inferior ();
2020b7ab 1718 tp = inferior_thread ();
16c381f0
JK
1719 if (tp->suspend.stop_signal != TARGET_SIGNAL_TRAP)
1720 resume (0, tp->suspend.stop_signal);
9d3789f7
CF
1721 else
1722 break;
1723 }
eff8332b 1724
16d905e2 1725 windows_initialization_done = 1;
16c381f0 1726 inf->control.stop_soon = NO_STOP_QUIETLY;
9d3789f7
CF
1727 stop_after_trap = 0;
1728 return;
1729}
1730
616a9dc4
CV
1731/* Try to set or remove a user privilege to the current process. Return -1
1732 if that fails, the previous setting of that privilege otherwise.
1733
1734 This code is copied from the Cygwin source code and rearranged to allow
1735 dynamically loading of the needed symbols from advapi32 which is only
581e13c1 1736 available on NT/2K/XP. */
616a9dc4
CV
1737static int
1738set_process_privilege (const char *privilege, BOOL enable)
1739{
616a9dc4
CV
1740 HANDLE token_hdl = NULL;
1741 LUID restore_priv;
1742 TOKEN_PRIVILEGES new_priv, orig_priv;
1743 int ret = -1;
1744 DWORD size;
1745
616a9dc4
CV
1746 if (!OpenProcessToken (GetCurrentProcess (),
1747 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
1748 &token_hdl))
1749 goto out;
1750
418c6cb3 1751 if (!LookupPrivilegeValueA (NULL, privilege, &restore_priv))
616a9dc4
CV
1752 goto out;
1753
1754 new_priv.PrivilegeCount = 1;
1755 new_priv.Privileges[0].Luid = restore_priv;
1756 new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
1757
1758 if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv,
295732ea 1759 sizeof orig_priv, &orig_priv, &size))
616a9dc4
CV
1760 goto out;
1761#if 0
1762 /* Disabled, otherwise every `attach' in an unprivileged user session
1763 would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
581e13c1 1764 windows_attach(). */
616a9dc4 1765 /* AdjustTokenPrivileges returns TRUE even if the privilege could not
581e13c1 1766 be enabled. GetLastError () returns an correct error code, though. */
616a9dc4
CV
1767 if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
1768 goto out;
1769#endif
1770
1771 ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
1772
1773out:
1774 if (token_hdl)
1775 CloseHandle (token_hdl);
1776
1777 return ret;
1778}
1779
02cc9f49 1780/* Attach to process PID, then initialize for debugging it. */
24e60978 1781static void
dc05df57 1782windows_attach (struct target_ops *ops, char *args, int from_tty)
24e60978
SC
1783{
1784 BOOL ok;
559e75c0 1785 DWORD pid;
24e60978 1786
74164c56 1787 pid = parse_pid_to_attach (args);
24e60978 1788
616a9dc4
CV
1789 if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
1790 {
1791 printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n");
581e13c1
MS
1792 printf_unfiltered ("This can cause attach to "
1793 "fail on Windows NT/2K/XP\n");
616a9dc4
CV
1794 }
1795
dc05df57 1796 windows_init_thread_list ();
9d3789f7 1797 ok = DebugActiveProcess (pid);
91a175b3 1798 saw_create = 0;
24e60978 1799
10325bc5 1800#ifdef __CYGWIN__
24e60978 1801 if (!ok)
baa93fa6 1802 {
581e13c1 1803 /* Try fall back to Cygwin pid. */
baa93fa6
CF
1804 pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
1805
1806 if (pid > 0)
1807 ok = DebugActiveProcess (pid);
10325bc5
PA
1808 }
1809#endif
baa93fa6 1810
10325bc5
PA
1811 if (!ok)
1812 error (_("Can't attach to process."));
24e60978 1813
2b008701 1814 DebugSetProcessKillOnExit (FALSE);
3ade5333 1815
24e60978
SC
1816 if (from_tty)
1817 {
1818 char *exec_file = (char *) get_exec_file (0);
1819
1820 if (exec_file)
1821 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
39f77062 1822 target_pid_to_str (pid_to_ptid (pid)));
24e60978
SC
1823 else
1824 printf_unfiltered ("Attaching to %s\n",
39f77062 1825 target_pid_to_str (pid_to_ptid (pid)));
24e60978
SC
1826
1827 gdb_flush (gdb_stdout);
1828 }
1829
dc05df57 1830 do_initial_windows_stuff (ops, pid, 1);
9d3789f7 1831 target_terminal_ours ();
24e60978
SC
1832}
1833
24e60978 1834static void
dc05df57 1835windows_detach (struct target_ops *ops, char *args, int from_tty)
24e60978 1836{
02cc9f49
CV
1837 int detached = 1;
1838
2b008701
CF
1839 ptid_t ptid = {-1};
1840 windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
96998ce7 1841
2b008701
CF
1842 if (!DebugActiveProcessStop (current_event.dwProcessId))
1843 {
1844 error (_("Can't detach process %lu (error %lu)"),
1845 current_event.dwProcessId, GetLastError ());
1846 detached = 0;
02cc9f49 1847 }
2b008701
CF
1848 DebugSetProcessKillOnExit (FALSE);
1849
02cc9f49 1850 if (detached && from_tty)
24e60978
SC
1851 {
1852 char *exec_file = get_exec_file (0);
1853 if (exec_file == 0)
1854 exec_file = "";
02cc9f49
CV
1855 printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file,
1856 current_event.dwProcessId);
24e60978
SC
1857 gdb_flush (gdb_stdout);
1858 }
7f9f62ba 1859
39f77062 1860 inferior_ptid = null_ptid;
7f9f62ba
PA
1861 detach_inferior (current_event.dwProcessId);
1862
0795be10 1863 unpush_target (ops);
24e60978
SC
1864}
1865
3ee6f623 1866static char *
dc05df57 1867windows_pid_to_exec_file (int pid)
47216e51 1868{
b3c613f2 1869 static char path[__PMAX];
10325bc5 1870#ifdef __CYGWIN__
581e13c1 1871 /* Try to find exe name as symlink target of /proc/<pid>/exe. */
33605d39
CF
1872 int nchars;
1873 char procexe[sizeof ("/proc/4294967295/exe")];
2dc38344 1874 sprintf (procexe, "/proc/%u/exe", pid);
33605d39
CF
1875 nchars = readlink (procexe, path, sizeof(path));
1876 if (nchars > 0 && nchars < sizeof (path))
47216e51 1877 {
33605d39
CF
1878 path[nchars] = '\0'; /* Got it */
1879 return path;
47216e51 1880 }
10325bc5
PA
1881#endif
1882
33605d39 1883 /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
581e13c1 1884 of gdb, or we're trying to debug a non-Cygwin windows executable. */
33605d39
CF
1885 if (!get_module_name (0, path))
1886 path[0] = '\0';
1887
1888 return path;
47216e51
CV
1889}
1890
24e60978
SC
1891/* Print status information about what we're accessing. */
1892
1893static void
dc05df57 1894windows_files_info (struct target_ops *ignore)
24e60978 1895{
181e7f93
PA
1896 struct inferior *inf = current_inferior ();
1897
24e60978 1898 printf_unfiltered ("\tUsing the running image of %s %s.\n",
181e7f93
PA
1899 inf->attach_flag ? "attached" : "child",
1900 target_pid_to_str (inferior_ptid));
24e60978
SC
1901}
1902
24e60978 1903static void
dc05df57 1904windows_open (char *arg, int from_tty)
24e60978 1905{
8a3fe4f8 1906 error (_("Use the \"run\" command to start a Unix child process."));
24e60978
SC
1907}
1908
cd44747c
PM
1909/* Modify CreateProcess parameters for use of a new separate console.
1910 Parameters are:
1911 *FLAGS: DWORD parameter for general process creation flags.
1912 *SI: STARTUPINFO structure, for which the console window size and
1913 console buffer size is filled in if GDB is running in a console.
1914 to create the new console.
1915 The size of the used font is not available on all versions of
1916 Windows OS. Furthermore, the current font might not be the default
1917 font, but this is still better than before.
1918 If the windows and buffer sizes are computed,
1919 SI->DWFLAGS is changed so that this information is used
1920 by CreateProcess function. */
1921
1922static void
1923windows_set_console_info (STARTUPINFO *si, DWORD *flags)
1924{
1925 HANDLE hconsole = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
1926 FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1927
1928 if (hconsole != INVALID_HANDLE_VALUE)
1929 {
1930 CONSOLE_SCREEN_BUFFER_INFO sbinfo;
1931 COORD font_size;
1932 CONSOLE_FONT_INFO cfi;
1933
1934 GetCurrentConsoleFont (hconsole, FALSE, &cfi);
1935 font_size = GetConsoleFontSize (hconsole, cfi.nFont);
1936 GetConsoleScreenBufferInfo(hconsole, &sbinfo);
1937 si->dwXSize = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
1938 si->dwYSize = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
1939 if (font_size.X)
1940 si->dwXSize *= font_size.X;
1941 else
1942 si->dwXSize *= 8;
1943 if (font_size.Y)
1944 si->dwYSize *= font_size.Y;
1945 else
1946 si->dwYSize *= 12;
1947 si->dwXCountChars = sbinfo.dwSize.X;
1948 si->dwYCountChars = sbinfo.dwSize.Y;
1949 si->dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS;
1950 }
1951 *flags |= CREATE_NEW_CONSOLE;
1952}
1953
dc05df57 1954/* Start an inferior windows child process and sets inferior_ptid to its pid.
24e60978
SC
1955 EXEC_FILE is the file to run.
1956 ALLARGS is a string containing the arguments to the program.
1957 ENV is the environment vector to pass. Errors reported with error(). */
1958
24e60978 1959static void
dc05df57 1960windows_create_inferior (struct target_ops *ops, char *exec_file,
136d6dae 1961 char *allargs, char **in_env, int from_tty)
24e60978 1962{
b3c613f2 1963 STARTUPINFO si;
41b4aadc 1964#ifdef __CYGWIN__
b3c613f2
CF
1965 cygwin_buf_t real_path[__PMAX];
1966 cygwin_buf_t shell[__PMAX]; /* Path to shell */
d0d0ab16 1967 const char *sh;
b3c613f2
CF
1968 cygwin_buf_t *toexec;
1969 cygwin_buf_t *cygallargs;
1970 cygwin_buf_t *args;
d0d0ab16 1971 size_t len;
2becadee
CF
1972 int tty;
1973 int ostdin, ostdout, ostderr;
41b4aadc 1974#else
b3c613f2
CF
1975 char real_path[__PMAX];
1976 char shell[__PMAX]; /* Path to shell */
d0d0ab16
CV
1977 char *toexec;
1978 char *args;
41b4aadc
CF
1979 HANDLE tty;
1980#endif
d0d0ab16
CV
1981 PROCESS_INFORMATION pi;
1982 BOOL ret;
1983 DWORD flags = 0;
3cb3b8df 1984 const char *inferior_io_terminal = get_inferior_io_terminal ();
24e60978
SC
1985
1986 if (!exec_file)
8a3fe4f8 1987 error (_("No executable specified, use `target exec'."));
24e60978
SC
1988
1989 memset (&si, 0, sizeof (si));
1990 si.cb = sizeof (si);
1991
d0d0ab16
CV
1992 if (new_group)
1993 flags |= CREATE_NEW_PROCESS_GROUP;
1994
1995 if (new_console)
cd44747c 1996 windows_set_console_info (&si, &flags);
d0d0ab16 1997
10325bc5 1998#ifdef __CYGWIN__
349b409f 1999 if (!useshell)
dfe7f3ac 2000 {
d0d0ab16
CV
2001 flags |= DEBUG_ONLY_THIS_PROCESS;
2002 if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, exec_file, real_path,
b3c613f2 2003 __PMAX * sizeof (cygwin_buf_t)) < 0)
d0d0ab16 2004 error (_("Error starting executable: %d"), errno);
dfe7f3ac 2005 toexec = real_path;
b3c613f2 2006#ifdef __USEWIDE
d0d0ab16
CV
2007 len = mbstowcs (NULL, allargs, 0) + 1;
2008 if (len == (size_t) -1)
2009 error (_("Error starting executable: %d"), errno);
2010 cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
2011 mbstowcs (cygallargs, allargs, len);
60c5c021
CF
2012#else
2013 cygallargs = allargs;
b3c613f2 2014#endif
dfe7f3ac
CF
2015 }
2016 else
2017 {
349b409f
CF
2018 sh = getenv ("SHELL");
2019 if (!sh)
2020 sh = "/bin/sh";
b3c613f2 2021 if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, sh, shell, __PMAX) < 0)
d0d0ab16 2022 error (_("Error starting executable via shell: %d"), errno);
b3c613f2 2023#ifdef __USEWIDE
d0d0ab16
CV
2024 len = sizeof (L" -c 'exec '") + mbstowcs (NULL, exec_file, 0)
2025 + mbstowcs (NULL, allargs, 0) + 2;
2026 cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
2027 swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
b3c613f2 2028#else
581e13c1
MS
2029 cygallargs = (char *)
2030 alloca (sizeof (" -c 'exec '") + strlen (exec_file)
b3c613f2
CF
2031 + strlen (allargs) + 2);
2032 sprintf (cygallargs, " -c 'exec %s %s'", exec_file, allargs);
2033#endif
dfe7f3ac 2034 toexec = shell;
d0d0ab16 2035 flags |= DEBUG_PROCESS;
dfe7f3ac 2036 }
b3c613f2
CF
2037
2038#ifdef __USEWIDE
2039 args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
2040 * sizeof (wchar_t));
d0d0ab16
CV
2041 wcscpy (args, toexec);
2042 wcscat (args, L" ");
2043 wcscat (args, cygallargs);
b3c613f2
CF
2044#else
2045 args = (cygwin_buf_t *) alloca (strlen (toexec) + strlen (cygallargs) + 2);
2046 strcpy (args, toexec);
2047 strcat (args, " ");
2048 strcat (args, cygallargs);
2049#endif
2050
e88c49c3 2051 /* Prepare the environment vars for CreateProcess. */
002c07a9 2052 cygwin_internal (CW_SYNC_WINENV);
1750a5ef 2053
2becadee
CF
2054 if (!inferior_io_terminal)
2055 tty = ostdin = ostdout = ostderr = -1;
2056 else
2057 {
2058 tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
2059 if (tty < 0)
2060 {
2061 print_sys_errmsg (inferior_io_terminal, errno);
2062 ostdin = ostdout = ostderr = -1;
2063 }
2064 else
2065 {
2066 ostdin = dup (0);
2067 ostdout = dup (1);
2068 ostderr = dup (2);
2069 dup2 (tty, 0);
2070 dup2 (tty, 1);
2071 dup2 (tty, 2);
2072 }
2073 }
d0d0ab16
CV
2074
2075 windows_init_thread_list ();
b3c613f2
CF
2076 ret = CreateProcess (0,
2077 args, /* command line */
2078 NULL, /* Security */
2079 NULL, /* thread */
2080 TRUE, /* inherit handles */
2081 flags, /* start flags */
2082 NULL, /* environment */
2083 NULL, /* current directory */
2084 &si,
2085 &pi);
d0d0ab16
CV
2086 if (tty >= 0)
2087 {
2088 close (tty);
2089 dup2 (ostdin, 0);
2090 dup2 (ostdout, 1);
2091 dup2 (ostderr, 2);
2092 close (ostdin);
2093 close (ostdout);
2094 close (ostderr);
2095 }
41b4aadc 2096#else
b3c613f2 2097 toexec = exec_file;
d0d0ab16
CV
2098 args = alloca (strlen (toexec) + strlen (allargs) + 2);
2099 strcpy (args, toexec);
2100 strcat (args, " ");
2101 strcat (args, allargs);
2102
d0d0ab16
CV
2103 flags |= DEBUG_ONLY_THIS_PROCESS;
2104
41b4aadc
CF
2105 if (!inferior_io_terminal)
2106 tty = INVALID_HANDLE_VALUE;
2107 else
2108 {
2109 SECURITY_ATTRIBUTES sa;
2110 sa.nLength = sizeof(sa);
2111 sa.lpSecurityDescriptor = 0;
2112 sa.bInheritHandle = TRUE;
2113 tty = CreateFileA (inferior_io_terminal, GENERIC_READ | GENERIC_WRITE,
2114 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
2115 if (tty == INVALID_HANDLE_VALUE)
2116 warning (_("Warning: Failed to open TTY %s, error %#x."),
2117 inferior_io_terminal, (unsigned) GetLastError ());
2118 else
2119 {
2120 si.hStdInput = tty;
2121 si.hStdOutput = tty;
2122 si.hStdError = tty;
2123 si.dwFlags |= STARTF_USESTDHANDLES;
2124 }
2125 }
2becadee 2126
dc05df57 2127 windows_init_thread_list ();
d0d0ab16
CV
2128 ret = CreateProcessA (0,
2129 args, /* command line */
2130 NULL, /* Security */
2131 NULL, /* thread */
2132 TRUE, /* inherit handles */
2133 flags, /* start flags */
2134 NULL, /* environment */
2135 NULL, /* current directory */
2136 &si,
2137 &pi);
41b4aadc
CF
2138 if (tty != INVALID_HANDLE_VALUE)
2139 CloseHandle (tty);
10325bc5 2140#endif
2becadee 2141
24e60978 2142 if (!ret)
8a3fe4f8
AC
2143 error (_("Error creating process %s, (error %d)."),
2144 exec_file, (unsigned) GetLastError ());
24e60978 2145
c1766e7d
PM
2146 CloseHandle (pi.hThread);
2147 CloseHandle (pi.hProcess);
2148
dfe7f3ac
CF
2149 if (useshell && shell[0] != '\0')
2150 saw_create = -1;
2151 else
2152 saw_create = 0;
2153
dc05df57 2154 do_initial_windows_stuff (ops, pi.dwProcessId, 0);
d3a09475 2155
dc05df57 2156 /* windows_continue (DBG_CONTINUE, -1); */
24e60978
SC
2157}
2158
2159static void
dc05df57 2160windows_mourn_inferior (struct target_ops *ops)
24e60978 2161{
dc05df57 2162 (void) windows_continue (DBG_CONTINUE, -1);
fa4ba8da 2163 i386_cleanup_dregs();
bf25528d
CF
2164 if (open_process_used)
2165 {
2166 CHECK (CloseHandle (current_process_handle));
2167 open_process_used = 0;
2168 }
0795be10 2169 unpush_target (ops);
24e60978
SC
2170 generic_mourn_inferior ();
2171}
2172
24e60978 2173/* Send a SIGINT to the process group. This acts just like the user typed a
581e13c1 2174 ^C on the controlling terminal. */
24e60978 2175
b607efe7 2176static void
dc05df57 2177windows_stop (ptid_t ptid)
24e60978 2178{
1ef980b9 2179 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
1e37c281 2180 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
3a4b77d8 2181 registers_changed (); /* refresh register state */
24e60978
SC
2182}
2183
3ee6f623 2184static int
dc05df57 2185windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
0a65a603
AC
2186 int write, struct mem_attrib *mem,
2187 struct target_ops *target)
24e60978 2188{
5732a500 2189 SIZE_T done = 0;
24e60978
SC
2190 if (write)
2191 {
29fe111d 2192 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
2c647436 2193 len, (DWORD) (uintptr_t) memaddr));
2b008701 2194 if (!WriteProcessMemory (current_process_handle,
2c647436 2195 (LPVOID) (uintptr_t) memaddr, our,
6f17862b
CF
2196 len, &done))
2197 done = 0;
2b008701 2198 FlushInstructionCache (current_process_handle,
2c647436 2199 (LPCVOID) (uintptr_t) memaddr, len);
24e60978
SC
2200 }
2201 else
2202 {
29fe111d 2203 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
2c647436 2204 len, (DWORD) (uintptr_t) memaddr));
2b008701 2205 if (!ReadProcessMemory (current_process_handle,
2c647436 2206 (LPCVOID) (uintptr_t) memaddr, our,
6f17862b
CF
2207 len, &done))
2208 done = 0;
24e60978
SC
2209 }
2210 return done;
2211}
2212
3ee6f623 2213static void
7d85a9c0 2214windows_kill_inferior (struct target_ops *ops)
24e60978 2215{
3cee93ac
CF
2216 CHECK (TerminateProcess (current_process_handle, 0));
2217
b5edcb45
ILT
2218 for (;;)
2219 {
dc05df57 2220 if (!windows_continue (DBG_CONTINUE, -1))
b5edcb45 2221 break;
3cee93ac 2222 if (!WaitForDebugEvent (&current_event, INFINITE))
b5edcb45 2223 break;
3cee93ac 2224 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
b5edcb45
ILT
2225 break;
2226 }
2227
581e13c1 2228 target_mourn_inferior (); /* Or just windows_mourn_inferior? */
24e60978
SC
2229}
2230
24e60978 2231static void
dc05df57 2232windows_prepare_to_store (struct regcache *regcache)
24e60978 2233{
581e13c1 2234 /* Do nothing, since we can store individual regs. */
24e60978
SC
2235}
2236
2237static int
dc05df57 2238windows_can_run (void)
24e60978
SC
2239{
2240 return 1;
2241}
2242
2243static void
dc05df57 2244windows_close (int x)
24e60978 2245{
dc05df57 2246 DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
3bccec63 2247 PIDGET (inferior_ptid)));
24e60978 2248}
1ef980b9 2249
581e13c1 2250/* Convert pid to printable format. */
3ee6f623 2251static char *
117de6a9 2252windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
24e60978 2253{
3ee6f623 2254 static char buf[80];
3ee6f623 2255
2dc38344
PA
2256 if (ptid_get_tid (ptid) != 0)
2257 {
2258 snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
2259 ptid_get_pid (ptid), ptid_get_tid (ptid));
2260 return buf;
2261 }
2262
2263 return normal_pid_to_str (ptid);
3ee6f623
CF
2264}
2265
de1b3c3d 2266static LONGEST
dc05df57 2267windows_xfer_shared_libraries (struct target_ops *ops,
de1b3c3d
PA
2268 enum target_object object, const char *annex,
2269 gdb_byte *readbuf, const gdb_byte *writebuf,
2270 ULONGEST offset, LONGEST len)
3cb8e7f6 2271{
de1b3c3d
PA
2272 struct obstack obstack;
2273 const char *buf;
2274 LONGEST len_avail;
3cb8e7f6 2275 struct so_list *so;
3cb8e7f6 2276
de1b3c3d
PA
2277 if (writebuf)
2278 return -1;
3cb8e7f6 2279
de1b3c3d
PA
2280 obstack_init (&obstack);
2281 obstack_grow_str (&obstack, "<library-list>\n");
2282 for (so = solib_start.next; so; so = so->next)
581e13c1
MS
2283 windows_xfer_shared_library (so->so_name, (CORE_ADDR)
2284 (uintptr_t) so->lm_info->load_addr,
5af949e3 2285 target_gdbarch, &obstack);
de1b3c3d 2286 obstack_grow_str0 (&obstack, "</library-list>\n");
3cb8e7f6 2287
de1b3c3d
PA
2288 buf = obstack_finish (&obstack);
2289 len_avail = strlen (buf);
2290 if (offset >= len_avail)
2291 return 0;
3cb8e7f6 2292
de1b3c3d
PA
2293 if (len > len_avail - offset)
2294 len = len_avail - offset;
2295 memcpy (readbuf, buf + offset, len);
3cb8e7f6 2296
de1b3c3d
PA
2297 obstack_free (&obstack, NULL);
2298 return len;
3cb8e7f6
CF
2299}
2300
de1b3c3d 2301static LONGEST
dc05df57 2302windows_xfer_partial (struct target_ops *ops, enum target_object object,
de1b3c3d
PA
2303 const char *annex, gdb_byte *readbuf,
2304 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
3cb8e7f6 2305{
de1b3c3d 2306 switch (object)
3cb8e7f6 2307 {
de1b3c3d
PA
2308 case TARGET_OBJECT_MEMORY:
2309 if (readbuf)
2310 return (*ops->deprecated_xfer_memory) (offset, readbuf,
244e85c8 2311 len, 0/*read*/, NULL, ops);
de1b3c3d
PA
2312 if (writebuf)
2313 return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
2314 len, 1/*write*/, NULL, ops);
2315 return -1;
2316
2317 case TARGET_OBJECT_LIBRARIES:
dc05df57 2318 return windows_xfer_shared_libraries (ops, object, annex, readbuf,
de1b3c3d 2319 writebuf, offset, len);
3929abe9 2320
de1b3c3d
PA
2321 default:
2322 if (ops->beneath != NULL)
2323 return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
2324 readbuf, writebuf, offset, len);
2325 return -1;
3929abe9 2326 }
02c5aecd
CF
2327}
2328
711e434b
PM
2329/* Provide thread local base, i.e. Thread Information Block address.
2330 Returns 1 if ptid is found and sets *ADDR to thread_local_base. */
2331
2332static int
2333windows_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
2334{
2335 thread_info *th;
2336
2337 th = thread_rec (ptid_get_tid (ptid), 0);
2338 if (th == NULL)
2339 return 0;
2340
2341 if (addr != NULL)
2342 *addr = th->thread_local_base;
2343
2344 return 1;
2345}
2346
1e2f1c5c
JB
2347static ptid_t
2348windows_get_ada_task_ptid (long lwp, long thread)
2349{
2350 return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
2351}
2352
3ee6f623 2353static void
dc05df57 2354init_windows_ops (void)
3ee6f623 2355{
dc05df57
CF
2356 windows_ops.to_shortname = "child";
2357 windows_ops.to_longname = "Win32 child process";
2358 windows_ops.to_doc = "Win32 child process (started by the \"run\" command).";
2359 windows_ops.to_open = windows_open;
2360 windows_ops.to_close = windows_close;
2361 windows_ops.to_attach = windows_attach;
2362 windows_ops.to_attach_no_wait = 1;
2363 windows_ops.to_detach = windows_detach;
2364 windows_ops.to_resume = windows_resume;
2365 windows_ops.to_wait = windows_wait;
2366 windows_ops.to_fetch_registers = windows_fetch_inferior_registers;
2367 windows_ops.to_store_registers = windows_store_inferior_registers;
2368 windows_ops.to_prepare_to_store = windows_prepare_to_store;
2369 windows_ops.deprecated_xfer_memory = windows_xfer_memory;
2370 windows_ops.to_xfer_partial = windows_xfer_partial;
2371 windows_ops.to_files_info = windows_files_info;
2372 windows_ops.to_insert_breakpoint = memory_insert_breakpoint;
2373 windows_ops.to_remove_breakpoint = memory_remove_breakpoint;
2374 windows_ops.to_terminal_init = terminal_init_inferior;
2375 windows_ops.to_terminal_inferior = terminal_inferior;
2376 windows_ops.to_terminal_ours_for_output = terminal_ours_for_output;
2377 windows_ops.to_terminal_ours = terminal_ours;
2378 windows_ops.to_terminal_save_ours = terminal_save_ours;
2379 windows_ops.to_terminal_info = child_terminal_info;
2380 windows_ops.to_kill = windows_kill_inferior;
2381 windows_ops.to_create_inferior = windows_create_inferior;
2382 windows_ops.to_mourn_inferior = windows_mourn_inferior;
2383 windows_ops.to_can_run = windows_can_run;
2384 windows_ops.to_thread_alive = windows_thread_alive;
2385 windows_ops.to_pid_to_str = windows_pid_to_str;
2386 windows_ops.to_stop = windows_stop;
2387 windows_ops.to_stratum = process_stratum;
c35b1492
PA
2388 windows_ops.to_has_all_memory = default_child_has_all_memory;
2389 windows_ops.to_has_memory = default_child_has_memory;
2390 windows_ops.to_has_stack = default_child_has_stack;
2391 windows_ops.to_has_registers = default_child_has_registers;
2392 windows_ops.to_has_execution = default_child_has_execution;
dc05df57 2393 windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
1e2f1c5c 2394 windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
711e434b 2395 windows_ops.to_get_tib_address = windows_get_tib_address;
9bb9e8ad 2396
5aca5a82
PM
2397 i386_use_watchpoints (&windows_ops);
2398
9bb9e8ad
PM
2399 i386_dr_low.set_control = cygwin_set_dr7;
2400 i386_dr_low.set_addr = cygwin_set_dr;
2401 i386_dr_low.reset_addr = NULL;
2402 i386_dr_low.get_status = cygwin_get_dr6;
2403
2404 /* i386_dr_low.debug_register_length field is set by
2405 calling i386_set_debug_register_length function
2406 in processor windows specific native file. */
2407
dc05df57 2408 windows_ops.to_magic = OPS_MAGIC;
c719b714 2409}
24e60978 2410
3929abe9 2411static void
dc05df57 2412set_windows_aliases (char *argv0)
3929abe9
CF
2413{
2414 add_info_alias ("dll", "sharedlibrary", 1);
2415}
2416
24e60978 2417void
dc05df57 2418_initialize_windows_nat (void)
24e60978 2419{
fa58ee11
EZ
2420 struct cmd_list_element *c;
2421
dc05df57 2422 init_windows_ops ();
1ef980b9 2423
d0d0ab16
CV
2424#ifdef __CYGWIN__
2425 cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
2426#endif
2427
fa58ee11 2428 c = add_com ("dll-symbols", class_files, dll_symbol_command,
1bedd215 2429 _("Load dll library symbols from FILE."));
5ba2abeb 2430 set_cmd_completer (c, filename_completer);
450005e7
CF
2431
2432 add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
2433
70992597
PM
2434 add_com_alias ("add-shared-symbol-files", "dll-symbols", class_alias, 1);
2435
2436 add_com_alias ("assf", "dll-symbols", class_alias, 1);
2437
10325bc5 2438#ifdef __CYGWIN__
5bf193a2
AC
2439 add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\
2440Set use of shell to start subprocess."), _("\
2441Show use of shell to start subprocess."), NULL,
2442 NULL,
2443 NULL, /* FIXME: i18n: */
2444 &setlist, &showlist);
2445
581e13c1
MS
2446 add_setshow_boolean_cmd ("cygwin-exceptions", class_support,
2447 &cygwin_exceptions, _("\
09280ddf
CF
2448Break when an exception is detected in the Cygwin DLL itself."), _("\
2449Show whether gdb breaks on exceptions in the Cygwin DLL itself."), NULL,
2450 NULL,
2451 NULL, /* FIXME: i18n: */
2452 &setlist, &showlist);
10325bc5 2453#endif
09280ddf 2454
5bf193a2
AC
2455 add_setshow_boolean_cmd ("new-console", class_support, &new_console, _("\
2456Set creation of new console when creating child process."), _("\
2457Show creation of new console when creating child process."), NULL,
2458 NULL,
2459 NULL, /* FIXME: i18n: */
2460 &setlist, &showlist);
2461
2462 add_setshow_boolean_cmd ("new-group", class_support, &new_group, _("\
2463Set creation of new group when creating child process."), _("\
2464Show creation of new group when creating child process."), NULL,
2465 NULL,
2466 NULL, /* FIXME: i18n: */
2467 &setlist, &showlist);
2468
2469 add_setshow_boolean_cmd ("debugexec", class_support, &debug_exec, _("\
2470Set whether to display execution in child process."), _("\
2471Show whether to display execution in child process."), NULL,
2472 NULL,
2473 NULL, /* FIXME: i18n: */
2474 &setlist, &showlist);
2475
2476 add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\
2477Set whether to display kernel events in child process."), _("\
2478Show whether to display kernel events in child process."), NULL,
2479 NULL,
2480 NULL, /* FIXME: i18n: */
2481 &setlist, &showlist);
2482
2483 add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\
2484Set whether to display memory accesses in child process."), _("\
2485Show whether to display memory accesses in child process."), NULL,
2486 NULL,
2487 NULL, /* FIXME: i18n: */
2488 &setlist, &showlist);
2489
2490 add_setshow_boolean_cmd ("debugexceptions", class_support,
2491 &debug_exceptions, _("\
2492Set whether to display kernel exceptions in child process."), _("\
2493Show whether to display kernel exceptions in child process."), NULL,
2494 NULL,
2495 NULL, /* FIXME: i18n: */
2496 &setlist, &showlist);
1ef980b9 2497
711e434b 2498 init_w32_command_list ();
c1748f97
PM
2499
2500 add_cmd ("selector", class_info, display_selectors,
1a966eab 2501 _("Display selectors infos."),
c1748f97 2502 &info_w32_cmdlist);
dc05df57
CF
2503 add_target (&windows_ops);
2504 deprecated_init_ui_hook = set_windows_aliases;
24e60978 2505}
3cee93ac 2506
fa4ba8da
PM
2507/* Hardware watchpoint support, adapted from go32-nat.c code. */
2508
2509/* Pass the address ADDR to the inferior in the I'th debug register.
2510 Here we just store the address in dr array, the registers will be
dc05df57 2511 actually set up when windows_continue is called. */
9bb9e8ad 2512static void
fa4ba8da
PM
2513cygwin_set_dr (int i, CORE_ADDR addr)
2514{
2515 if (i < 0 || i > 3)
2516 internal_error (__FILE__, __LINE__,
e2e0b3e5 2517 _("Invalid register %d in cygwin_set_dr.\n"), i);
41b4aadc 2518 dr[i] = addr;
fa4ba8da
PM
2519 debug_registers_changed = 1;
2520 debug_registers_used = 1;
2521}
2522
2523/* Pass the value VAL to the inferior in the DR7 debug control
2524 register. Here we just store the address in D_REGS, the watchpoint
dc05df57 2525 will be actually set up in windows_wait. */
9bb9e8ad
PM
2526static void
2527cygwin_set_dr7 (unsigned long val)
fa4ba8da 2528{
9bb9e8ad 2529 dr[7] = (CORE_ADDR) val;
fa4ba8da
PM
2530 debug_registers_changed = 1;
2531 debug_registers_used = 1;
2532}
2533
2534/* Get the value of the DR6 debug status register from the inferior.
2535 Here we just return the value stored in dr[6]
2536 by the last call to thread_rec for current_event.dwThreadId id. */
9bb9e8ad 2537static unsigned long
fa4ba8da
PM
2538cygwin_get_dr6 (void)
2539{
9bb9e8ad 2540 return (unsigned long) dr[6];
fa4ba8da
PM
2541}
2542
2dc38344 2543/* Determine if the thread referenced by "ptid" is alive
3cee93ac 2544 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
581e13c1 2545 it means that the thread has died. Otherwise it is assumed to be alive. */
3cee93ac 2546static int
28439f5e 2547windows_thread_alive (struct target_ops *ops, ptid_t ptid)
3cee93ac 2548{
2dc38344
PA
2549 int tid;
2550
2551 gdb_assert (ptid_get_tid (ptid) != 0);
2552 tid = ptid_get_tid (ptid);
39f77062 2553
581e13c1
MS
2554 return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0
2555 ? FALSE : TRUE;
3cee93ac
CF
2556}
2557
2a3d5645
CF
2558void
2559_initialize_check_for_gdb_ini (void)
2560{
2561 char *homedir;
2562 if (inhibit_gdbinit)
2563 return;
2564
2565 homedir = getenv ("HOME");
2566 if (homedir)
2567 {
2568 char *p;
2569 char *oldini = (char *) alloca (strlen (homedir) +
2570 sizeof ("/gdb.ini"));
2571 strcpy (oldini, homedir);
2572 p = strchr (oldini, '\0');
0ba1096a 2573 if (p > oldini && !IS_DIR_SEPARATOR (p[-1]))
2a3d5645
CF
2574 *p++ = '/';
2575 strcpy (p, "gdb.ini");
2576 if (access (oldini, 0) == 0)
2577 {
2578 int len = strlen (oldini);
2579 char *newini = alloca (len + 1);
dfe7f3ac 2580 sprintf (newini, "%.*s.gdbinit",
58fa08f0 2581 (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
8a3fe4f8 2582 warning (_("obsolete '%s' found. Rename to '%s'."), oldini, newini);
2a3d5645
CF
2583 }
2584 }
2585}
33605d39 2586
2b008701 2587/* Define dummy functions which always return error for the rare cases where
581e13c1 2588 these functions could not be found. */
2b008701
CF
2589static BOOL WINAPI
2590bad_DebugActiveProcessStop (DWORD w)
2591{
2592 return FALSE;
2593}
2594static BOOL WINAPI
2595bad_DebugBreakProcess (HANDLE w)
2596{
2597 return FALSE;
2598}
2599static BOOL WINAPI
2600bad_DebugSetProcessKillOnExit (BOOL w)
2601{
2602 return FALSE;
2603}
2604static BOOL WINAPI
2605bad_EnumProcessModules (HANDLE w, HMODULE *x, DWORD y, LPDWORD z)
2606{
2607 return FALSE;
2608}
b3c613f2
CF
2609
2610#ifdef __USEWIDE
2b008701 2611static DWORD WINAPI
b3c613f2 2612bad_GetModuleFileNameExW (HANDLE w, HMODULE x, LPWSTR y, DWORD z)
2b008701
CF
2613{
2614 return 0;
2615}
d0d0ab16
CV
2616#else
2617static DWORD WINAPI
b3c613f2 2618bad_GetModuleFileNameExA (HANDLE w, HMODULE x, LPSTR y, DWORD z)
d0d0ab16
CV
2619{
2620 return 0;
2621}
2622#endif
b3c613f2 2623
2b008701
CF
2624static BOOL WINAPI
2625bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
2626{
2627 return FALSE;
2628}
2629
418c6cb3
CF
2630static BOOL WINAPI
2631bad_OpenProcessToken (HANDLE w, DWORD x, PHANDLE y)
2632{
2633 return FALSE;
2634}
2635
cd44747c
PM
2636static BOOL WINAPI
2637bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
2638{
2639 f->nFont = 0;
2640 return 1;
2641}
2642static COORD WINAPI
2643bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
2644{
2645 COORD size;
2646 size.X = 8;
2647 size.Y = 12;
2648 return size;
2649}
2650
2b008701 2651/* Load any functions which may not be available in ancient versions
581e13c1 2652 of Windows. */
33605d39 2653void
2b008701 2654_initialize_loadable (void)
33605d39 2655{
2b008701
CF
2656 HMODULE hm = NULL;
2657
2658 hm = LoadLibrary ("kernel32.dll");
2659 if (hm)
33605d39 2660 {
b3c613f2 2661 DebugActiveProcessStop = (void *)
2b008701 2662 GetProcAddress (hm, "DebugActiveProcessStop");
b3c613f2 2663 DebugBreakProcess = (void *)
2b008701 2664 GetProcAddress (hm, "DebugBreakProcess");
b3c613f2 2665 DebugSetProcessKillOnExit = (void *)
2b008701 2666 GetProcAddress (hm, "DebugSetProcessKillOnExit");
cd44747c
PM
2667 GetConsoleFontSize = (void *)
2668 GetProcAddress (hm, "GetConsoleFontSize");
2669 GetCurrentConsoleFont = (void *)
2670 GetProcAddress (hm, "GetCurrentConsoleFont");
2b008701 2671 }
33605d39 2672
2b008701 2673 /* Set variables to dummy versions of these processes if the function
581e13c1 2674 wasn't found in kernel32.dll. */
b3c613f2
CF
2675 if (!DebugBreakProcess)
2676 DebugBreakProcess = bad_DebugBreakProcess;
2677 if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
2b008701 2678 {
b3c613f2
CF
2679 DebugActiveProcessStop = bad_DebugActiveProcessStop;
2680 DebugSetProcessKillOnExit = bad_DebugSetProcessKillOnExit;
2b008701 2681 }
cd44747c
PM
2682 if (!GetConsoleFontSize)
2683 GetConsoleFontSize = bad_GetConsoleFontSize;
2684 if (!GetCurrentConsoleFont)
2685 GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
33605d39 2686
2b008701 2687 /* Load optional functions used for retrieving filename information
581e13c1 2688 associated with the currently debugged process or its dlls. */
2b008701
CF
2689 hm = LoadLibrary ("psapi.dll");
2690 if (hm)
2691 {
b3c613f2 2692 EnumProcessModules = (void *)
2b008701 2693 GetProcAddress (hm, "EnumProcessModules");
b3c613f2 2694 GetModuleInformation = (void *)
2b008701 2695 GetProcAddress (hm, "GetModuleInformation");
b3c613f2
CF
2696 GetModuleFileNameEx = (void *)
2697 GetProcAddress (hm, GetModuleFileNameEx_name);
33605d39
CF
2698 }
2699
b3c613f2 2700 if (!EnumProcessModules || !GetModuleInformation || !GetModuleFileNameEx)
2b008701
CF
2701 {
2702 /* Set variables to dummy versions of these processes if the function
581e13c1 2703 wasn't found in psapi.dll. */
b3c613f2
CF
2704 EnumProcessModules = bad_EnumProcessModules;
2705 GetModuleInformation = bad_GetModuleInformation;
2706 GetModuleFileNameEx = bad_GetModuleFileNameEx;
581e13c1
MS
2707 /* This will probably fail on Windows 9x/Me. Let the user know
2708 that we're missing some functionality. */
2709 warning(_("\
2710cannot automatically find executable file or library to read symbols.\n\
2711Use \"file\" or \"dll\" command to load executable/libraries directly."));
418c6cb3
CF
2712 }
2713
2714 hm = LoadLibrary ("advapi32.dll");
2715 if (hm)
2716 {
b3c613f2
CF
2717 OpenProcessToken = (void *) GetProcAddress (hm, "OpenProcessToken");
2718 LookupPrivilegeValueA = (void *)
418c6cb3 2719 GetProcAddress (hm, "LookupPrivilegeValueA");
b3c613f2 2720 AdjustTokenPrivileges = (void *)
418c6cb3
CF
2721 GetProcAddress (hm, "AdjustTokenPrivileges");
2722 /* Only need to set one of these since if OpenProcessToken fails nothing
581e13c1
MS
2723 else is needed. */
2724 if (!OpenProcessToken || !LookupPrivilegeValueA
2725 || !AdjustTokenPrivileges)
b3c613f2 2726 OpenProcessToken = bad_OpenProcessToken;
2b008701 2727 }
33605d39 2728}
This page took 1.938843 seconds and 4 git commands to generate.