From 31b060a20f9c8b39d8b16c3c6e44b20d17d60c27 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 12 Jan 2009 01:10:28 +0000 Subject: [PATCH] Fix linking with --enable-targets=all: * Makefile.in (ALL_TARGET_OBS): Add windows-tdep.o. (HFILES_NO_SRCDIR): Add windows-tdep.h. (ALLDEPFILES): Add windows-tdep.c. * win32-tdep.h: Delete. * windows-tdep.h: Rename from win32-tdep.h. * win32-nat.h: Delete. * windows-nat.h: Rename from win32-nat.h. * win32-nat.c: Delete. * windows-nat.c: Rename from win32-nat.c. * win32-termcap.c: Delete. * windows-termcap.c: Rename from win32-termcap.c. * amd64-windows-nat.c: Handle rename from win32-nat.h -> windows-nat.h. * configure.ac: Handle rename from win32-termcap.c -> windows-termcap.c. * configure: Regenerate. * gdb_curses.h: Change comment to reflect rename from win32-termcap.c -> windows-termcap.c. * i386-cygwin-tdep.c: Handle rename from win32-tdep.h -> windows-tdep.h. * i386-windows-nat.c: Refect rename from win32-nat.h -> windows-nat.h. * windows-nat.c: Ditto. Also reflect rename from from win32-tdep.h -> windows-tdep.h. (win32_make_so): Handle cygwin compiler warning due to change of load_addr from DWORD to LPVOID. (handle_load_dll): Use %p in format string to properly print address and avoid a compiler warning. (DEBUG_EXCEPTION_SIMPLE): Ditto. (handle_exception): Ditto. * windows-tdep.c: Handle rename from win32-tdep.h -> windows-tdep.h. * config/i386/cygwin.mh: Handle rename from win32-nat.o -> windows-nat.o. * config/i386/mingw.mh: Ditto. * config/i386/mingw64.mh: Ditto. --- gdb/ChangeLog | 38 + gdb/Makefile.in | 7 +- gdb/amd64-windows-nat.c | 2 +- gdb/config/i386/cygwin.mh | 2 +- gdb/config/i386/mingw.mh | 2 +- gdb/config/i386/mingw64.mh | 2 +- gdb/configure | 2 +- gdb/configure.ac | 2 +- gdb/configure.tgt | 6 +- gdb/gdb_curses.h | 2 +- gdb/i386-cygwin-tdep.c | 2 +- gdb/i386-windows-nat.c | 2 +- gdb/win32-nat.c | 2339 ------------------------------------ gdb/win32-nat.h | 24 - gdb/win32-tdep.c | 41 - gdb/win32-tdep.h | 27 - gdb/win32-termcap.c | 65 - gdb/windows-nat.c | 14 +- gdb/windows-tdep.c | 2 +- 19 files changed, 62 insertions(+), 2519 deletions(-) delete mode 100644 gdb/win32-nat.c delete mode 100644 gdb/win32-nat.h delete mode 100644 gdb/win32-tdep.c delete mode 100644 gdb/win32-tdep.h delete mode 100644 gdb/win32-termcap.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2de10b846..73d7624551 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2009-01-11 Jan Kratochvil + + Fix linking with --enable-targets=all: + * Makefile.in (ALL_TARGET_OBS): Add windows-tdep.o. + (HFILES_NO_SRCDIR): Add windows-tdep.h. + (ALLDEPFILES): Add windows-tdep.c. + +2009-01-11 Christ Faylor + + * win32-nat.h: Delete. + * windows-nat.h: Rename from win32-nat.h. + * win32-nat.c: Delete. + * windows-nat.c: Rename from win32-nat.c. + * win32-termcap.c: Delete. + * windows-termcap.c: Rename from win32-termcap.c. + * amd64-windows-nat.c: Handle rename from win32-nat.h -> windows-nat.h. + * configure.ac: Handle rename from win32-termcap.c -> + windows-termcap.c. + * configure: Regenerate. + * gdb_curses.h: Change comment to reflect rename from win32-termcap.c + -> windows-termcap.c. + * i386-cygwin-tdep.c: Handle rename from win32-tdep.h -> + windows-tdep.h. + * i386-windows-nat.c: Refect rename from win32-nat.h -> windows-nat.h. + * windows-nat.c: Ditto. Also reflect rename from from win32-tdep.h -> + windows-tdep.h. + (win32_make_so): Handle cygwin compiler warning due to change of + load_addr from DWORD to LPVOID. + (handle_load_dll): Use %p in format string to properly print address + and avoid a compiler warning. + (DEBUG_EXCEPTION_SIMPLE): Ditto. + (handle_exception): Ditto. + * windows-tdep.c: Handle rename from win32-tdep.h -> windows-tdep.h. + * config/i386/cygwin.mh: Handle rename from win32-nat.o -> + windows-nat.o. + * config/i386/mingw.mh: Ditto. + * config/i386/mingw64.mh: Ditto. + 2009-01-11 Jan Kratochvil * f-typeprint.c (f_type_print_varspec_suffix): Convert the autovariable diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 2fe2d7a101..d8983c9bd6 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -515,7 +515,8 @@ ALL_TARGET_OBS = \ xcoffread.o \ prologue-value.o \ symfile-mem.o \ - corelow.o + corelow.o \ + windows-tdep.o # Host-dependent makefile fragment comes in here. @host_makefile_frag@ @@ -727,7 +728,7 @@ config/sparc/nm-sol2.h config/nm-linux.h config/mips/nm-irix5.h \ config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ -sentinel-frame.h bcache.h symfile.h +sentinel-frame.h bcache.h symfile.h windows-tdep.h # Header files that already have srcdir in them, or which are in objdir. @@ -1340,7 +1341,7 @@ ALLDEPFILES = \ spu-linux-nat.c spu-tdep.c \ v850-tdep.c \ vax-nat.c vax-tdep.c vaxbsd-nat.c vaxnbsd-tdep.c \ - win32-nat.c \ + windows-nat.c windows-tdep.c \ xcoffread.c xcoffsolib.c \ xstormy16-tdep.c \ xtensa-tdep.c xtensa-config.c \ diff --git a/gdb/amd64-windows-nat.c b/gdb/amd64-windows-nat.c index 88815a9fc4..a6ff2f6418 100644 --- a/gdb/amd64-windows-nat.c +++ b/gdb/amd64-windows-nat.c @@ -16,7 +16,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "win32-nat.h" +#include "windows-nat.h" #include diff --git a/gdb/config/i386/cygwin.mh b/gdb/config/i386/cygwin.mh index 5d7f75f687..5b5a143cf3 100644 --- a/gdb/config/i386/cygwin.mh +++ b/gdb/config/i386/cygwin.mh @@ -1,4 +1,4 @@ MH_CFLAGS= -NATDEPFILES= i386-nat.o win32-nat.o i386-windows-nat.o +NATDEPFILES= i386-nat.o windows-nat.o i386-windows-nat.o NAT_FILE=nm-cygwin.h XM_CLIBS= diff --git a/gdb/config/i386/mingw.mh b/gdb/config/i386/mingw.mh index 5d7f75f687..5b5a143cf3 100644 --- a/gdb/config/i386/mingw.mh +++ b/gdb/config/i386/mingw.mh @@ -1,4 +1,4 @@ MH_CFLAGS= -NATDEPFILES= i386-nat.o win32-nat.o i386-windows-nat.o +NATDEPFILES= i386-nat.o windows-nat.o i386-windows-nat.o NAT_FILE=nm-cygwin.h XM_CLIBS= diff --git a/gdb/config/i386/mingw64.mh b/gdb/config/i386/mingw64.mh index 6da61e5e46..20809b80a5 100644 --- a/gdb/config/i386/mingw64.mh +++ b/gdb/config/i386/mingw64.mh @@ -1,2 +1,2 @@ -NATDEPFILES= i386-nat.o win32-nat.o amd64-windows-nat.o +NATDEPFILES= i386-nat.o windows-nat.o amd64-windows-nat.o NAT_FILE=nm-cygwin64.h diff --git a/gdb/configure b/gdb/configure index bb2f7a5d85..59681f5e76 100755 --- a/gdb/configure +++ b/gdb/configure @@ -10170,7 +10170,7 @@ case $host_os in ;; *mingw32*) ac_cv_search_tgetent="none required" - CONFIG_OBS="$CONFIG_OBS win32-termcap.o" + CONFIG_OBS="$CONFIG_OBS windows-termcap.o" ;; esac diff --git a/gdb/configure.ac b/gdb/configure.ac index 4e0cf7deeb..56d40ad438 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -506,7 +506,7 @@ case $host_os in ;; *mingw32*) ac_cv_search_tgetent="none required" - CONFIG_OBS="$CONFIG_OBS win32-termcap.o" + CONFIG_OBS="$CONFIG_OBS windows-termcap.o" ;; esac diff --git a/gdb/configure.tgt b/gdb/configure.tgt index f5a43570d9..8bce78df49 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -201,13 +201,13 @@ i[34567]86-*-gnu*) i[34567]86-*-cygwin*) # Target: Intel 386 running win32 gdb_target_obs="i386-tdep.o i386-cygwin-tdep.o i387-tdep.o \ - solib-target.o corelow.o win32-tdep.o" + solib-target.o corelow.o windows-tdep.o" build_gdbserver=yes ;; i[34567]86-*-mingw32*) # Target: Intel 386 running win32 gdb_target_obs="i386-tdep.o i386-cygwin-tdep.o i387-tdep.o \ - solib-target.o corelow.o win32-tdep.o" + solib-target.o corelow.o windows-tdep.o" build_gdbserver=yes ;; i[34567]86-*-*) @@ -526,7 +526,7 @@ x86_64-*-mingw*) # Target: MingW/amd64 gdb_target_obs="amd64-tdep.o amd64-windows-tdep.o \ i386-tdep.o i386-cygwin-tdep.o i387-tdep.o \ - solib-target.o win32-tdep.o" + solib-target.o windows-tdep.o" ;; x86_64-*-netbsd* | x86_64-*-knetbsd*-gnu) # Target: NetBSD/amd64 diff --git a/gdb/gdb_curses.h b/gdb/gdb_curses.h index 29782bc707..ff1c5f5cb4 100644 --- a/gdb/gdb_curses.h +++ b/gdb/gdb_curses.h @@ -36,7 +36,7 @@ #include #else /* On MinGW, a real termcap library is usually not present. Stub versions - of the termcap functions will be built from win32-termcap.c. Readline + of the termcap functions will be built from windows-termcap.c. Readline provides its own extern declarations when there's no termcap.h; do the same here for the termcap functions used in GDB. */ extern int tgetnum (const char *); diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-cygwin-tdep.c index d639f5b2eb..c7088fdd8f 100644 --- a/gdb/i386-cygwin-tdep.c +++ b/gdb/i386-cygwin-tdep.c @@ -21,7 +21,7 @@ #include "osabi.h" #include "gdb_string.h" #include "i386-tdep.h" -#include "win32-tdep.h" +#include "windows-tdep.h" #include "regset.h" #include "gdb_obstack.h" #include "xml-support.h" diff --git a/gdb/i386-windows-nat.c b/gdb/i386-windows-nat.c index a22d6e8942..5de297c57d 100644 --- a/gdb/i386-windows-nat.c +++ b/gdb/i386-windows-nat.c @@ -16,7 +16,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "win32-nat.h" +#include "windows-nat.h" #include diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c deleted file mode 100644 index 9a1a28cfd5..0000000000 --- a/gdb/win32-nat.c +++ /dev/null @@ -1,2339 +0,0 @@ -/* Target-vector operations for controlling win32 child processes, for GDB. - - Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - Contributed by Cygnus Solutions, A Red Hat Company. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Originally by Steve Chamberlain, sac@cygnus.com */ - -#include "defs.h" -#include "frame.h" /* required by inferior.h */ -#include "inferior.h" -#include "target.h" -#include "exceptions.h" -#include "gdbcore.h" -#include "command.h" -#include "completer.h" -#include "regcache.h" -#include "top.h" -#include -#include -#include -#include -#include -#include -#ifdef __CYGWIN__ -#include -#endif -#include - -#include "buildsym.h" -#include "symfile.h" -#include "objfiles.h" -#include "gdb_obstack.h" -#include "gdb_string.h" -#include "gdbthread.h" -#include "gdbcmd.h" -#include -#include -#include "exec.h" -#include "solist.h" -#include "solib.h" -#include "xml-support.h" - -#include "i386-tdep.h" -#include "i387-tdep.h" - -#include "win32-tdep.h" -#include "win32-nat.h" - -static struct target_ops win32_ops; - -#ifdef __CYGWIN__ -/* The starting and ending address of the cygwin1.dll text segment. */ -static bfd_vma cygwin_load_start; -static bfd_vma cygwin_load_end; -#endif - -static int have_saved_context; /* True if we've saved context from a cygwin signal. */ -static CONTEXT saved_context; /* Containes the saved context from a cygwin signal. */ - -/* If we're not using the old Cygwin header file set, define the - following which never should have been in the generic Win32 API - headers in the first place since they were our own invention... */ -#ifndef _GNU_H_WINDOWS_H -enum - { - FLAG_TRACE_BIT = 0x100, - CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT) - }; -#endif -#include - -#ifndef CONTEXT_EXTENDED_REGISTERS -/* This macro is only defined on ia32. It only makes sense on this target, - so define it as zero if not already defined. */ -#define CONTEXT_EXTENDED_REGISTERS 0 -#endif - -#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \ - | CONTEXT_EXTENDED_REGISTERS - -static unsigned dr[8]; -static int debug_registers_changed; -static int debug_registers_used; -#define DR6_CLEAR_VALUE 0xffff0ff0 - -/* The string sent by cygwin when it processes a signal. - FIXME: This should be in a cygwin include file. */ -#ifndef _CYGWIN_SIGNAL_STRING -#define _CYGWIN_SIGNAL_STRING "cYgSiGw00f" -#endif - -#define CHECK(x) check (x, __FILE__,__LINE__) -#define DEBUG_EXEC(x) if (debug_exec) printf_unfiltered x -#define DEBUG_EVENTS(x) if (debug_events) printf_unfiltered x -#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x -#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x - -static void win32_stop (ptid_t); -static int win32_win32_thread_alive (ptid_t); -static void win32_kill_inferior (void); - -static enum target_signal last_sig = TARGET_SIGNAL_0; -/* Set if a signal was received from the debugged process */ - -/* Thread information structure used to track information that is - not available in gdb's thread structure. */ -typedef struct thread_info_struct - { - struct thread_info_struct *next; - DWORD id; - HANDLE h; - char *name; - int suspended; - int reload_context; - CONTEXT context; - STACKFRAME sf; - } -thread_info; - -static thread_info thread_head; - -/* The process and thread handles for the above context. */ - -static DEBUG_EVENT current_event; /* The current debug event from - WaitForDebugEvent */ -static HANDLE current_process_handle; /* Currently executing process */ -static thread_info *current_thread; /* Info on currently selected thread */ -static DWORD main_thread_id; /* Thread ID of the main thread */ - -/* Counts of things. */ -static int exception_count = 0; -static int event_count = 0; -static int saw_create; -static int open_process_used = 0; - -/* User options. */ -static int new_console = 0; -#ifdef __CYGWIN__ -static int cygwin_exceptions = 0; -#endif -static int new_group = 1; -static int debug_exec = 0; /* show execution */ -static int debug_events = 0; /* show events from kernel */ -static int debug_memory = 0; /* show target memory accesses */ -static int debug_exceptions = 0; /* show target exceptions */ -static int useshell = 0; /* use shell for subprocesses */ - -/* This vector maps GDB's idea of a register's number into an offset - in the win32 exception context vector. - - It also contains the bit mask needed to load the register in question. - - The contents of this table can only be computed by the units - that provide CPU-specific support for Windows native debugging. - These units should set the table by calling - win32_set_context_register_offsets. - - One day we could read a reg, we could inspect the context we - already have loaded, if it doesn't have the bit set that we need, - we read that set of registers in using GetThreadContext. If the - context already contains what we need, we just unpack it. Then to - write a register, first we have to ensure that the context contains - the other regs of the group, and then we copy the info in and set - out bit. */ - -static const int *mappings; - -/* This vector maps the target's idea of an exception (extracted - from the DEBUG_EVENT structure) to GDB's idea. */ - -struct xlate_exception - { - int them; - enum target_signal us; - }; - -static const struct xlate_exception - xlate[] = -{ - {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV}, - {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV}, - {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP}, - {DBG_CONTROL_C, TARGET_SIGNAL_INT}, - {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP}, - {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE}, - {-1, -1}}; - -/* Set the MAPPINGS static global to OFFSETS. - See the description of MAPPINGS for more details. */ - -void -win32_set_context_register_offsets (const int *offsets) -{ - mappings = offsets; -} - -static void -check (BOOL ok, const char *file, int line) -{ - if (!ok) - printf_filtered ("error return %s:%d was %lu\n", file, line, - GetLastError ()); -} - -/* Find a thread record given a thread id. If GET_CONTEXT is not 0, - then also retrieve the context for this thread. If GET_CONTEXT is - negative, then don't suspend the thread. */ -static thread_info * -thread_rec (DWORD id, int get_context) -{ - thread_info *th; - - for (th = &thread_head; (th = th->next) != NULL;) - if (th->id == id) - { - if (!th->suspended && get_context) - { - if (get_context > 0 && id != current_event.dwThreadId) - { - if (SuspendThread (th->h) == (DWORD) -1) - { - DWORD err = GetLastError (); - warning (_("SuspendThread failed. (winerr %d)"), - (int) err); - return NULL; - } - th->suspended = 1; - } - else if (get_context < 0) - th->suspended = -1; - th->reload_context = 1; - } - return th; - } - - return NULL; -} - -/* Add a thread to the thread list. */ -static thread_info * -win32_add_thread (ptid_t ptid, HANDLE h) -{ - thread_info *th; - DWORD id; - - gdb_assert (ptid_get_tid (ptid) != 0); - - id = ptid_get_tid (ptid); - - if ((th = thread_rec (id, FALSE))) - return th; - - th = XZALLOC (thread_info); - th->id = id; - th->h = h; - th->next = thread_head.next; - thread_head.next = th; - add_thread (ptid); - /* Set the debug registers for the new thread if they are used. */ - if (debug_registers_used) - { - /* Only change the value of the debug registers. */ - th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS; - CHECK (GetThreadContext (th->h, &th->context)); - th->context.Dr0 = dr[0]; - th->context.Dr1 = dr[1]; - th->context.Dr2 = dr[2]; - th->context.Dr3 = dr[3]; - th->context.Dr6 = DR6_CLEAR_VALUE; - th->context.Dr7 = dr[7]; - CHECK (SetThreadContext (th->h, &th->context)); - th->context.ContextFlags = 0; - } - return th; -} - -/* Clear out any old thread list and reintialize it to a - pristine state. */ -static void -win32_init_thread_list (void) -{ - thread_info *th = &thread_head; - - DEBUG_EVENTS (("gdb: win32_init_thread_list\n")); - init_thread_list (); - while (th->next != NULL) - { - thread_info *here = th->next; - th->next = here->next; - xfree (here); - } - thread_head.next = NULL; -} - -/* Delete a thread from the list of threads */ -static void -win32_delete_thread (ptid_t ptid) -{ - thread_info *th; - DWORD id; - - gdb_assert (ptid_get_tid (ptid) != 0); - - id = ptid_get_tid (ptid); - - if (info_verbose) - printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid)); - delete_thread (ptid); - - for (th = &thread_head; - th->next != NULL && th->next->id != id; - th = th->next) - continue; - - if (th->next != NULL) - { - thread_info *here = th->next; - th->next = here->next; - xfree (here); - } -} - -static void -do_win32_fetch_inferior_registers (struct regcache *regcache, int r) -{ - char *context_offset = ((char *) ¤t_thread->context) + mappings[r]; - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - long l; - - if (!current_thread) - return; /* Windows sometimes uses a non-existent thread id in its - events */ - - if (current_thread->reload_context) - { -#ifdef __COPY_CONTEXT_SIZE - if (have_saved_context) - { - /* Lie about where the program actually is stopped since cygwin has informed us that - we should consider the signal to have occurred at another location which is stored - in "saved_context. */ - memcpy (¤t_thread->context, &saved_context, __COPY_CONTEXT_SIZE); - have_saved_context = 0; - } - else -#endif - { - thread_info *th = current_thread; - th->context.ContextFlags = CONTEXT_DEBUGGER_DR; - GetThreadContext (th->h, &th->context); - /* Copy dr values from that thread. - But only if there were not modified since last stop. PR gdb/2388 */ - if (!debug_registers_changed) - { - dr[0] = th->context.Dr0; - dr[1] = th->context.Dr1; - dr[2] = th->context.Dr2; - dr[3] = th->context.Dr3; - dr[6] = th->context.Dr6; - dr[7] = th->context.Dr7; - } - } - current_thread->reload_context = 0; - } - - if (r == I387_FISEG_REGNUM (tdep)) - { - l = *((long *) context_offset) & 0xffff; - regcache_raw_supply (regcache, r, (char *) &l); - } - else if (r == I387_FOP_REGNUM (tdep)) - { - l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1); - regcache_raw_supply (regcache, r, (char *) &l); - } - else if (r >= 0) - regcache_raw_supply (regcache, r, context_offset); - else - { - for (r = 0; r < gdbarch_num_regs (gdbarch); r++) - do_win32_fetch_inferior_registers (regcache, r); - } -} - -static void -win32_fetch_inferior_registers (struct regcache *regcache, int r) -{ - current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE); - /* Check if current_thread exists. Windows sometimes uses a non-existent - thread id in its events */ - if (current_thread) - do_win32_fetch_inferior_registers (regcache, r); -} - -static void -do_win32_store_inferior_registers (const struct regcache *regcache, int r) -{ - if (!current_thread) - /* Windows sometimes uses a non-existent thread id in its events */; - else if (r >= 0) - regcache_raw_collect (regcache, r, - ((char *) ¤t_thread->context) + mappings[r]); - else - { - for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++) - do_win32_store_inferior_registers (regcache, r); - } -} - -/* Store a new register value into the current thread context */ -static void -win32_store_inferior_registers (struct regcache *regcache, int r) -{ - current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE); - /* Check if current_thread exists. Windows sometimes uses a non-existent - thread id in its events */ - if (current_thread) - do_win32_store_inferior_registers (regcache, r); -} - -static int psapi_loaded = 0; -static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, - LPDWORD); -static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, - DWORD); -static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, - DWORD); - -/* Get the name of a given module at at given base address. If base_address - is zero return the first loaded module (which is always the name of the - executable). */ -static int -get_module_name (LPVOID base_address, char *dll_name_ret) -{ - DWORD len; - MODULEINFO mi; - int i; - HMODULE dh_buf[1]; - HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */ - DWORD cbNeeded; -#ifdef __CYGWIN__ - char pathbuf[PATH_MAX + 1]; /* Temporary storage prior to converting to - posix form */ -#else - char *pathbuf = dll_name_ret; /* Just copy directly to passed-in arg */ -#endif - - /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain - the needed functions. */ - if (psapi_loaded <= 0) - goto failed; - - cbNeeded = 0; - /* Find size of buffer needed to handle list of modules loaded in inferior */ - if (!psapi_EnumProcessModules (current_process_handle, DllHandle, - sizeof (HMODULE), &cbNeeded) || !cbNeeded) - goto failed; - - /* Allocate correct amount of space for module list */ - DllHandle = (HMODULE *) alloca (cbNeeded); - if (!DllHandle) - goto failed; - - /* Get the list of modules */ - if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded, - &cbNeeded)) - goto failed; - - for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++) - { - /* Get information on this module */ - if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i], - &mi, sizeof (mi))) - error (_("Can't get module info")); - - if (!base_address || mi.lpBaseOfDll == base_address) - { - /* Try to find the name of the given module */ - len = psapi_GetModuleFileNameExA (current_process_handle, - DllHandle[i], pathbuf, MAX_PATH); - if (len == 0) - error (_("Error getting dll name: %u."), (unsigned) GetLastError ()); -#ifdef __CYGWIN__ - /* Cygwin prefers that the path be in /x/y/z format */ - cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret); -#endif - return 1; /* success */ - } - } - -failed: - dll_name_ret[0] = '\0'; - return 0; /* failure */ -} - -/* Encapsulate the information required in a call to - symbol_file_add_args */ -struct safe_symbol_file_add_args -{ - char *name; - int from_tty; - struct section_addr_info *addrs; - int mainline; - int flags; - struct ui_file *err, *out; - struct objfile *ret; -}; - -/* Maintain a linked list of "so" information. */ -struct lm_info -{ - LPVOID load_addr; -}; - -static struct so_list solib_start, *solib_end; - -/* Call symbol_file_add with stderr redirected. We don't care if there - are errors. */ -static int -safe_symbol_file_add_stub (void *argv) -{ -#define p ((struct safe_symbol_file_add_args *) argv) - p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags); - return !!p->ret; -#undef p -} - -/* Restore gdb's stderr after calling symbol_file_add */ -static void -safe_symbol_file_add_cleanup (void *p) -{ -#define sp ((struct safe_symbol_file_add_args *)p) - gdb_flush (gdb_stderr); - gdb_flush (gdb_stdout); - ui_file_delete (gdb_stderr); - ui_file_delete (gdb_stdout); - gdb_stderr = sp->err; - gdb_stdout = sp->out; -#undef sp -} - -/* symbol_file_add wrapper that prevents errors from being displayed. */ -static struct objfile * -safe_symbol_file_add (char *name, int from_tty, - struct section_addr_info *addrs, - int mainline, int flags) -{ - struct safe_symbol_file_add_args p; - struct cleanup *cleanup; - - cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p); - - p.err = gdb_stderr; - p.out = gdb_stdout; - gdb_flush (gdb_stderr); - gdb_flush (gdb_stdout); - gdb_stderr = ui_file_new (); - gdb_stdout = ui_file_new (); - p.name = name; - p.from_tty = from_tty; - p.addrs = addrs; - p.mainline = mainline; - p.flags = flags; - catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR); - - do_cleanups (cleanup); - return p.ret; -} - -static struct so_list * -win32_make_so (const char *name, LPVOID load_addr) -{ - struct so_list *so; - char buf[MAX_PATH + 1]; - char cwd[MAX_PATH + 1]; - char *p; - WIN32_FIND_DATA w32_fd; - HANDLE h = FindFirstFile(name, &w32_fd); - MEMORY_BASIC_INFORMATION m; - - if (h == INVALID_HANDLE_VALUE) - strcpy (buf, name); - else - { - FindClose (h); - strcpy (buf, name); - if (GetCurrentDirectory (MAX_PATH + 1, cwd)) - { - p = strrchr (buf, '\\'); - if (p) - p[1] = '\0'; - SetCurrentDirectory (buf); - GetFullPathName (w32_fd.cFileName, MAX_PATH, buf, &p); - SetCurrentDirectory (cwd); - } - } - - if (strcasecmp (buf, "ntdll.dll") == 0) - { - GetSystemDirectory (buf, sizeof (buf)); - strcat (buf, "\\ntdll.dll"); - } - so = XZALLOC (struct so_list); - so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info)); - so->lm_info->load_addr = load_addr; - strcpy (so->so_original_name, name); -#ifndef __CYGWIN__ - strcpy (so->so_name, buf); -#else - cygwin_conv_to_posix_path (buf, so->so_name); - /* Record cygwin1.dll .text start/end. */ - p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1); - if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0) - { - bfd *abfd; - asection *text = NULL; - CORE_ADDR text_vma; - - abfd = bfd_openr (so->so_name, "pei-i386"); - - if (!abfd) - return so; - - if (bfd_check_format (abfd, bfd_object)) - text = bfd_get_section_by_name (abfd, ".text"); - - if (!text) - { - bfd_close (abfd); - return so; - } - - /* The symbols in a dll are offset by 0x1000, which is the the - offset from 0 of the first byte in an image - because of the - file header and the section alignment. */ - cygwin_load_start = load_addr + 0x1000; - cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text); - - bfd_close (abfd); - } -#endif - - return so; -} - -static char * -get_image_name (HANDLE h, void *address, int unicode) -{ - static char buf[(2 * MAX_PATH) + 1]; - DWORD size = unicode ? sizeof (WCHAR) : sizeof (char); - char *address_ptr; - int len = 0; - char b[2]; - SIZE_T done; - - /* Attempt to read the name of the dll that was detected. - This is documented to work only when actively debugging - a program. It will not work for attached processes. */ - if (address == NULL) - return NULL; - - /* See if we could read the address of a string, and that the - address isn't null. */ - if (!ReadProcessMemory (h, address, &address_ptr, sizeof (address_ptr), &done) - || done != sizeof (address_ptr) || !address_ptr) - return NULL; - - /* Find the length of the string */ - while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done) - && (b[0] != 0 || b[size - 1] != 0) && done == size) - continue; - - if (!unicode) - ReadProcessMemory (h, address_ptr, buf, len, &done); - else - { - WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR)); - ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR), - &done); - - WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0); - } - - return buf; -} - -/* Wait for child to do something. Return pid of child, or -1 in case - of error; store status through argument pointer OURSTATUS. */ -static int -handle_load_dll (void *dummy) -{ - LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll; - char dll_buf[MAX_PATH + 1]; - char *dll_name = NULL; - - dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; - - if (!get_module_name (event->lpBaseOfDll, dll_buf)) - dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; - - dll_name = dll_buf; - - if (*dll_name == '\0') - dll_name = get_image_name (current_process_handle, - event->lpImageName, event->fUnicode); - if (!dll_name) - return 1; - - solib_end->next = win32_make_so (dll_name, event->lpBaseOfDll); - solib_end = solib_end->next; - - DEBUG_EVENTS (("gdb: Loading dll \"%s\" at 0x%lx.\n", solib_end->so_name, - solib_end->lm_info->load_addr)); - - return 1; -} - -static void -win32_free_so (struct so_list *so) -{ - if (so->lm_info) - xfree (so->lm_info); - xfree (so); -} - -static int -handle_unload_dll (void *dummy) -{ - LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll; - struct so_list *so; - - for (so = &solib_start; so->next != NULL; so = so->next) - if (so->next->lm_info->load_addr == lpBaseOfDll) - { - struct so_list *sodel = so->next; - so->next = sodel->next; - if (!so->next) - solib_end = so; - DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name)); - - win32_free_so (sodel); - solib_add (NULL, 0, NULL, auto_solib_add); - return 1; - } - - error (_("Error: dll starting at 0x%lx not found."), (DWORD) lpBaseOfDll); - - return 0; -} - -/* Clear list of loaded DLLs. */ -static void -win32_clear_solib (void) -{ - solib_start.next = NULL; - solib_end = &solib_start; -} - -/* Load DLL symbol info. */ -void -dll_symbol_command (char *args, int from_tty) -{ - int n; - dont_repeat (); - - if (args == NULL) - error (_("dll-symbols requires a file name")); - - n = strlen (args); - if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0) - { - char *newargs = (char *) alloca (n + 4 + 1); - strcpy (newargs, args); - strcat (newargs, ".dll"); - args = newargs; - } - - safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED); -} - -/* Handle DEBUG_STRING output from child process. - Cygwin prepends its messages with a "cygwin:". Interpret this as - a Cygwin signal. Otherwise just print the string as a warning. */ -static int -handle_output_debug_string (struct target_waitstatus *ourstatus) -{ - char *s = NULL; - int retval = 0; - - if (!target_read_string - ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData, - &s, 1024, 0) - || !s || !*s) - /* nothing to do */; - else if (strncmp (s, _CYGWIN_SIGNAL_STRING, sizeof (_CYGWIN_SIGNAL_STRING) - 1) != 0) - { -#ifdef __CYGWIN__ - if (strncmp (s, "cYg", 3) != 0) -#endif - warning (("%s"), s); - } -#ifdef __COPY_CONTEXT_SIZE - else - { - /* Got a cygwin signal marker. A cygwin signal is followed by the signal number - itself and then optionally followed by the thread id and address to saved context - within the DLL. If these are supplied, then the given thread is assumed to have - issued the signal and the context from the thread is assumed to be stored at the - given address in the inferior. Tell gdb to treat this like a real signal. */ - char *p; - int sig = strtol (s + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0); - int gotasig = target_signal_from_host (sig); - ourstatus->value.sig = gotasig; - if (gotasig) - { - LPCVOID x; - DWORD n; - ourstatus->kind = TARGET_WAITKIND_STOPPED; - retval = strtoul (p, &p, 0); - if (!retval) - retval = main_thread_id; - else if ((x = (LPCVOID) strtoul (p, &p, 0)) - && ReadProcessMemory (current_process_handle, x, - &saved_context, __COPY_CONTEXT_SIZE, &n) - && n == __COPY_CONTEXT_SIZE) - have_saved_context = 1; - current_event.dwThreadId = retval; - } - } -#endif - - if (s) - xfree (s); - return retval; -} - -static int -display_selector (HANDLE thread, DWORD sel) -{ - LDT_ENTRY info; - if (GetThreadSelectorEntry (thread, sel, &info)) - { - int base, limit; - printf_filtered ("0x%03lx: ", sel); - if (!info.HighWord.Bits.Pres) - { - puts_filtered ("Segment not present\n"); - return 0; - } - base = (info.HighWord.Bits.BaseHi << 24) + - (info.HighWord.Bits.BaseMid << 16) - + info.BaseLow; - limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow; - if (info.HighWord.Bits.Granularity) - limit = (limit << 12) | 0xfff; - printf_filtered ("base=0x%08x limit=0x%08x", base, limit); - if (info.HighWord.Bits.Default_Big) - puts_filtered(" 32-bit "); - else - puts_filtered(" 16-bit "); - switch ((info.HighWord.Bits.Type & 0xf) >> 1) - { - case 0: - puts_filtered ("Data (Read-Only, Exp-up"); - break; - case 1: - puts_filtered ("Data (Read/Write, Exp-up"); - break; - case 2: - puts_filtered ("Unused segment ("); - break; - case 3: - puts_filtered ("Data (Read/Write, Exp-down"); - break; - case 4: - puts_filtered ("Code (Exec-Only, N.Conf"); - break; - case 5: - puts_filtered ("Code (Exec/Read, N.Conf"); - break; - case 6: - puts_filtered ("Code (Exec-Only, Conf"); - break; - case 7: - puts_filtered ("Code (Exec/Read, Conf"); - break; - default: - printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type); - } - if ((info.HighWord.Bits.Type & 0x1) == 0) - puts_filtered(", N.Acc"); - puts_filtered (")\n"); - if ((info.HighWord.Bits.Type & 0x10) == 0) - puts_filtered("System selector "); - printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl); - if (info.HighWord.Bits.Granularity) - puts_filtered ("Page granular.\n"); - else - puts_filtered ("Byte granular.\n"); - return 1; - } - else - { - printf_filtered ("Invalid selector 0x%lx.\n",sel); - return 0; - } -} - -static void -display_selectors (char * args, int from_tty) -{ - if (!current_thread) - { - puts_filtered ("Impossible to display selectors now.\n"); - return; - } - if (!args) - { - - puts_filtered ("Selector $cs\n"); - display_selector (current_thread->h, - current_thread->context.SegCs); - puts_filtered ("Selector $ds\n"); - display_selector (current_thread->h, - current_thread->context.SegDs); - puts_filtered ("Selector $es\n"); - display_selector (current_thread->h, - current_thread->context.SegEs); - puts_filtered ("Selector $ss\n"); - display_selector (current_thread->h, - current_thread->context.SegSs); - puts_filtered ("Selector $fs\n"); - display_selector (current_thread->h, - current_thread->context.SegFs); - puts_filtered ("Selector $gs\n"); - display_selector (current_thread->h, - current_thread->context.SegGs); - } - else - { - int sel; - sel = parse_and_eval_long (args); - printf_filtered ("Selector \"%s\"\n",args); - display_selector (current_thread->h, sel); - } -} - -static struct cmd_list_element *info_w32_cmdlist = NULL; - -static void -info_w32_command (char *args, int from_tty) -{ - help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout); -} - - -#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ - printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \ - current_event.u.Exception.ExceptionRecord.ExceptionAddress) - -static int -handle_exception (struct target_waitstatus *ourstatus) -{ - thread_info *th; - DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode; - - ourstatus->kind = TARGET_WAITKIND_STOPPED; - - /* Record the context of the current thread */ - th = thread_rec (current_event.dwThreadId, -1); - - switch (code) - { - case EXCEPTION_ACCESS_VIOLATION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION"); - ourstatus->value.sig = TARGET_SIGNAL_SEGV; -#ifdef __CYGWIN__ - { - /* See if the access violation happened within the cygwin DLL itself. Cygwin uses - a kind of exception handling to deal with passed-in invalid addresses. gdb - should not treat these as real SEGVs since they will be silently handled by - cygwin. A real SEGV will (theoretically) be caught by cygwin later in the process - and will be sent as a cygwin-specific-signal. So, ignore SEGVs if they show up - within the text segment of the DLL itself. */ - char *fn; - bfd_vma addr = (bfd_vma) (uintptr_t) current_event.u.Exception. - ExceptionRecord.ExceptionAddress; - if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end)) - || (find_pc_partial_function (addr, &fn, NULL, NULL) - && strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0)) - return 0; - } -#endif - break; - case STATUS_STACK_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW"); - ourstatus->value.sig = TARGET_SIGNAL_SEGV; - break; - case STATUS_FLOAT_DENORMAL_OPERAND: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_INEXACT_RESULT: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_INVALID_OPERATION: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_STACK_CHECK: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_UNDERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_FLOAT_DIVIDE_BY_ZERO: - DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_INTEGER_DIVIDE_BY_ZERO: - DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case STATUS_INTEGER_OVERFLOW: - DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW"); - ourstatus->value.sig = TARGET_SIGNAL_FPE; - break; - case EXCEPTION_BREAKPOINT: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT"); - ourstatus->value.sig = TARGET_SIGNAL_TRAP; - break; - case DBG_CONTROL_C: - DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C"); - ourstatus->value.sig = TARGET_SIGNAL_INT; - break; - case DBG_CONTROL_BREAK: - DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK"); - ourstatus->value.sig = TARGET_SIGNAL_INT; - break; - case EXCEPTION_SINGLE_STEP: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP"); - ourstatus->value.sig = TARGET_SIGNAL_TRAP; - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION"); - ourstatus->value.sig = TARGET_SIGNAL_ILL; - break; - case EXCEPTION_PRIV_INSTRUCTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION"); - ourstatus->value.sig = TARGET_SIGNAL_ILL; - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION"); - ourstatus->value.sig = TARGET_SIGNAL_ILL; - break; - default: - /* Treat unhandled first chance exceptions specially. */ - if (current_event.u.Exception.dwFirstChance) - return -1; - printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n", - current_event.u.Exception.ExceptionRecord.ExceptionCode, - current_event.u.Exception.ExceptionRecord.ExceptionAddress); - ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; - break; - } - exception_count++; - last_sig = ourstatus->value.sig; - return 1; -} - -/* Resume all artificially suspended threads if we are continuing - execution */ -static BOOL -win32_continue (DWORD continue_status, int id) -{ - int i; - thread_info *th; - BOOL res; - - DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n", - current_event.dwProcessId, current_event.dwThreadId, - continue_status == DBG_CONTINUE ? - "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED")); - - for (th = &thread_head; (th = th->next) != NULL;) - if ((id == -1 || id == (int) th->id) - && th->suspended) - { - if (debug_registers_changed) - { - th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS; - th->context.Dr0 = dr[0]; - th->context.Dr1 = dr[1]; - th->context.Dr2 = dr[2]; - th->context.Dr3 = dr[3]; - th->context.Dr6 = DR6_CLEAR_VALUE; - th->context.Dr7 = dr[7]; - } - if (th->context.ContextFlags) - { - CHECK (SetThreadContext (th->h, &th->context)); - th->context.ContextFlags = 0; - } - if (th->suspended > 0) - (void) ResumeThread (th->h); - th->suspended = 0; - } - - res = ContinueDebugEvent (current_event.dwProcessId, - current_event.dwThreadId, - continue_status); - - debug_registers_changed = 0; - return res; -} - -/* Called in pathological case where Windows fails to send a - CREATE_PROCESS_DEBUG_EVENT after an attach. */ -static DWORD -fake_create_process (void) -{ - current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, - current_event.dwProcessId); - if (current_process_handle != NULL) - open_process_used = 1; - else - { - error (_("OpenProcess call failed, GetLastError = %lud\n"), - GetLastError ()); - /* We can not debug anything in that case. */ - } - main_thread_id = current_event.dwThreadId; - current_thread = win32_add_thread (ptid_build (current_event.dwProcessId, 0, - current_event.dwThreadId), - current_event.u.CreateThread.hThread); - return main_thread_id; -} - -static void -win32_resume (ptid_t ptid, int step, enum target_signal sig) -{ - thread_info *th; - DWORD continue_status = DBG_CONTINUE; - - /* A specific PTID means `step only this thread id'. */ - int resume_all = ptid_equal (ptid, minus_one_ptid); - - /* If we're continuing all threads, it's the current inferior that - should be handled specially. */ - if (resume_all) - ptid = inferior_ptid; - - if (sig != TARGET_SIGNAL_0) - { - if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) - { - DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig)); - } - else if (sig == last_sig) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - else -#if 0 -/* This code does not seem to work, because - the kernel does probably not consider changes in the ExceptionRecord - structure when passing the exception to the inferior. - Note that this seems possible in the exception handler itself. */ - { - int i; - for (i = 0; xlate[i].them != -1; i++) - if (xlate[i].us == sig) - { - current_event.u.Exception.ExceptionRecord.ExceptionCode = - xlate[i].them; - continue_status = DBG_EXCEPTION_NOT_HANDLED; - break; - } - if (continue_status == DBG_CONTINUE) - { - DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig)); - } - } -#endif - DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n", - last_sig)); - } - - last_sig = TARGET_SIGNAL_0; - - DEBUG_EXEC (("gdb: win32_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n", - ptid_get_pid (ptid), ptid_get_tid (ptid), step, sig)); - - /* Get context for currently selected thread */ - th = thread_rec (ptid_get_tid (inferior_ptid), FALSE); - if (th) - { - if (step) - { - /* Single step by setting t bit */ - win32_fetch_inferior_registers (get_current_regcache (), - gdbarch_ps_regnum (current_gdbarch)); - th->context.EFlags |= FLAG_TRACE_BIT; - } - - if (th->context.ContextFlags) - { - if (debug_registers_changed) - { - th->context.Dr0 = dr[0]; - th->context.Dr1 = dr[1]; - th->context.Dr2 = dr[2]; - th->context.Dr3 = dr[3]; - th->context.Dr6 = DR6_CLEAR_VALUE; - th->context.Dr7 = dr[7]; - } - CHECK (SetThreadContext (th->h, &th->context)); - th->context.ContextFlags = 0; - } - } - - /* Allow continuing with the same signal that interrupted us. - Otherwise complain. */ - - if (resume_all) - win32_continue (continue_status, -1); - else - win32_continue (continue_status, ptid_get_tid (ptid)); -} - -/* Get the next event from the child. Return 1 if the event requires - handling by WFI (or whatever). - */ -static int -get_win32_debug_event (int pid, struct target_waitstatus *ourstatus) -{ - BOOL debug_event; - DWORD continue_status, event_code; - thread_info *th; - static thread_info dummy_thread_info; - int retval = 0; - - last_sig = TARGET_SIGNAL_0; - - if (!(debug_event = WaitForDebugEvent (¤t_event, 1000))) - goto out; - - event_count++; - continue_status = DBG_CONTINUE; - - event_code = current_event.dwDebugEventCode; - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - th = NULL; - have_saved_context = 0; - - switch (event_code) - { - case CREATE_THREAD_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "CREATE_THREAD_DEBUG_EVENT")); - if (saw_create != 1) - { - struct inferior *inf; - inf = find_inferior_pid (current_event.dwProcessId); - if (!saw_create && inf->attach_flag) - { - /* Kludge around a Windows bug where first event is a create - thread event. Caused when attached process does not have - a main thread. */ - retval = fake_create_process (); - if (retval) - saw_create++; - } - break; - } - /* Record the existence of this thread */ - retval = current_event.dwThreadId; - th = win32_add_thread (ptid_build (current_event.dwProcessId, 0, - current_event.dwThreadId), - current_event.u.CreateThread.hThread); - break; - - case EXIT_THREAD_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "EXIT_THREAD_DEBUG_EVENT")); - if (current_event.dwThreadId != main_thread_id) - { - win32_delete_thread (ptid_build (current_event.dwProcessId, 0, - current_event.dwThreadId)); - th = &dummy_thread_info; - } - break; - - case CREATE_PROCESS_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "CREATE_PROCESS_DEBUG_EVENT")); - CloseHandle (current_event.u.CreateProcessInfo.hFile); - if (++saw_create != 1) - break; - - current_process_handle = current_event.u.CreateProcessInfo.hProcess; - if (main_thread_id) - win32_delete_thread (ptid_build (current_event.dwProcessId, 0, - main_thread_id)); - main_thread_id = current_event.dwThreadId; - /* Add the main thread */ - th = win32_add_thread (ptid_build (current_event.dwProcessId, 0, - current_event.dwThreadId), - current_event.u.CreateProcessInfo.hThread); - retval = current_event.dwThreadId; - break; - - case EXIT_PROCESS_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "EXIT_PROCESS_DEBUG_EVENT")); - if (saw_create != 1) - break; - ourstatus->kind = TARGET_WAITKIND_EXITED; - ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode; - retval = main_thread_id; - break; - - case LOAD_DLL_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "LOAD_DLL_DEBUG_EVENT")); - CloseHandle (current_event.u.LoadDll.hFile); - if (saw_create != 1) - break; - catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL); - ourstatus->kind = TARGET_WAITKIND_LOADED; - ourstatus->value.integer = 0; - retval = main_thread_id; - break; - - case UNLOAD_DLL_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "UNLOAD_DLL_DEBUG_EVENT")); - if (saw_create != 1) - break; - catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL); - ourstatus->kind = TARGET_WAITKIND_LOADED; - ourstatus->value.integer = 0; - retval = main_thread_id; - break; - - case EXCEPTION_DEBUG_EVENT: - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "EXCEPTION_DEBUG_EVENT")); - if (saw_create != 1) - break; - switch (handle_exception (ourstatus)) - { - case 0: - continue_status = DBG_EXCEPTION_NOT_HANDLED; - break; - case 1: - retval = current_event.dwThreadId; - break; - case -1: - last_sig = 1; - continue_status = -1; - break; - } - break; - - case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */ - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", - (unsigned) current_event.dwProcessId, - (unsigned) current_event.dwThreadId, - "OUTPUT_DEBUG_STRING_EVENT")); - if (saw_create != 1) - break; - retval = handle_output_debug_string (ourstatus); - break; - - default: - if (saw_create != 1) - break; - printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n", - (DWORD) current_event.dwProcessId, - (DWORD) current_event.dwThreadId); - printf_unfiltered (" unknown event code %ld\n", - current_event.dwDebugEventCode); - break; - } - - if (!retval || saw_create != 1) - { - if (continue_status == -1) - win32_resume (minus_one_ptid, 0, 1); - else - CHECK (win32_continue (continue_status, -1)); - } - else - { - inferior_ptid = ptid_build (current_event.dwProcessId, 0, - retval); - current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE); - } - -out: - return retval; -} - -/* Wait for interesting events to occur in the target process. */ -static ptid_t -win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus) -{ - int pid = -1; - - target_terminal_ours (); - - /* We loop when we get a non-standard exception rather than return - with a SPURIOUS because resume can try and step or modify things, - which needs a current_thread->h. But some of these exceptions mark - the birth or death of threads, which mean that the current thread - isn't necessarily what you think it is. */ - - while (1) - { - int retval; - - /* Ignore CTRL+C signals while waiting for a debug event. - FIXME: brobecker/2008-05-20: When the user presses CTRL+C while - the inferior is running, both the inferior and GDB receive the - associated signal. If the inferior receives the signal first - and the delay until GDB receives that signal is sufficiently long, - GDB can sometimes receive the SIGINT after we have unblocked - the CTRL+C handler. This would lead to the debugger to stop - prematurely while handling the new-thread event that comes - with the handling of the SIGINT inside the inferior, and then - stop again immediately when the user tries to resume the execution - in the inferior. This is a classic race, and it would be nice - to find a better solution to that problem. But in the meantime, - the current approach already greatly mitigate this issue. */ - SetConsoleCtrlHandler (NULL, TRUE); - retval = get_win32_debug_event (pid, ourstatus); - SetConsoleCtrlHandler (NULL, FALSE); - - if (retval) - return ptid_build (current_event.dwProcessId, 0, retval); - else - { - int detach = 0; - - if (deprecated_ui_loop_hook != NULL) - detach = deprecated_ui_loop_hook (0); - - if (detach) - win32_kill_inferior (); - } - } -} - -static void -do_initial_win32_stuff (struct target_ops *ops, DWORD pid, int attaching) -{ - extern int stop_after_trap; - int i; - struct inferior *inf; - struct thread_info *tp; - - last_sig = TARGET_SIGNAL_0; - event_count = 0; - exception_count = 0; - open_process_used = 0; - debug_registers_changed = 0; - debug_registers_used = 0; - for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++) - dr[i] = 0; -#ifdef __CYGWIN__ - cygwin_load_start = cygwin_load_end = 0; -#endif - current_event.dwProcessId = pid; - memset (¤t_event, 0, sizeof (current_event)); - push_target (ops); - disable_breakpoints_in_shlibs (); - win32_clear_solib (); - clear_proceed_status (); - init_wait_for_inferior (); - - inf = add_inferior (pid); - inf->attach_flag = attaching; - - /* Make the new process the current inferior, so terminal handling - can rely on it. When attaching, we don't know about any thread - id here, but that's OK --- nothing should be referencing the - current thread until we report an event out of win32_wait. */ - inferior_ptid = pid_to_ptid (pid); - - terminal_init_inferior_with_pgrp (pid); - target_terminal_inferior (); - - inf->stop_soon = STOP_QUIETLY; - while (1) - { - stop_after_trap = 1; - wait_for_inferior (0); - tp = inferior_thread (); - if (tp->stop_signal != TARGET_SIGNAL_TRAP) - resume (0, tp->stop_signal); - else - break; - } - - inf->stop_soon = NO_STOP_QUIETLY; - stop_after_trap = 0; - return; -} - -/* Since Windows XP, detaching from a process is supported by Windows. - The following code tries loading the appropriate functions dynamically. - If loading these functions succeeds use them to actually detach from - the inferior process, otherwise behave as usual, pretending that - detach has worked. */ -static BOOL WINAPI (*kernel32_DebugSetProcessKillOnExit)(BOOL); -static BOOL WINAPI (*kernel32_DebugActiveProcessStop)(DWORD); - -static int -has_detach_ability (void) -{ - static HMODULE kernel32 = NULL; - - if (!kernel32) - kernel32 = LoadLibrary ("kernel32.dll"); - if (kernel32) - { - if (!kernel32_DebugSetProcessKillOnExit) - kernel32_DebugSetProcessKillOnExit = - (void *) GetProcAddress (kernel32, "DebugSetProcessKillOnExit"); - if (!kernel32_DebugActiveProcessStop) - kernel32_DebugActiveProcessStop = - (void *) GetProcAddress (kernel32, "DebugActiveProcessStop"); - if (kernel32_DebugSetProcessKillOnExit - && kernel32_DebugActiveProcessStop) - return 1; - } - return 0; -} - -/* Try to set or remove a user privilege to the current process. Return -1 - if that fails, the previous setting of that privilege otherwise. - - This code is copied from the Cygwin source code and rearranged to allow - dynamically loading of the needed symbols from advapi32 which is only - available on NT/2K/XP. */ -static int -set_process_privilege (const char *privilege, BOOL enable) -{ - static HMODULE advapi32 = NULL; - static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE); - static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID); - static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, - DWORD, PTOKEN_PRIVILEGES, PDWORD); - - HANDLE token_hdl = NULL; - LUID restore_priv; - TOKEN_PRIVILEGES new_priv, orig_priv; - int ret = -1; - DWORD size; - - if (GetVersion () >= 0x80000000) /* No security availbale on 9x/Me */ - return 0; - - if (!advapi32) - { - if (!(advapi32 = LoadLibrary ("advapi32.dll"))) - goto out; - if (!OpenProcessToken) - OpenProcessToken = - (void *) GetProcAddress (advapi32, "OpenProcessToken"); - if (!LookupPrivilegeValue) - LookupPrivilegeValue = - (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA"); - if (!AdjustTokenPrivileges) - AdjustTokenPrivileges = - (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges"); - if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges) - { - advapi32 = NULL; - goto out; - } - } - - if (!OpenProcessToken (GetCurrentProcess (), - TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, - &token_hdl)) - goto out; - - if (!LookupPrivilegeValue (NULL, privilege, &restore_priv)) - goto out; - - new_priv.PrivilegeCount = 1; - new_priv.Privileges[0].Luid = restore_priv; - new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - - if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv, - sizeof orig_priv, &orig_priv, &size)) - goto out; -#if 0 - /* Disabled, otherwise every `attach' in an unprivileged user session - would raise the "Failed to get SE_DEBUG_NAME privilege" warning in - win32_attach(). */ - /* AdjustTokenPrivileges returns TRUE even if the privilege could not - be enabled. GetLastError () returns an correct error code, though. */ - if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED) - goto out; -#endif - - ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0; - -out: - if (token_hdl) - CloseHandle (token_hdl); - - return ret; -} - -/* Attach to process PID, then initialize for debugging it. */ -static void -win32_attach (struct target_ops *ops, char *args, int from_tty) -{ - BOOL ok; - DWORD pid; - - if (!args) - error_no_arg (_("process-id to attach")); - - if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0) - { - printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n"); - printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n"); - } - - pid = strtoul (args, 0, 0); /* Windows pid */ - - win32_init_thread_list (); - ok = DebugActiveProcess (pid); - saw_create = 0; - -#ifdef __CYGWIN__ - if (!ok) - { - /* Try fall back to Cygwin pid */ - pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid); - - if (pid > 0) - ok = DebugActiveProcess (pid); - } -#endif - - if (!ok) - error (_("Can't attach to process.")); - - if (has_detach_ability ()) - kernel32_DebugSetProcessKillOnExit (FALSE); - - if (from_tty) - { - char *exec_file = (char *) get_exec_file (0); - - if (exec_file) - printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, - target_pid_to_str (pid_to_ptid (pid))); - else - printf_unfiltered ("Attaching to %s\n", - target_pid_to_str (pid_to_ptid (pid))); - - gdb_flush (gdb_stdout); - } - - do_initial_win32_stuff (ops, pid, 1); - target_terminal_ours (); -} - -static void -win32_detach (struct target_ops *ops, char *args, int from_tty) -{ - int detached = 1; - - if (has_detach_ability ()) - { - ptid_t ptid = {-1}; - win32_resume (ptid, 0, TARGET_SIGNAL_0); - - if (!kernel32_DebugActiveProcessStop (current_event.dwProcessId)) - { - error (_("Can't detach process %lu (error %lu)"), - current_event.dwProcessId, GetLastError ()); - detached = 0; - } - kernel32_DebugSetProcessKillOnExit (FALSE); - } - if (detached && from_tty) - { - char *exec_file = get_exec_file (0); - if (exec_file == 0) - exec_file = ""; - printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file, - current_event.dwProcessId); - gdb_flush (gdb_stdout); - } - - inferior_ptid = null_ptid; - detach_inferior (current_event.dwProcessId); - - unpush_target (ops); -} - -static char * -win32_pid_to_exec_file (int pid) -{ - static char path[MAX_PATH + 1]; - -#ifdef __CYGWIN__ - /* Try to find exe name as symlink target of /proc//exe */ - int nchars; - char procexe[sizeof ("/proc/4294967295/exe")]; - sprintf (procexe, "/proc/%u/exe", pid); - nchars = readlink (procexe, path, sizeof(path)); - if (nchars > 0 && nchars < sizeof (path)) - { - path[nchars] = '\0'; /* Got it */ - return path; - } -#endif - - /* If we get here then either Cygwin is hosed, this isn't a Cygwin version - of gdb, or we're trying to debug a non-Cygwin windows executable. */ - if (!get_module_name (0, path)) - path[0] = '\0'; - - return path; -} - -/* Print status information about what we're accessing. */ - -static void -win32_files_info (struct target_ops *ignore) -{ - struct inferior *inf = current_inferior (); - - printf_unfiltered ("\tUsing the running image of %s %s.\n", - inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid)); -} - -static void -win32_open (char *arg, int from_tty) -{ - error (_("Use the \"run\" command to start a Unix child process.")); -} - -/* Start an inferior win32 child process and sets inferior_ptid to its pid. - EXEC_FILE is the file to run. - ALLARGS is a string containing the arguments to the program. - ENV is the environment vector to pass. Errors reported with error(). */ - -static void -win32_create_inferior (struct target_ops *ops, char *exec_file, - char *allargs, char **in_env, int from_tty) -{ - STARTUPINFO si; - PROCESS_INFORMATION pi; - BOOL ret; - DWORD flags; - char *args; - char real_path[MAXPATHLEN]; - char *toexec; - char shell[MAX_PATH + 1]; /* Path to shell */ - const char *sh; - int tty; - int ostdin, ostdout, ostderr; - const char *inferior_io_terminal = get_inferior_io_terminal (); - - if (!exec_file) - error (_("No executable specified, use `target exec'.")); - - memset (&si, 0, sizeof (si)); - si.cb = sizeof (si); - -#ifdef __CYGWIN__ - if (!useshell) - { - flags = DEBUG_ONLY_THIS_PROCESS; - cygwin_conv_to_win32_path (exec_file, real_path); - toexec = real_path; - } - else - { - char *newallargs; - sh = getenv ("SHELL"); - if (!sh) - sh = "/bin/sh"; - cygwin_conv_to_win32_path (sh, shell); - newallargs = alloca (sizeof (" -c 'exec '") + strlen (exec_file) - + strlen (allargs) + 2); - sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs); - allargs = newallargs; - toexec = shell; - flags = DEBUG_PROCESS; - } -#else - toexec = exec_file; - flags = DEBUG_ONLY_THIS_PROCESS; -#endif - - if (new_group) - flags |= CREATE_NEW_PROCESS_GROUP; - - if (new_console) - flags |= CREATE_NEW_CONSOLE; - - args = alloca (strlen (toexec) + strlen (allargs) + 2); - strcpy (args, toexec); - strcat (args, " "); - strcat (args, allargs); - -#ifdef __CYGWIN__ - /* Prepare the environment vars for CreateProcess. */ - cygwin_internal (CW_SYNC_WINENV); - - if (!inferior_io_terminal) - tty = ostdin = ostdout = ostderr = -1; - else - { - tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY); - if (tty < 0) - { - print_sys_errmsg (inferior_io_terminal, errno); - ostdin = ostdout = ostderr = -1; - } - else - { - ostdin = dup (0); - ostdout = dup (1); - ostderr = dup (2); - dup2 (tty, 0); - dup2 (tty, 1); - dup2 (tty, 2); - } - } -#endif - - win32_init_thread_list (); - ret = CreateProcess (0, - args, /* command line */ - NULL, /* Security */ - NULL, /* thread */ - TRUE, /* inherit handles */ - flags, /* start flags */ - NULL, /* environment */ - NULL, /* current directory */ - &si, - &pi); - -#ifdef __CYGWIN__ - if (tty >= 0) - { - close (tty); - dup2 (ostdin, 0); - dup2 (ostdout, 1); - dup2 (ostderr, 2); - close (ostdin); - close (ostdout); - close (ostderr); - } -#endif - - if (!ret) - error (_("Error creating process %s, (error %d)."), - exec_file, (unsigned) GetLastError ()); - - CloseHandle (pi.hThread); - CloseHandle (pi.hProcess); - - if (useshell && shell[0] != '\0') - saw_create = -1; - else - saw_create = 0; - - do_initial_win32_stuff (ops, pi.dwProcessId, 0); - - /* win32_continue (DBG_CONTINUE, -1); */ -} - -static void -win32_mourn_inferior (struct target_ops *ops) -{ - (void) win32_continue (DBG_CONTINUE, -1); - i386_cleanup_dregs(); - if (open_process_used) - { - CHECK (CloseHandle (current_process_handle)); - open_process_used = 0; - } - unpush_target (ops); - generic_mourn_inferior (); -} - -/* Send a SIGINT to the process group. This acts just like the user typed a - ^C on the controlling terminal. */ - -static void -win32_stop (ptid_t ptid) -{ - DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n")); - CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId)); - registers_changed (); /* refresh register state */ -} - -static int -win32_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len, - int write, struct mem_attrib *mem, - struct target_ops *target) -{ - SIZE_T done = 0; - if (write) - { - DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n", - len, (DWORD) (uintptr_t) memaddr)); - if (!WriteProcessMemory (current_process_handle, - (LPVOID) (uintptr_t) memaddr, our, - len, &done)) - done = 0; - FlushInstructionCache (current_process_handle, - (LPCVOID) (uintptr_t) memaddr, len); - } - else - { - DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n", - len, (DWORD) (uintptr_t) memaddr)); - if (!ReadProcessMemory (current_process_handle, - (LPCVOID) (uintptr_t) memaddr, our, - len, &done)) - done = 0; - } - return done; -} - -static void -win32_kill_inferior (void) -{ - CHECK (TerminateProcess (current_process_handle, 0)); - - for (;;) - { - if (!win32_continue (DBG_CONTINUE, -1)) - break; - if (!WaitForDebugEvent (¤t_event, INFINITE)) - break; - if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) - break; - } - - target_mourn_inferior (); /* or just win32_mourn_inferior? */ -} - -static void -win32_prepare_to_store (struct regcache *regcache) -{ - /* Do nothing, since we can store individual regs */ -} - -static int -win32_can_run (void) -{ - return 1; -} - -static void -win32_close (int x) -{ - DEBUG_EVENTS (("gdb: win32_close, inferior_ptid=%d\n", - PIDGET (inferior_ptid))); -} - -/* Convert pid to printable format. */ -static char * -win32_pid_to_str (ptid_t ptid) -{ - static char buf[80]; - - if (ptid_get_tid (ptid) != 0) - { - snprintf (buf, sizeof (buf), "Thread %d.0x%lx", - ptid_get_pid (ptid), ptid_get_tid (ptid)); - return buf; - } - - return normal_pid_to_str (ptid); -} - -static LONGEST -win32_xfer_shared_libraries (struct target_ops *ops, - enum target_object object, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) -{ - struct obstack obstack; - const char *buf; - LONGEST len_avail; - struct so_list *so; - - if (writebuf) - return -1; - - obstack_init (&obstack); - obstack_grow_str (&obstack, "\n"); - for (so = solib_start.next; so; so = so->next) - win32_xfer_shared_library (so->so_name, (CORE_ADDR) so->lm_info->load_addr, - &obstack); - obstack_grow_str0 (&obstack, "\n"); - - buf = obstack_finish (&obstack); - len_avail = strlen (buf); - if (offset >= len_avail) - return 0; - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - obstack_free (&obstack, NULL); - return len; -} - -static LONGEST -win32_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, LONGEST len) -{ - switch (object) - { - case TARGET_OBJECT_MEMORY: - if (readbuf) - return (*ops->deprecated_xfer_memory) (offset, readbuf, - len, 0/*read*/, NULL, ops); - if (writebuf) - return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf, - len, 1/*write*/, NULL, ops); - return -1; - - case TARGET_OBJECT_LIBRARIES: - return win32_xfer_shared_libraries (ops, object, annex, readbuf, - writebuf, offset, len); - - default: - if (ops->beneath != NULL) - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len); - return -1; - } -} - -static void -init_win32_ops (void) -{ - win32_ops.to_shortname = "child"; - win32_ops.to_longname = "Win32 child process"; - win32_ops.to_doc = "Win32 child process (started by the \"run\" command)."; - win32_ops.to_open = win32_open; - win32_ops.to_close = win32_close; - win32_ops.to_attach = win32_attach; - win32_ops.to_attach_no_wait = 1; - win32_ops.to_detach = win32_detach; - win32_ops.to_resume = win32_resume; - win32_ops.to_wait = win32_wait; - win32_ops.to_fetch_registers = win32_fetch_inferior_registers; - win32_ops.to_store_registers = win32_store_inferior_registers; - win32_ops.to_prepare_to_store = win32_prepare_to_store; - win32_ops.deprecated_xfer_memory = win32_xfer_memory; - win32_ops.to_xfer_partial = win32_xfer_partial; - win32_ops.to_files_info = win32_files_info; - win32_ops.to_insert_breakpoint = memory_insert_breakpoint; - win32_ops.to_remove_breakpoint = memory_remove_breakpoint; - win32_ops.to_terminal_init = terminal_init_inferior; - win32_ops.to_terminal_inferior = terminal_inferior; - win32_ops.to_terminal_ours_for_output = terminal_ours_for_output; - win32_ops.to_terminal_ours = terminal_ours; - win32_ops.to_terminal_save_ours = terminal_save_ours; - win32_ops.to_terminal_info = child_terminal_info; - win32_ops.to_kill = win32_kill_inferior; - win32_ops.to_create_inferior = win32_create_inferior; - win32_ops.to_mourn_inferior = win32_mourn_inferior; - win32_ops.to_can_run = win32_can_run; - win32_ops.to_thread_alive = win32_win32_thread_alive; - win32_ops.to_pid_to_str = win32_pid_to_str; - win32_ops.to_stop = win32_stop; - win32_ops.to_stratum = process_stratum; - win32_ops.to_has_all_memory = 1; - win32_ops.to_has_memory = 1; - win32_ops.to_has_stack = 1; - win32_ops.to_has_registers = 1; - win32_ops.to_has_execution = 1; - win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file; - win32_ops.to_magic = OPS_MAGIC; -} - -static void -set_win32_aliases (char *argv0) -{ - add_info_alias ("dll", "sharedlibrary", 1); -} - -void -_initialize_win32_nat (void) -{ - struct cmd_list_element *c; - - init_win32_ops (); - - c = add_com ("dll-symbols", class_files, dll_symbol_command, - _("Load dll library symbols from FILE.")); - set_cmd_completer (c, filename_completer); - - add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1); - -#ifdef __CYGWIN__ - add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\ -Set use of shell to start subprocess."), _("\ -Show use of shell to start subprocess."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("cygwin-exceptions", class_support, &cygwin_exceptions, _("\ -Break when an exception is detected in the Cygwin DLL itself."), _("\ -Show whether gdb breaks on exceptions in the Cygwin DLL itself."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); -#endif - - add_setshow_boolean_cmd ("new-console", class_support, &new_console, _("\ -Set creation of new console when creating child process."), _("\ -Show creation of new console when creating child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("new-group", class_support, &new_group, _("\ -Set creation of new group when creating child process."), _("\ -Show creation of new group when creating child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("debugexec", class_support, &debug_exec, _("\ -Set whether to display execution in child process."), _("\ -Show whether to display execution in child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\ -Set whether to display kernel events in child process."), _("\ -Show whether to display kernel events in child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\ -Set whether to display memory accesses in child process."), _("\ -Show whether to display memory accesses in child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_setshow_boolean_cmd ("debugexceptions", class_support, - &debug_exceptions, _("\ -Set whether to display kernel exceptions in child process."), _("\ -Show whether to display kernel exceptions in child process."), NULL, - NULL, - NULL, /* FIXME: i18n: */ - &setlist, &showlist); - - add_prefix_cmd ("w32", class_info, info_w32_command, - _("Print information specific to Win32 debugging."), - &info_w32_cmdlist, "info w32 ", 0, &infolist); - - add_cmd ("selector", class_info, display_selectors, - _("Display selectors infos."), - &info_w32_cmdlist); - add_target (&win32_ops); - deprecated_init_ui_hook = set_win32_aliases; -} - -/* Hardware watchpoint support, adapted from go32-nat.c code. */ - -/* Pass the address ADDR to the inferior in the I'th debug register. - Here we just store the address in dr array, the registers will be - actually set up when win32_continue is called. */ -void -cygwin_set_dr (int i, CORE_ADDR addr) -{ - if (i < 0 || i > 3) - internal_error (__FILE__, __LINE__, - _("Invalid register %d in cygwin_set_dr.\n"), i); - dr[i] = (unsigned) addr; - debug_registers_changed = 1; - debug_registers_used = 1; -} - -/* Pass the value VAL to the inferior in the DR7 debug control - register. Here we just store the address in D_REGS, the watchpoint - will be actually set up in win32_wait. */ -void -cygwin_set_dr7 (unsigned val) -{ - dr[7] = val; - debug_registers_changed = 1; - debug_registers_used = 1; -} - -/* Get the value of the DR6 debug status register from the inferior. - Here we just return the value stored in dr[6] - by the last call to thread_rec for current_event.dwThreadId id. */ -unsigned -cygwin_get_dr6 (void) -{ - return dr[6]; -} - -/* Determine if the thread referenced by "ptid" is alive - by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0 - it means that the thread has died. Otherwise it is assumed to be alive. */ -static int -win32_win32_thread_alive (ptid_t ptid) -{ - int tid; - - gdb_assert (ptid_get_tid (ptid) != 0); - tid = ptid_get_tid (ptid); - - return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 ? - FALSE : TRUE; -} - -void -_initialize_check_for_gdb_ini (void) -{ - char *homedir; - if (inhibit_gdbinit) - return; - - homedir = getenv ("HOME"); - if (homedir) - { - char *p; - char *oldini = (char *) alloca (strlen (homedir) + - sizeof ("/gdb.ini")); - strcpy (oldini, homedir); - p = strchr (oldini, '\0'); - if (p > oldini && p[-1] != '/') - *p++ = '/'; - strcpy (p, "gdb.ini"); - if (access (oldini, 0) == 0) - { - int len = strlen (oldini); - char *newini = alloca (len + 1); - sprintf (newini, "%.*s.gdbinit", - (int) (len - (sizeof ("gdb.ini") - 1)), oldini); - warning (_("obsolete '%s' found. Rename to '%s'."), oldini, newini); - } - } -} - -void -_initialize_psapi (void) -{ - /* Load optional functions used for retrieving filename information - associated with the currently debugged process or its dlls. */ - if (!psapi_loaded) - { - HMODULE psapi_module_handle; - - psapi_loaded = -1; - - psapi_module_handle = LoadLibrary ("psapi.dll"); - if (psapi_module_handle) - { - psapi_EnumProcessModules = (void *) GetProcAddress (psapi_module_handle, "EnumProcessModules"); - psapi_GetModuleInformation = (void *) GetProcAddress (psapi_module_handle, "GetModuleInformation"); - psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, "GetModuleFileNameExA"); - - if (psapi_EnumProcessModules != NULL - && psapi_GetModuleInformation != NULL - && psapi_GetModuleFileNameExA != NULL) - psapi_loaded = 1; - } - } - - /* This will probably fail on Windows 9x/Me. Let the user know that we're - missing some functionality. */ - if (psapi_loaded < 0) - warning(_("cannot automatically find executable file or library to read symbols. Use \"file\" or \"dll\" command to load executable/libraries directly.")); -} diff --git a/gdb/win32-nat.h b/gdb/win32-nat.h deleted file mode 100644 index 6b8287dd63..0000000000 --- a/gdb/win32-nat.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2008, 2009 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef WIN32_NAT_H -#define WIN32_NAT_H - -extern void win32_set_context_register_offsets (const int *offsets); - -#endif - diff --git a/gdb/win32-tdep.c b/gdb/win32-tdep.c deleted file mode 100644 index 1a4bae8cbf..0000000000 --- a/gdb/win32-tdep.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include "defs.h" -#include "win32-tdep.h" -#include "gdb_obstack.h" -#include "xml-support.h" - -void -win32_xfer_shared_library (const char* so_name, CORE_ADDR load_addr, - struct obstack *obstack) -{ - char *p; - obstack_grow_str (obstack, ""); -} - - diff --git a/gdb/win32-tdep.h b/gdb/win32-tdep.h deleted file mode 100644 index a38aa3393a..0000000000 --- a/gdb/win32-tdep.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef WIN32_TDEP_H -#define WIN32_TDEP_H - -struct obstack; - -extern void win32_xfer_shared_library (const char* so_name, - CORE_ADDR load_addr, - struct obstack *obstack); - -#endif diff --git a/gdb/win32-termcap.c b/gdb/win32-termcap.c deleted file mode 100644 index 9034c17dea..0000000000 --- a/gdb/win32-termcap.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Win32 termcap emulation. - - Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - Contributed by CodeSourcery, LLC. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Each of the files below is a minimal implementation of the standard - termcap function with the same name, suitable for use in a Windows - console window. */ - -int -tgetent (char *buffer, char *termtype) -{ - return -1; -} - -int -tgetnum (char *name) -{ - return -1; -} - -int -tgetflag (char *name) -{ - return -1; -} - -char * -tgetstr (char *name, char **area) -{ - return NULL; -} - -int -tputs (char *string, int nlines, int (*outfun) ()) -{ - while (*string) - outfun (*string++); - - return 0; -} - -char * -tgoto (const char *cap, int col, int row) -{ - return NULL; -} diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 9a1a28cfd5..4acbd1bc46 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -60,8 +60,8 @@ #include "i386-tdep.h" #include "i387-tdep.h" -#include "win32-tdep.h" -#include "win32-nat.h" +#include "windows-tdep.h" +#include "windows-nat.h" static struct target_ops win32_ops; @@ -651,8 +651,8 @@ win32_make_so (const char *name, LPVOID load_addr) /* The symbols in a dll are offset by 0x1000, which is the the offset from 0 of the first byte in an image - because of the file header and the section alignment. */ - cygwin_load_start = load_addr + 0x1000; - cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text); + cygwin_load_start = (bfd_vma) ((char *) load_addr + 0x1000); + cygwin_load_end = (bfd_vma) ((char *) cygwin_load_start + bfd_section_size (abfd, text)); bfd_close (abfd); } @@ -727,7 +727,7 @@ handle_load_dll (void *dummy) solib_end->next = win32_make_so (dll_name, event->lpBaseOfDll); solib_end = solib_end->next; - DEBUG_EVENTS (("gdb: Loading dll \"%s\" at 0x%lx.\n", solib_end->so_name, + DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %p.\n", solib_end->so_name, solib_end->lm_info->load_addr)); return 1; @@ -973,7 +973,7 @@ info_w32_command (char *args, int from_tty) #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \ - printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \ + printf_unfiltered ("gdb: Target exception %s at %p\n", x, \ current_event.u.Exception.ExceptionRecord.ExceptionAddress) static int @@ -1086,7 +1086,7 @@ handle_exception (struct target_waitstatus *ourstatus) /* Treat unhandled first chance exceptions specially. */ if (current_event.u.Exception.dwFirstChance) return -1; - printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n", + printf_unfiltered ("gdb: unknown target exception 0x%08lx at %p\n", current_event.u.Exception.ExceptionRecord.ExceptionCode, current_event.u.Exception.ExceptionRecord.ExceptionAddress); ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c index 1a4bae8cbf..1305fc8307 100644 --- a/gdb/windows-tdep.c +++ b/gdb/windows-tdep.c @@ -16,7 +16,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "win32-tdep.h" +#include "windows-tdep.h" #include "gdb_obstack.h" #include "xml-support.h"