/* Target-vector operations for controlling windows child processes, for GDB.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
#include <sys/cygwin.h>
#include <cygwin/version.h>
#endif
+#include <algorithm>
#include "buildsym.h"
#include "filenames.h"
#include "x86-nat.h"
#include "complaints.h"
#include "inf-child.h"
+#include "gdb_tilde_expand.h"
#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
#define DebugActiveProcessStop dyn_DebugActiveProcessStop
#define DEBUG_MEM(x) if (debug_memory) printf_unfiltered x
#define DEBUG_EXCEPT(x) if (debug_exceptions) printf_unfiltered x
-static void windows_interrupt (struct target_ops *self, ptid_t);
-static int windows_thread_alive (struct target_ops *, ptid_t);
-static void windows_kill_inferior (struct target_ops *);
-
static void cygwin_set_dr (int i, CORE_ADDR addr);
static void cygwin_set_dr7 (unsigned long val);
static CORE_ADDR cygwin_get_dr (int i);
{STATUS_FLOAT_DIVIDE_BY_ZERO, GDB_SIGNAL_FPE},
{-1, GDB_SIGNAL_UNKNOWN}};
+
+struct windows_nat_target final : public x86_nat_target<inf_child_target>
+{
+ void close () override;
+
+ void attach (const char *, int) override;
+
+ bool attach_no_wait () override
+ { return true; }
+
+ void detach (inferior *, int) override;
+
+ void resume (ptid_t, int , enum gdb_signal) override;
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ enum target_xfer_status xfer_partial (enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len) override;
+
+ void files_info () override;
+
+ void kill () override;
+
+ void create_inferior (const char *, const std::string &,
+ char **, int) override;
+
+ void mourn_inferior () override;
+
+ bool thread_alive (ptid_t ptid) override;
+
+ const char *pid_to_str (ptid_t) override;
+
+ void interrupt () override;
+
+ char *pid_to_exec_file (int pid) override;
+
+ ptid_t get_ada_task_ptid (long lwp, long thread) override;
+
+ bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
+
+ const char *thread_name (struct thread_info *) override;
+};
+
+static windows_nat_target the_windows_nat_target;
+
/* Set the MAPPINGS static global to OFFSETS.
See the description of MAPPINGS for more details. */
}
static void
-do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
+do_windows_fetch_inferior_registers (struct regcache *regcache,
+ windows_thread_info *th, int r)
{
- char *context_offset = ((char *) ¤t_thread->context) + mappings[r];
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ char *context_offset = ((char *) &th->context) + mappings[r];
+ struct gdbarch *gdbarch = regcache->arch ();
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)
+ if (th->reload_context)
{
#ifdef __CYGWIN__
if (have_saved_context)
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,
+ memcpy (&th->context, &saved_context,
__COPY_CONTEXT_SIZE);
have_saved_context = 0;
}
else
#endif
{
- windows_thread_info *th = current_thread;
th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
CHECK (GetThreadContext (th->h, &th->context));
/* Copy dr values from that thread.
dr[7] = th->context.Dr7;
}
}
- current_thread->reload_context = 0;
+ th->reload_context = 0;
}
if (r == I387_FISEG_REGNUM (tdep))
{
l = *((long *) context_offset) & 0xffff;
- regcache_raw_supply (regcache, r, (char *) &l);
+ regcache->raw_supply (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);
+ regcache->raw_supply (r, (char *) &l);
}
else if (segment_register_p (r))
{
in fact only 16 bits long. Make sure we do not read extra
bits from our source buffer. */
l = *((long *) context_offset) & 0xffff;
- regcache_raw_supply (regcache, r, (char *) &l);
+ regcache->raw_supply (r, (char *) &l);
}
else if (r >= 0)
- regcache_raw_supply (regcache, r, context_offset);
+ regcache->raw_supply (r, context_offset);
else
{
for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
- do_windows_fetch_inferior_registers (regcache, r);
+ do_windows_fetch_inferior_registers (regcache, th, r);
}
}
-static void
-windows_fetch_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int r)
+void
+windows_nat_target::fetch_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
+ DWORD pid = ptid_get_tid (regcache->ptid ());
+ windows_thread_info *th = thread_rec (pid, TRUE);
+
+ /* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
- if (current_thread)
- do_windows_fetch_inferior_registers (regcache, r);
+ if (th != NULL)
+ do_windows_fetch_inferior_registers (regcache, th, r);
}
static void
-do_windows_store_inferior_registers (const struct regcache *regcache, int r)
+do_windows_store_inferior_registers (const struct regcache *regcache,
+ windows_thread_info *th, 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]);
+ if (r >= 0)
+ regcache->raw_collect (r, ((char *) &th->context) + mappings[r]);
else
{
- for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
- do_windows_store_inferior_registers (regcache, r);
+ for (r = 0; r < gdbarch_num_regs (regcache->arch ()); r++)
+ do_windows_store_inferior_registers (regcache, th, r);
}
}
-/* Store a new register value into the current thread context. */
-static void
-windows_store_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int r)
+/* Store a new register value into the context of the thread tied to
+ REGCACHE. */
+
+void
+windows_nat_target::store_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
+ DWORD pid = ptid_get_tid (regcache->ptid ());
+ windows_thread_info *th = thread_rec (pid, TRUE);
+
+ /* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
- if (current_thread)
- do_windows_store_inferior_registers (regcache, r);
+ if (th != NULL)
+ do_windows_store_inferior_registers (regcache, th, r);
}
/* Encapsulate the information required in a call to
{
char *name;
int from_tty;
- struct section_addr_info *addrs;
+ section_addr_info *addrs;
int mainline;
int flags;
struct ui_file *err, *out;
};
/* Maintain a linked list of "so" information. */
-struct lm_info
+struct lm_info_windows : public lm_info_base
{
- LPVOID load_addr;
+ LPVOID load_addr = 0;
};
static struct so_list solib_start, *solib_end;
}
#endif
so = XCNEW (struct so_list);
- so->lm_info = XNEW (struct lm_info);
- so->lm_info->load_addr = load_addr;
+ lm_info_windows *li = new lm_info_windows;
+ so->lm_info = li;
+ li->load_addr = load_addr;
strcpy (so->so_original_name, name);
#ifndef __CYGWIN__
strcpy (so->so_name, buf);
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 = gdb_bfd_open (so->so_name, "pei-i386", -1);
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
- if (!abfd)
+ if (abfd == NULL)
return so;
- if (bfd_check_format (abfd, bfd_object))
- text = bfd_get_section_by_name (abfd, ".text");
+ if (bfd_check_format (abfd.get (), bfd_object))
+ text = bfd_get_section_by_name (abfd.get (), ".text");
if (!text)
- {
- gdb_bfd_unref (abfd);
- return so;
- }
+ return so;
/* The symbols in a dll are offset by 0x1000, which is the
offset from 0 of the first byte in an image - because of the
file header and the section alignment. */
cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
load_addr + 0x1000);
- cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-
- gdb_bfd_unref (abfd);
+ cygwin_load_end = cygwin_load_start + bfd_section_size (abfd.get (),
+ text);
}
#endif
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)
+static void
+handle_load_dll ()
{
LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll;
char *dll_name;
dll_name = get_image_name (current_process_handle,
event->lpImageName, event->fUnicode);
if (!dll_name)
- return 1;
+ return;
solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
solib_end = solib_end->next;
- DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
- host_address_to_string (solib_end->lm_info->load_addr)));
+ lm_info_windows *li = (lm_info_windows *) solib_end->lm_info;
- return 1;
+ DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
+ host_address_to_string (li->load_addr)));
}
static void
windows_free_so (struct so_list *so)
{
- if (so->lm_info)
- xfree (so->lm_info);
+ lm_info_windows *li = (lm_info_windows *) so->lm_info;
+
+ delete li;
xfree (so);
}
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)
+static void
+handle_unload_dll ()
{
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;
+ {
+ lm_info_windows *li_next = (lm_info_windows *) so->next->lm_info;
+
+ if (li_next->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));
+ so->next = sodel->next;
+ if (!so->next)
+ solib_end = so;
+ DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
- windows_free_so (sodel);
- return 1;
- }
+ windows_free_so (sodel);
+ return;
+ }
+ }
/* We did not find any DLL that was previously loaded at this address,
so register a complaint. We do not report an error, because we have
4 mysterious UNLOAD_DLL_DEBUG_EVENTs during the startup phase (these
events are apparently caused by the WOW layer, the interface between
32bit and 64bit worlds). */
- complaint (&symfile_complaints, _("dll starting at %s not found."),
+ complaint (_("dll starting at %s not found."),
host_address_to_string (lpBaseOfDll));
+}
- return 0;
+/* Call FUNC wrapped in a TRY/CATCH that swallows all GDB
+ exceptions. */
+
+static void
+catch_errors (void (*func) ())
+{
+ TRY
+ {
+ func ();
+ }
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
}
/* Clear list of loaded DLLs. */
}
static void
-signal_event_command (char *args, int from_tty)
+signal_event_command (const char *args, int from_tty)
{
uintptr_t event_id = 0;
char *endargs = NULL;
static int
handle_output_debug_string (struct target_waitstatus *ourstatus)
{
- char *s = NULL;
+ gdb::unique_xmalloc_ptr<char> s;
int retval = 0;
if (!target_read_string
((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
- &s, 1024, 0)
- || !s || !*s)
+ &s, 1024, 0)
+ || !s || !*(s.get ()))
/* nothing to do */;
- else if (!startswith (s, _CYGWIN_SIGNAL_STRING))
+ else if (!startswith (s.get (), _CYGWIN_SIGNAL_STRING))
{
#ifdef __CYGWIN__
- if (!startswith (s, "cYg"))
+ if (!startswith (s.get (), "cYg"))
#endif
{
- char *p = strchr (s, '\0');
+ char *p = strchr (s.get (), '\0');
- if (p > s && *--p == '\n')
+ if (p > s.get () && *--p == '\n')
*p = '\0';
- warning (("%s"), s);
+ warning (("%s"), s.get ());
}
}
#ifdef __CYGWIN__
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 sig = strtol (s.get () + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
gdb_signal gotasig = gdb_signal_from_host (sig);
ourstatus->value.sig = gotasig;
}
#endif
- if (s)
- xfree (s);
return retval;
}
}
static void
-display_selectors (char * args, int from_tty)
+display_selectors (const char * args, int from_tty)
{
if (!current_thread)
{
if (named_thread != NULL)
{
int thread_name_len;
- char *thread_name;
+ gdb::unique_xmalloc_ptr<char> thread_name;
thread_name_len = target_read_string (thread_name_target,
&thread_name, 1025, NULL);
if (thread_name_len > 0)
{
- thread_name[thread_name_len - 1] = '\0';
+ thread_name.get ()[thread_name_len - 1] = '\0';
xfree (named_thread->name);
- named_thread->name = thread_name;
+ named_thread->name = thread_name.release ();
}
- else
- xfree (thread_name);
}
ourstatus->value.sig = GDB_SIGNAL_TRAP;
result = HANDLE_EXCEPTION_IGNORED;
break;
}
- /* treat improperly formed exception as unknown, fallthrough */
+ /* treat improperly formed exception as unknown */
+ /* FALLTHROUGH */
default:
/* Treat unhandled first chance exceptions specially. */
if (current_event.u.Exception.dwFirstChance)
return main_thread_id;
}
-static void
-windows_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal sig)
+void
+windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
{
windows_thread_info *th;
DWORD continue_status = DBG_CONTINUE;
{
/* Single step by setting t bit. */
struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- windows_fetch_inferior_registers (ops, regcache,
- gdbarch_ps_regnum (gdbarch));
+ struct gdbarch *gdbarch = regcache->arch ();
+ fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
th->context.EFlags |= FLAG_TRACE_BIT;
}
"EXIT_PROCESS_DEBUG_EVENT"));
if (!windows_initialization_done)
{
- target_terminal_ours ();
+ target_terminal::ours ();
target_mourn_inferior (inferior_ptid);
error (_("During startup program exited with code 0x%x."),
(unsigned int) current_event.u.ExitProcess.dwExitCode);
CloseHandle (current_event.u.LoadDll.hFile);
if (saw_create != 1 || ! windows_initialization_done)
break;
- catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
+ catch_errors (handle_load_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
thread_id = main_thread_id;
"UNLOAD_DLL_DEBUG_EVENT"));
if (saw_create != 1 || ! windows_initialization_done)
break;
- catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
+ catch_errors (handle_unload_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
thread_id = main_thread_id;
}
/* Wait for interesting events to occur in the target process. */
-static ptid_t
-windows_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+ int options)
{
int pid = -1;
- target_terminal_ours ();
+ 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,
the user tries to resume the execution in the inferior.
This is a classic race that we should try to fix one day. */
SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
- retval = get_windows_debug_event (ops, pid, ourstatus);
+ retval = get_windows_debug_event (this, pid, ourstatus);
SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
if (retval)
detach = deprecated_ui_loop_hook (0);
if (detach)
- windows_kill_inferior (ops);
+ kill ();
}
}
}
current thread until we report an event out of windows_wait. */
inferior_ptid = pid_to_ptid (pid);
- target_terminal_init ();
- target_terminal_inferior ();
+ target_terminal::init ();
+ target_terminal::inferior ();
windows_initialization_done = 0;
{
struct target_waitstatus status;
- windows_wait (ops, minus_one_ptid, &status, 0);
+ ops->wait (minus_one_ptid, &status, 0);
/* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread
events. */
&& status.kind != TARGET_WAITKIND_SPURIOUS)
break;
- windows_resume (ops, minus_one_ptid, 0, GDB_SIGNAL_0);
+ ops->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
}
/* Now that the inferior has been started and all DLLs have been mapped,
}
/* Attach to process PID, then initialize for debugging it. */
-static void
-windows_attach (struct target_ops *ops, const char *args, int from_tty)
+
+void
+windows_nat_target::attach (const char *args, int from_tty)
{
BOOL ok;
DWORD pid;
gdb_flush (gdb_stdout);
}
- do_initial_windows_stuff (ops, pid, 1);
- target_terminal_ours ();
+ do_initial_windows_stuff (this, pid, 1);
+ target_terminal::ours ();
}
-static void
-windows_detach (struct target_ops *ops, const char *args, int from_tty)
+void
+windows_nat_target::detach (inferior *inf, int from_tty)
{
int detached = 1;
- ptid_t ptid = {-1};
- windows_resume (ops, ptid, 0, GDB_SIGNAL_0);
+ ptid_t ptid = minus_one_ptid;
+ resume (ptid, 0, GDB_SIGNAL_0);
if (!DebugActiveProcessStop (current_event.dwProcessId))
{
if (detached && from_tty)
{
- char *exec_file = get_exec_file (0);
+ const char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
printf_unfiltered ("Detaching from program: %s, Pid %u\n", exec_file,
inferior_ptid = null_ptid;
detach_inferior (current_event.dwProcessId);
- inf_child_maybe_unpush_target (ops);
+ maybe_unpush_target ();
}
/* Try to determine the executable filename.
/* The pid_to_exec_file target_ops method for this platform. */
-static char *
-windows_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+windows_nat_target::pid_to_exec_file (int pid)
{
static char path[__PMAX];
#ifdef __CYGWIN__
/* Print status information about what we're accessing. */
-static void
-windows_files_info (struct target_ops *ignore)
+void
+windows_nat_target::files_info ()
{
struct inferior *inf = current_inferior ();
ALLARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error(). */
-static void
-windows_create_inferior (struct target_ops *ops, char *exec_file,
- char *allargs, char **in_env, int from_tty)
+void
+windows_nat_target::create_inferior (const char *exec_file,
+ const std::string &origallargs,
+ char **in_env, int from_tty)
{
STARTUPINFO si;
#ifdef __CYGWIN__
cygwin_buf_t real_path[__PMAX];
cygwin_buf_t shell[__PMAX]; /* Path to shell */
+ cygwin_buf_t infcwd[__PMAX];
const char *sh;
cygwin_buf_t *toexec;
cygwin_buf_t *cygallargs;
#else /* !__CYGWIN__ */
char real_path[__PMAX];
char shell[__PMAX]; /* Path to shell */
- char *toexec;
+ const char *toexec;
char *args, *allargs_copy;
size_t args_len, allargs_len;
int fd_inp = -1, fd_out = -1, fd_err = -1;
size_t envsize;
char **env;
#endif /* !__CYGWIN__ */
+ const char *allargs = origallargs.c_str ();
PROCESS_INFORMATION pi;
BOOL ret;
DWORD flags = 0;
if (!exec_file)
error (_("No executable specified, use `target exec'."));
+ const char *inferior_cwd = get_inferior_cwd ();
+ std::string expanded_infcwd;
+ if (inferior_cwd != NULL)
+ {
+ expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+ /* Mirror slashes on inferior's cwd. */
+ std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+ '/', '\\');
+ inferior_cwd = expanded_infcwd.c_str ();
+ }
+
memset (&si, 0, sizeof (si));
si.cb = sizeof (si);
flags |= DEBUG_PROCESS;
}
+ if (inferior_cwd != NULL
+ && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
+ infcwd, strlen (inferior_cwd)) < 0)
+ error (_("Error converting inferior cwd: %d"), errno);
+
#ifdef __USEWIDE
args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
* sizeof (wchar_t));
TRUE, /* inherit handles */
flags, /* start flags */
w32_env, /* environment */
- NULL, /* current directory */
+ inferior_cwd != NULL ? infcwd : NULL, /* current
+ directory */
&si,
&pi);
if (w32_env)
TRUE, /* inherit handles */
flags, /* start flags */
w32env, /* environment */
- NULL, /* current directory */
+ inferior_cwd, /* current directory */
&si,
&pi);
if (tty != INVALID_HANDLE_VALUE)
else
saw_create = 0;
- do_initial_windows_stuff (ops, pi.dwProcessId, 0);
+ do_initial_windows_stuff (this, pi.dwProcessId, 0);
/* windows_continue (DBG_CONTINUE, -1, 0); */
}
-static void
-windows_mourn_inferior (struct target_ops *ops)
+void
+windows_nat_target::mourn_inferior ()
{
(void) windows_continue (DBG_CONTINUE, -1, 0);
x86_cleanup_dregs();
CHECK (CloseHandle (current_process_handle));
open_process_used = 0;
}
- inf_child_mourn_inferior (ops);
+ inf_child_target::mourn_inferior ();
}
/* Send a SIGINT to the process group. This acts just like the user typed a
^C on the controlling terminal. */
-static void
-windows_interrupt (struct target_ops *self, ptid_t ptid)
+void
+windows_nat_target::interrupt ()
{
DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
return success ? TARGET_XFER_OK : TARGET_XFER_E_IO;
}
-static void
-windows_kill_inferior (struct target_ops *ops)
+void
+windows_nat_target::kill ()
{
CHECK (TerminateProcess (current_process_handle, 0));
target_mourn_inferior (inferior_ptid); /* Or just windows_mourn_inferior? */
}
-static void
-windows_close (struct target_ops *self)
+void
+windows_nat_target::close ()
{
DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
ptid_get_pid (inferior_ptid)));
}
/* Convert pid to printable format. */
-static char *
-windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+windows_nat_target::pid_to_str (ptid_t ptid)
{
static char buf[80];
obstack_init (&obstack);
obstack_grow_str (&obstack, "<library-list>\n");
for (so = solib_start.next; so; so = so->next)
- windows_xfer_shared_library (so->so_name, (CORE_ADDR)
- (uintptr_t) so->lm_info->load_addr,
- target_gdbarch (), &obstack);
+ {
+ lm_info_windows *li = (lm_info_windows *) so->lm_info;
+
+ windows_xfer_shared_library (so->so_name, (CORE_ADDR)
+ (uintptr_t) li->load_addr,
+ target_gdbarch (), &obstack);
+ }
obstack_grow_str0 (&obstack, "</library-list>\n");
buf = (const char *) obstack_finish (&obstack);
return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
}
-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, ULONGEST len,
- ULONGEST *xfered_len)
+enum target_xfer_status
+windows_nat_target::xfer_partial (enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
case TARGET_OBJECT_LIBRARIES:
- return windows_xfer_shared_libraries (ops, object, annex, readbuf,
+ return windows_xfer_shared_libraries (this, object, annex, readbuf,
writebuf, offset, len, xfered_len);
default:
- return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
+ return beneath->xfer_partial (object, annex,
+ readbuf, writebuf, offset, len,
+ xfered_len);
}
}
/* Provide thread local base, i.e. Thread Information Block address.
Returns 1 if ptid is found and sets *ADDR to thread_local_base. */
-static int
-windows_get_tib_address (struct target_ops *self,
- ptid_t ptid, CORE_ADDR *addr)
+bool
+windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
{
windows_thread_info *th;
th = thread_rec (ptid_get_tid (ptid), 0);
if (th == NULL)
- return 0;
+ return false;
if (addr != NULL)
*addr = th->thread_local_base;
- return 1;
+ return true;
}
-static ptid_t
-windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+windows_nat_target::get_ada_task_ptid (long lwp, long thread)
{
return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
}
/* Implementation of the to_thread_name method. */
-static const char *
-windows_thread_name (struct target_ops *self, struct thread_info *thr)
+const char *
+windows_nat_target::thread_name (struct thread_info *thr)
{
return thread_rec (ptid_get_tid (thr->ptid), 0)->name;
}
-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_interrupt = windows_interrupt;
- 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;
- t->to_thread_name = windows_thread_name;
-
- return t;
-}
-
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_windows_nat;
void
_initialize_windows_nat (void)
{
- 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;
calling x86_set_debug_register_length function
in processor windows specific native file. */
- add_target (t);
+ add_inf_child_target (&the_windows_nat_target);
#ifdef __CYGWIN__
cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
/* 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
-windows_thread_alive (struct target_ops *ops, ptid_t ptid)
+
+bool
+windows_nat_target::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;
+ return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_check_for_gdb_ini;
-
void
_initialize_check_for_gdb_ini (void)
{
return size;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_loadable;
-
/* Load any functions which may not be available in ancient versions
of Windows. */