/* Target-vector operations for controlling windows child processes, for GDB.
- Copyright (C) 1995-2013 Free Software Foundation, Inc.
+ Copyright (C) 1995-2014 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
#include "defs.h"
#include "frame.h" /* required by inferior.h */
#include "inferior.h"
+#include "infrun.h"
#include "target.h"
-#include "exceptions.h"
#include "gdbcore.h"
#include "command.h"
#include "completer.h"
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
-#include <stdlib.h>
#include <windows.h>
#include <imagehlp.h>
#include <psapi.h>
#include <sys/cygwin.h>
#include <cygwin/version.h>
#endif
-#include <signal.h>
#include "buildsym.h"
#include "filenames.h"
#include "objfiles.h"
#include "gdb_bfd.h"
#include "gdb_obstack.h"
-#include "gdb_string.h"
#include "gdbthread.h"
#include "gdbcmd.h"
#include <unistd.h>
#include "windows-tdep.h"
#include "windows-nat.h"
-#include "i386-nat.h"
+#include "x86-nat.h"
#include "complaints.h"
+#include "inf-child.h"
#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
#define DebugActiveProcessStop dyn_DebugActiveProcessStop
CONSOLE_FONT_INFO *);
static COORD WINAPI (*GetConsoleFontSize) (HANDLE, DWORD);
-static struct target_ops windows_ops;
-
#undef STARTUPINFO
#undef CreateProcess
#undef GetModuleFileNameEx
#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x
#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x
-static void windows_stop (ptid_t);
+static void windows_stop (struct target_ops *self, ptid_t);
static int windows_thread_alive (struct target_ops *, ptid_t);
static void windows_kill_inferior (struct target_ops *);
{
DWORD err = GetLastError ();
- warning (_("SuspendThread (tid=0x%x) failed."
- " (winerr %u)"),
- (unsigned) id, (unsigned) err);
- return NULL;
+ /* We get Access Denied (5) when trying to suspend
+ threads that Windows started on behalf of the
+ debuggee, usually when those threads are just
+ about to exit. */
+ if (err != ERROR_ACCESS_DENIED)
+ warning (_("SuspendThread (tid=0x%x) failed."
+ " (winerr %u)"),
+ (unsigned) id, (unsigned) err);
+ th->suspended = -1;
}
- th->suspended = 1;
+ else
+ th->suspended = 1;
}
else if (get_context < 0)
th->suspended = -1;
if ((th = thread_rec (id, FALSE)))
return th;
- th = XZALLOC (thread_info);
+ th = XCNEW (thread_info);
th->id = id;
th->h = h;
th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
{
thread_info *th = current_thread;
th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
- GetThreadContext (th->h, &th->context);
+ CHECK (GetThreadContext (th->h, &th->context));
/* Copy dr values from that thread.
But only if there were not modified since last stop.
PR gdb/2388 */
do_windows_store_inferior_registers (regcache, r);
}
-/* Get the name of a given module 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__
- cygwin_buf_t pathbuf[__PMAX]; /* Temporary storage prior to converting to
- posix form. __PMAX is always enough
- as long as SO_NAME_MAX_PATH_SIZE is defined
- as 512. */
-#endif
-
- cbNeeded = 0;
- /* Find size of buffer needed to handle list of modules loaded in
- inferior. */
- if (!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 (!EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
- &cbNeeded))
- goto failed;
-
- for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
- {
- /* Get information on this module. */
- if (!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. */
-#ifdef __CYGWIN__
- /* Cygwin prefers that the path be in /x/y/z format. */
- len = GetModuleFileNameEx (current_process_handle,
- DllHandle[i], pathbuf, __PMAX);
- if (len == 0)
- error (_("Error getting dll name: %u."),
- (unsigned) GetLastError ());
- if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, dll_name_ret,
- __PMAX) < 0)
- error (_("Error converting dll name to POSIX: %d."), errno);
-#else
- len = GetModuleFileNameEx (current_process_handle,
- DllHandle[i], dll_name_ret, __PMAX);
- if (len == 0)
- error (_("Error getting dll name: %u."),
- (unsigned) GetLastError ());
-#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
#endif
}
#endif
- so = XZALLOC (struct so_list);
+ so = XCNEW (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);
return buf;
}
-/* Wait for child to do something. Return pid of child, or -1 in case
- of error; store status through argument pointer OURSTATUS. */
+/* Handle a DLL load event, and return 1.
+
+ This function assumes that this event did not occur during inferior
+ initialization, where their event info may be incomplete (see
+ do_initial_windows_stuff and windows_add_all_dlls for more info
+ on how we handle DLL loading during that phase). */
+
static int
handle_load_dll (void *dummy)
{
LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll;
- char dll_buf[__PMAX];
- 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);
+ char *dll_name;
+
+ /* Try getting the DLL name via the lpImageName field of the event.
+ Note that Microsoft documents this fields as strictly optional,
+ in the sense that it might be NULL. And the first DLL event in
+ particular is explicitly documented as "likely not pass[ed]"
+ (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
+ dll_name = get_image_name (current_process_handle,
+ event->lpImageName, event->fUnicode);
if (!dll_name)
return 1;
xfree (so);
}
+/* Handle a DLL unload event.
+ Return 1 if successful, or zero otherwise.
+
+ This function assumes that this event did not occur during inferior
+ initialization, where their event info may be incomplete (see
+ do_initial_windows_stuff and windows_add_all_dlls for more info
+ on how we handle DLL loading during that phase). */
+
static int
handle_unload_dll (void *dummy)
{
return 1;
}
-/* Resume all artificially suspended threads if we are continuing
- execution. */
+/* Resume thread specified by ID, or all artificially suspended
+ threads, if we are continuing execution. KILLED non-zero means we
+ have killed the inferior, so we should ignore weird errors due to
+ threads shutting down. */
static BOOL
-windows_continue (DWORD continue_status, int id)
+windows_continue (DWORD continue_status, int id, int killed)
{
int i;
thread_info *th;
}
if (th->context.ContextFlags)
{
- CHECK (SetThreadContext (th->h, &th->context));
+ DWORD ec = 0;
+
+ if (GetExitCodeThread (th->h, &ec)
+ && ec == STILL_ACTIVE)
+ {
+ BOOL status = SetThreadContext (th->h, &th->context);
+
+ if (!killed)
+ CHECK (status);
+ }
th->context.ContextFlags = 0;
}
if (th->suspended > 0)
Otherwise complain. */
if (resume_all)
- windows_continue (continue_status, -1);
+ windows_continue (continue_status, -1, 0);
else
- windows_continue (continue_status, ptid_get_tid (ptid));
+ windows_continue (continue_status, ptid_get_tid (ptid), 0);
}
/* Ctrl-C handler used when the inferior is not run in the same console. The
(unsigned) current_event.dwThreadId,
"LOAD_DLL_DEBUG_EVENT"));
CloseHandle (current_event.u.LoadDll.hFile);
- if (saw_create != 1)
+ if (saw_create != 1 || ! windows_initialization_done)
break;
catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
ourstatus->kind = TARGET_WAITKIND_LOADED;
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"UNLOAD_DLL_DEBUG_EVENT"));
- if (saw_create != 1)
+ if (saw_create != 1 || ! windows_initialization_done)
break;
catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
ourstatus->kind = TARGET_WAITKIND_LOADED;
if (continue_status == -1)
windows_resume (ops, minus_one_ptid, 0, 1);
else
- CHECK (windows_continue (continue_status, -1));
+ CHECK (windows_continue (continue_status, -1, 0));
}
else
{
}
}
+/* Iterate over all DLLs currently mapped by our inferior, and
+ add them to our list of solibs. */
+
+static void
+windows_add_all_dlls (void)
+{
+ struct so_list *so;
+ HMODULE dummy_hmodule;
+ DWORD cb_needed;
+ HMODULE *hmodules;
+ int i;
+
+ if (EnumProcessModules (current_process_handle, &dummy_hmodule,
+ sizeof (HMODULE), &cb_needed) == 0)
+ return;
+
+ if (cb_needed < 1)
+ return;
+
+ hmodules = (HMODULE *) alloca (cb_needed);
+ if (EnumProcessModules (current_process_handle, hmodules,
+ cb_needed, &cb_needed) == 0)
+ return;
+
+ for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
+ {
+ MODULEINFO mi;
+#ifdef __USEWIDE
+ wchar_t dll_name[__PMAX];
+ char name[__PMAX];
+#else
+ char dll_name[__PMAX];
+ char *name;
+#endif
+ if (GetModuleInformation (current_process_handle, hmodules[i],
+ &mi, sizeof (mi)) == 0)
+ continue;
+ if (GetModuleFileNameEx (current_process_handle, hmodules[i],
+ dll_name, sizeof (dll_name)) == 0)
+ continue;
+#ifdef __USEWIDE
+ wcstombs (name, dll_name, __PMAX);
+#else
+ name = dll_name;
+#endif
+
+ solib_end->next = windows_make_so (name, mi.lpBaseOfDll);
+ solib_end = solib_end->next;
+ }
+}
+
static void
do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
{
#endif
current_event.dwProcessId = pid;
memset (¤t_event, 0, sizeof (current_event));
- push_target (ops);
+ if (!target_is_pushed (ops))
+ push_target (ops);
disable_breakpoints_in_shlibs ();
windows_clear_solib ();
- clear_proceed_status ();
+ clear_proceed_status (0);
init_wait_for_inferior ();
inf = current_inferior ();
current thread until we report an event out of windows_wait. */
inferior_ptid = pid_to_ptid (pid);
- terminal_init_inferior_with_pgrp (pid);
+ child_terminal_init_with_pgrp (pid);
target_terminal_inferior ();
windows_initialization_done = 0;
break;
}
+ /* Now that the inferior has been started and all DLLs have been mapped,
+ we can iterate over all DLLs and load them in.
+
+ We avoid doing it any earlier because, on certain versions of Windows,
+ LOAD_DLL_DEBUG_EVENTs are sometimes not complete. In particular,
+ we have seen on Windows 8.1 that the ntdll.dll load event does not
+ include the DLL name, preventing us from creating an associated SO.
+ A possible explanation is that ntdll.dll might be mapped before
+ the SO info gets created by the Windows system -- ntdll.dll is
+ the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs
+ do not seem to suffer from that problem.
+
+ Rather than try to work around this sort of issue, it is much
+ simpler to just ignore DLL load/unload events during the startup
+ phase, and then process them all in one batch now. */
+ windows_add_all_dlls ();
+
windows_initialization_done = 1;
inf->control.stop_soon = NO_STOP_QUIETLY;
stop_after_trap = 0;
/* Attach to process PID, then initialize for debugging it. */
static void
-windows_attach (struct target_ops *ops, char *args, int from_tty)
+windows_attach (struct target_ops *ops, const char *args, int from_tty)
{
BOOL ok;
DWORD pid;
}
static void
-windows_detach (struct target_ops *ops, char *args, int from_tty)
+windows_detach (struct target_ops *ops, const char *args, int from_tty)
{
int detached = 1;
gdb_flush (gdb_stdout);
}
- i386_cleanup_dregs ();
+ x86_cleanup_dregs ();
inferior_ptid = null_ptid;
detach_inferior (current_event.dwProcessId);
- unpush_target (ops);
+ inf_child_maybe_unpush_target (ops);
+}
+
+/* Try to determine the executable filename.
+
+ EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
+
+ Upon success, the filename is stored inside EXE_NAME_RET, and
+ this function returns nonzero.
+
+ Otherwise, this function returns zero and the contents of
+ EXE_NAME_RET is undefined. */
+
+static int
+windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
+{
+ DWORD len;
+ HMODULE dh_buf;
+ DWORD cbNeeded;
+
+ cbNeeded = 0;
+ if (!EnumProcessModules (current_process_handle, &dh_buf,
+ sizeof (HMODULE), &cbNeeded) || !cbNeeded)
+ return 0;
+
+ /* We know the executable is always first in the list of modules,
+ which we just fetched. So no need to fetch more. */
+
+#ifdef __CYGWIN__
+ {
+ /* Cygwin prefers that the path be in /x/y/z format, so extract
+ the filename into a temporary buffer first, and then convert it
+ to POSIX format into the destination buffer. */
+ cygwin_buf_t *pathbuf = alloca (exe_name_max_len * sizeof (cygwin_buf_t));
+
+ len = GetModuleFileNameEx (current_process_handle,
+ dh_buf, pathbuf, exe_name_max_len);
+ if (len == 0)
+ error (_("Error getting executable filename: %u."),
+ (unsigned) GetLastError ());
+ if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, exe_name_ret,
+ exe_name_max_len) < 0)
+ error (_("Error converting executable filename to POSIX: %d."), errno);
+ }
+#else
+ len = GetModuleFileNameEx (current_process_handle,
+ dh_buf, exe_name_ret, exe_name_max_len);
+ if (len == 0)
+ error (_("Error getting executable filename: %u."),
+ (unsigned) GetLastError ());
+#endif
+
+ return 1; /* success */
}
+/* The pid_to_exec_file target_ops method for this platform. */
+
static char *
-windows_pid_to_exec_file (int pid)
+windows_pid_to_exec_file (struct target_ops *self, int pid)
{
static char path[__PMAX];
#ifdef __CYGWIN__
/* 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))
+ if (!windows_get_exec_module_filename (path, sizeof (path)))
path[0] = '\0';
return path;
target_pid_to_str (inferior_ptid));
}
-static void
-windows_open (char *arg, int from_tty)
-{
- error (_("Use the \"run\" command to start a Unix child process."));
-}
-
/* Modify CreateProcess parameters for use of a new separate console.
Parameters are:
*FLAGS: DWORD parameter for general process creation flags.
do_initial_windows_stuff (ops, pi.dwProcessId, 0);
- /* windows_continue (DBG_CONTINUE, -1); */
+ /* windows_continue (DBG_CONTINUE, -1, 0); */
}
static void
windows_mourn_inferior (struct target_ops *ops)
{
- (void) windows_continue (DBG_CONTINUE, -1);
- i386_cleanup_dregs();
+ (void) windows_continue (DBG_CONTINUE, -1, 0);
+ x86_cleanup_dregs();
if (open_process_used)
{
CHECK (CloseHandle (current_process_handle));
open_process_used = 0;
}
- unpush_target (ops);
- generic_mourn_inferior ();
+ inf_child_mourn_inferior (ops);
}
/* Send a SIGINT to the process group. This acts just like the user typed a
^C on the controlling terminal. */
static void
-windows_stop (ptid_t ptid)
+windows_stop (struct target_ops *self, ptid_t ptid)
{
DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
/* Helper for windows_xfer_partial that handles memory transfers.
Arguments are like target_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, LONGEST len)
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
SIZE_T done = 0;
BOOL success;
if (writebuf != NULL)
{
DEBUG_MEM (("gdb: write target memory, %s bytes at %s\n",
- plongest (len), core_addr_to_string (memaddr)));
+ pulongest (len), core_addr_to_string (memaddr)));
success = WriteProcessMemory (current_process_handle,
(LPVOID) (uintptr_t) memaddr, writebuf,
len, &done);
else
{
DEBUG_MEM (("gdb: read target memory, %s bytes at %s\n",
- plongest (len), core_addr_to_string (memaddr)));
+ pulongest (len), core_addr_to_string (memaddr)));
success = ReadProcessMemory (current_process_handle,
(LPCVOID) (uintptr_t) memaddr, readbuf,
len, &done);
if (!success)
lasterror = GetLastError ();
}
+ *xfered_len = (ULONGEST) done;
if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
- return done;
+ return TARGET_XFER_OK;
else
- return success ? done : TARGET_XFER_E_IO;
+ return success ? TARGET_XFER_OK : TARGET_XFER_E_IO;
}
static void
for (;;)
{
- if (!windows_continue (DBG_CONTINUE, -1))
+ if (!windows_continue (DBG_CONTINUE, -1, 1))
break;
if (!WaitForDebugEvent (¤t_event, INFINITE))
break;
}
static void
-windows_prepare_to_store (struct regcache *regcache)
-{
- /* Do nothing, since we can store individual regs. */
-}
-
-static int
-windows_can_run (void)
-{
- return 1;
-}
-
-static void
-windows_close (void)
+windows_close (struct target_ops *self)
{
DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
- PIDGET (inferior_ptid)));
+ ptid_get_pid (inferior_ptid)));
}
/* Convert pid to printable format. */
return normal_pid_to_str (ptid);
}
-static LONGEST
+static enum target_xfer_status
windows_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)
+ enum target_object object, const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct obstack obstack;
const char *buf;
struct so_list *so;
if (writebuf)
- return -1;
+ return TARGET_XFER_E_IO;
obstack_init (&obstack);
obstack_grow_str (&obstack, "<library-list>\n");
}
obstack_free (&obstack, NULL);
- return len;
+ *xfered_len = (ULONGEST) len;
+ return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
}
-static LONGEST
+static enum target_xfer_status
windows_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return windows_xfer_memory (readbuf, writebuf, offset, len);
+ return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
case TARGET_OBJECT_LIBRARIES:
return windows_xfer_shared_libraries (ops, object, annex, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len, xfered_len);
default:
- if (ops->beneath != NULL)
- return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len);
- return -1;
+ return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+ readbuf, writebuf, offset, len,
+ xfered_len);
}
}
Returns 1 if ptid is found and sets *ADDR to thread_local_base. */
static int
-windows_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
+windows_get_tib_address (struct target_ops *self,
+ ptid_t ptid, CORE_ADDR *addr)
{
thread_info *th;
}
static ptid_t
-windows_get_ada_task_ptid (long lwp, long thread)
+windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
{
return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
}
-static void
-init_windows_ops (void)
-{
- windows_ops.to_shortname = "child";
- windows_ops.to_longname = "Win32 child process";
- windows_ops.to_doc = "Win32 child process (started by the \"run\" command).";
- windows_ops.to_open = windows_open;
- windows_ops.to_close = windows_close;
- windows_ops.to_attach = windows_attach;
- windows_ops.to_attach_no_wait = 1;
- windows_ops.to_detach = windows_detach;
- windows_ops.to_resume = windows_resume;
- windows_ops.to_wait = windows_wait;
- windows_ops.to_fetch_registers = windows_fetch_inferior_registers;
- windows_ops.to_store_registers = windows_store_inferior_registers;
- windows_ops.to_prepare_to_store = windows_prepare_to_store;
- windows_ops.to_xfer_partial = windows_xfer_partial;
- windows_ops.to_files_info = windows_files_info;
- windows_ops.to_insert_breakpoint = memory_insert_breakpoint;
- windows_ops.to_remove_breakpoint = memory_remove_breakpoint;
- windows_ops.to_terminal_init = terminal_init_inferior;
- windows_ops.to_terminal_inferior = terminal_inferior;
- windows_ops.to_terminal_ours_for_output = terminal_ours_for_output;
- windows_ops.to_terminal_ours = terminal_ours;
- windows_ops.to_terminal_save_ours = terminal_save_ours;
- windows_ops.to_terminal_info = child_terminal_info;
- windows_ops.to_kill = windows_kill_inferior;
- windows_ops.to_create_inferior = windows_create_inferior;
- windows_ops.to_mourn_inferior = windows_mourn_inferior;
- windows_ops.to_can_run = windows_can_run;
- windows_ops.to_thread_alive = windows_thread_alive;
- windows_ops.to_pid_to_str = windows_pid_to_str;
- windows_ops.to_stop = windows_stop;
- windows_ops.to_stratum = process_stratum;
- windows_ops.to_has_all_memory = default_child_has_all_memory;
- windows_ops.to_has_memory = default_child_has_memory;
- windows_ops.to_has_stack = default_child_has_stack;
- windows_ops.to_has_registers = default_child_has_registers;
- windows_ops.to_has_execution = default_child_has_execution;
- windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
- windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
- windows_ops.to_get_tib_address = windows_get_tib_address;
-
- i386_use_watchpoints (&windows_ops);
-
- i386_dr_low.set_control = cygwin_set_dr7;
- i386_dr_low.set_addr = cygwin_set_dr;
- i386_dr_low.get_addr = cygwin_get_dr;
- i386_dr_low.get_status = cygwin_get_dr6;
- i386_dr_low.get_control = cygwin_get_dr7;
-
- /* i386_dr_low.debug_register_length field is set by
- calling i386_set_debug_register_length function
- in processor windows specific native file. */
+static struct target_ops *
+windows_target (void)
+{
+ struct target_ops *t = inf_child_target ();
+
+ t->to_close = windows_close;
+ t->to_attach = windows_attach;
+ t->to_attach_no_wait = 1;
+ t->to_detach = windows_detach;
+ t->to_resume = windows_resume;
+ t->to_wait = windows_wait;
+ t->to_fetch_registers = windows_fetch_inferior_registers;
+ t->to_store_registers = windows_store_inferior_registers;
+ t->to_xfer_partial = windows_xfer_partial;
+ t->to_files_info = windows_files_info;
+ t->to_kill = windows_kill_inferior;
+ t->to_create_inferior = windows_create_inferior;
+ t->to_mourn_inferior = windows_mourn_inferior;
+ t->to_thread_alive = windows_thread_alive;
+ t->to_pid_to_str = windows_pid_to_str;
+ t->to_stop = windows_stop;
+ t->to_pid_to_exec_file = windows_pid_to_exec_file;
+ t->to_get_ada_task_ptid = windows_get_ada_task_ptid;
+ t->to_get_tib_address = windows_get_tib_address;
- windows_ops.to_magic = OPS_MAGIC;
+ return t;
}
static void
_initialize_windows_nat (void)
{
struct cmd_list_element *c;
+ struct target_ops *t;
+
+ t = windows_target ();
+
+ x86_use_watchpoints (t);
+
+ x86_dr_low.set_control = cygwin_set_dr7;
+ x86_dr_low.set_addr = cygwin_set_dr;
+ x86_dr_low.get_addr = cygwin_get_dr;
+ x86_dr_low.get_status = cygwin_get_dr6;
+ x86_dr_low.get_control = cygwin_get_dr7;
- init_windows_ops ();
+ /* x86_dr_low.debug_register_length field is set by
+ calling x86_set_debug_register_length function
+ in processor windows specific native file. */
+
+ add_target (t);
#ifdef __CYGWIN__
cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
c = add_com ("dll-symbols", class_files, dll_symbol_command,
_("Load dll library symbols from FILE."));
set_cmd_completer (c, filename_completer);
+ deprecate_cmd (c, "sharedlibrary");
- add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
-
- add_com_alias ("add-shared-symbol-files", "dll-symbols", class_alias, 1);
+ c = add_com ("add-shared-symbol-files", class_files, dll_symbol_command,
+ _("Load dll library symbols from FILE."));
+ set_cmd_completer (c, filename_completer);
+ deprecate_cmd (c, "sharedlibrary");
- add_com_alias ("assf", "dll-symbols", class_alias, 1);
+ c = add_com ("assf", class_files, dll_symbol_command,
+ _("Load dll library symbols from FILE."));
+ set_cmd_completer (c, filename_completer);
+ deprecate_cmd (c, "sharedlibrary");
#ifdef __CYGWIN__
add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\
add_cmd ("selector", class_info, display_selectors,
_("Display selectors infos."),
&info_w32_cmdlist);
- add_target (&windows_ops);
deprecated_init_ui_hook = set_windows_aliases;
}