#include "server.h"
#include "regcache.h"
-#include "gdb/fileio.h"
+#include "gdbsupport/fileio.h"
#include "mem-break.h"
#include "win32-low.h"
#include "gdbthread.h"
using namespace windows_nat;
-static windows_process_info windows_process;
+/* See win32-low.h. */
+gdbserver_windows_process windows_process;
#ifndef USE_WIN32API
#include <sys/cygwin.h>
#define _T(x) TEXT (x)
#endif
-#ifndef COUNTOF
-#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
-#endif
-
int using_threads = 1;
-/* Globals. */
-static int attaching = 0;
-
-/* A status that hasn't been reported to the core yet, and so
- win32_wait should return it next, instead of fetching the next
- debug event off the win32 API. */
-static struct target_waitstatus cached_status;
-
-/* Non zero if an interrupt request is to be satisfied by suspending
- all threads. */
-static int soft_interrupt_requested = 0;
-
-/* Non zero if the inferior is stopped in a simulated breakpoint done
- by suspending all the threads. */
-static int faked_breakpoint = 0;
-
-/* True if current_process_handle needs to be closed. */
-static bool open_process_used = false;
-
const struct target_desc *win32_tdesc;
#ifdef __x86_64__
const struct target_desc *wow64_win32_tdesc;
win32_get_thread_context (windows_thread_info *th)
{
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
memset (&th->wow64_context, 0, sizeof (WOW64_CONTEXT));
else
#endif
win32_set_thread_context (windows_thread_info *th)
{
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
Wow64SetThreadContext (th->h, &th->wow64_context);
else
#endif
{
DWORD context_flags;
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
context_flags = th->wow64_context.ContextFlags;
else
#endif
/* See nat/windows-nat.h. */
windows_thread_info *
-windows_nat::windows_process_info::thread_rec
+gdbserver_windows_process::thread_rec
(ptid_t ptid, thread_disposition_type disposition)
{
thread_info *thread = find_thread_ptid (ptid);
#ifdef __x86_64__
/* For WOW64 processes, this is actually the pointer to the 64bit TIB,
and the 32bit TIB is exactly 2 pages after it. */
- if (wow64_process)
+ if (windows_process.wow64_process)
base += 2 * 4096; /* page size = 4096 */
#endif
th = new windows_thread_info (tid, h, base);
for_each_thread (delete_thread_info);
}
-/* Zero during the child initialization phase, and nonzero otherwise. */
-
-static int child_initialization_done = 0;
-
static void
do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
{
windows_process.last_sig = GDB_SIGNAL_0;
windows_process.handle = proch;
- windows_process.id = pid;
windows_process.main_thread_id = 0;
- soft_interrupt_requested = 0;
- faked_breakpoint = 0;
- open_process_used = true;
+ windows_process.soft_interrupt_requested = 0;
+ windows_process.faked_breakpoint = 0;
+ windows_process.open_process_used = true;
memset (&windows_process.current_event, 0,
sizeof (windows_process.current_event));
error ("Check if WOW64 process failed (error %d): %s\n",
(int) err, strwinerror (err));
}
- wow64_process = wow64;
+ windows_process.wow64_process = wow64;
- if (wow64_process
+ if (windows_process.wow64_process
&& (Wow64GetThreadContext == nullptr
|| Wow64SetThreadContext == nullptr))
error ("WOW64 debugging is not supported on this system.\n");
- ignore_first_breakpoint = !attached && wow64_process;
+ windows_process.ignore_first_breakpoint
+ = !attached && windows_process.wow64_process;
#endif
proc = add_process (pid, attached);
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
proc->tdesc = wow64_win32_tdesc;
else
#endif
proc->tdesc = win32_tdesc;
child_init_thread_list ();
- child_initialization_done = 0;
+ windows_process.child_initialization_done = 0;
if (the_low_target.initial_stuff != NULL)
(*the_low_target.initial_stuff) ();
- cached_status.set_ignore ();
+ windows_process.cached_status.set_ignore ();
/* Flush all currently pending debug events (thread and dll list) up
to the initial breakpoint. */
/* Note win32_wait doesn't return thread events. */
if (status.kind () != TARGET_WAITKIND_LOADED)
{
- cached_status = status;
+ windows_process.cached_status = status;
break;
}
phase, and then process them all in one batch now. */
windows_process.add_all_dlls ();
- child_initialization_done = 1;
+ windows_process.child_initialization_done = 1;
}
/* Resume all artificially suspended threads if we are continuing
{
DWORD *context_flags;
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
context_flags = &th->wow64_context.ContextFlags;
else
#endif
{
continue_one_thread (thread, thread_id);
});
- faked_breakpoint = 0;
+ windows_process.faked_breakpoint = 0;
return continue_last_debug_event (continue_status, debug_threads);
}
(*the_low_target.store_inferior_register) (regcache, th, regno);
}
-/* Map the Windows error number in ERROR to a locale-dependent error
- message string and return a pointer to it. Typically, the values
- for ERROR come from GetLastError.
-
- The string pointed to shall not be modified by the application,
- but may be overwritten by a subsequent call to strwinerror
-
- The strwinerror function does not change the current setting
- of GetLastError. */
-
-char *
-strwinerror (DWORD error)
-{
- static char buf[1024];
- TCHAR *msgbuf;
- DWORD lasterr = GetLastError ();
- DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
- | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- NULL,
- error,
- 0, /* Default language */
- (LPTSTR) &msgbuf,
- 0,
- NULL);
- if (chars != 0)
- {
- /* If there is an \r\n appended, zap it. */
- if (chars >= 2
- && msgbuf[chars - 2] == '\r'
- && msgbuf[chars - 1] == '\n')
- {
- chars -= 2;
- msgbuf[chars] = 0;
- }
-
- if (chars > ((COUNTOF (buf)) - 1))
- {
- chars = COUNTOF (buf) - 1;
- msgbuf [chars] = 0;
- }
-
-#ifdef UNICODE
- wcstombs (buf, msgbuf, chars + 1);
-#else
- strncpy (buf, msgbuf, chars + 1);
-#endif
- LocalFree (msgbuf);
- }
- else
- sprintf (buf, "unknown win32 error (%u)", (unsigned) error);
-
- SetLastError (lasterr);
- return buf;
-}
-
static BOOL
create_process (const char *program, char *args,
DWORD flags, PROCESS_INFORMATION *pi)
strcpy (program_and_args, program);
strcat (program_and_args, " ");
strcat (program_and_args, args);
- ret = CreateProcessA (program, /* image name */
+ ret = create_process (program, /* image name */
program_and_args, /* command line */
- NULL, /* security */
- NULL, /* thread */
- TRUE, /* inherit handles */
flags, /* start flags */
NULL, /* environment */
/* current directory */
(inferior_cwd.empty ()
? NULL
: gdb_tilde_expand (inferior_cwd.c_str ()).c_str()),
+ get_client_state ().disable_randomization,
&si, /* start info */
pi); /* proc info */
char *args = (char *) str_program_args.c_str ();
/* win32_wait needs to know we're not attaching. */
- attaching = 0;
+ windows_process.attaching = 0;
if (!program)
error ("No executable specified, specify executable to debug.\n");
/* Wait till we are at 1st instruction in program, return new pid
(assuming success). */
- cs.last_ptid = wait (ptid_t (windows_process.id), &cs.last_status, 0);
+ cs.last_ptid = wait (ptid_t (pi.dwProcessId), &cs.last_status, 0);
/* Necessary for handle_v_kill. */
- signal_pid = windows_process.id;
+ signal_pid = pi.dwProcessId;
- return windows_process.id;
+ return pi.dwProcessId;
}
/* Attach to a running process.
DebugSetProcessKillOnExit (FALSE);
/* win32_wait needs to know we're attaching. */
- attaching = 1;
+ windows_process.attaching = 1;
do_initial_child_stuff (h, pid, 1);
return 0;
}
/* See nat/windows-nat.h. */
int
-windows_nat::windows_process_info::handle_output_debug_string
+gdbserver_windows_process::handle_output_debug_string
(struct target_waitstatus *ourstatus)
{
#define READ_BUFFER_LEN 1024
static void
win32_clear_inferiors (void)
{
- if (open_process_used)
+ if (windows_process.open_process_used)
{
CloseHandle (windows_process.handle);
- open_process_used = false;
+ windows_process.open_process_used = false;
}
for_each_thread (delete_thread_info);
resume.sig = 0;
this->resume (&resume, 1);
- if (!DebugActiveProcessStop (windows_process.id))
+ if (!DebugActiveProcessStop (process->pid))
return -1;
DebugSetProcessKillOnExit (FALSE);
DWORD *context_flags;
#ifdef __x86_64__
- if (wow64_process)
+ if (windows_process.wow64_process)
context_flags = &th->wow64_context.ContextFlags;
else
#endif
/* See nat/windows-nat.h. */
void
-windows_nat::windows_process_info::handle_load_dll (const char *name,
- LPVOID base)
+gdbserver_windows_process::handle_load_dll (const char *name, LPVOID base)
{
CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
/* See nat/windows-nat.h. */
void
-windows_nat::windows_process_info::handle_unload_dll ()
+gdbserver_windows_process::handle_unload_dll ()
{
CORE_ADDR load_addr =
(CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
{
OUTMSG2(("fake_breakpoint_event\n"));
- faked_breakpoint = 1;
+ windows_process.faked_breakpoint = 1;
memset (&windows_process.current_event, 0,
sizeof (windows_process.current_event));
/* See nat/windows-nat.h. */
bool
-windows_nat::windows_process_info::handle_access_violation
+gdbserver_windows_process::handle_access_violation
(const EXCEPTION_RECORD *rec)
{
return false;
== EXCEPTION_BREAKPOINT)
|| (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
== STATUS_WX86_BREAKPOINT))
- && child_initialization_done)
+ && windows_process.child_initialization_done)
{
th->stopped_at_software_breakpoint = true;
CORE_ADDR pc = regcache_read_pc (regcache);
DEBUG_EVENT *current_event = &windows_process.current_event;
- if (soft_interrupt_requested)
+ if (windows_process.soft_interrupt_requested)
{
- soft_interrupt_requested = 0;
+ windows_process.soft_interrupt_requested = 0;
fake_breakpoint_event ();
goto gotevent;
}
- attaching = 0;
+ windows_process.attaching = 0;
{
gdb::optional<pending_stop> stop
= windows_process.fetch_pending_stop (debug_threads);
(unsigned) current_event->dwThreadId));
CloseHandle (current_event->u.CreateProcessInfo.hFile);
- if (open_process_used)
+ if (windows_process.open_process_used)
{
CloseHandle (windows_process.handle);
- open_process_used = false;
+ windows_process.open_process_used = false;
}
windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
(unsigned) current_event->dwProcessId,
(unsigned) current_event->dwThreadId));
CloseHandle (current_event->u.LoadDll.hFile);
- if (! child_initialization_done)
+ if (! windows_process.child_initialization_done)
break;
windows_process.dll_loaded_event ();
"for pid=%u tid=%x\n",
(unsigned) current_event->dwProcessId,
(unsigned) current_event->dwThreadId));
- if (! child_initialization_done)
+ if (! windows_process.child_initialization_done)
break;
windows_process.handle_unload_dll ();
ourstatus->set_loaded ();
win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
target_wait_flags options)
{
- if (cached_status.kind () != TARGET_WAITKIND_IGNORE)
+ if (windows_process.cached_status.kind () != TARGET_WAITKIND_IGNORE)
{
/* The core always does a wait after creating the inferior, and
do_initial_child_stuff already ran the inferior to the
initial breakpoint (or an exit, if creating the process
fails). Report it now. */
- *ourstatus = cached_status;
- cached_status.set_ignore ();
+ *ourstatus = windows_process.cached_status;
+ windows_process.cached_status.set_ignore ();
return debug_event_ptid (&windows_process.current_event);
}
void
win32_process_target::request_interrupt ()
{
- if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, windows_process.id))
+ if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, signal_pid))
return;
/* GenerateConsoleCtrlEvent can fail if process id being debugged is
return;
/* Last resort, suspend all threads manually. */
- soft_interrupt_requested = 1;
+ windows_process.soft_interrupt_requested = 1;
}
bool
#ifdef __x86_64__
EXCEPTION_RECORD32 er32;
- if (wow64_process)
+ if (windows_process.wow64_process)
{
buf = (char *) &er32;
bufsize = sizeof (er32);
- er32.ExceptionCode = siginfo_er.ExceptionCode;
- er32.ExceptionFlags = siginfo_er.ExceptionFlags;
- er32.ExceptionRecord = (uintptr_t) siginfo_er.ExceptionRecord;
- er32.ExceptionAddress = (uintptr_t) siginfo_er.ExceptionAddress;
- er32.NumberParameters = siginfo_er.NumberParameters;
+ er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
+ er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
+ er32.ExceptionRecord
+ = (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
+ er32.ExceptionAddress
+ = (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
+ er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
int i;
for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
- er32.ExceptionInformation[i] = siginfo_er.ExceptionInformation[i];
+ er32.ExceptionInformation[i]
+ = windows_process.siginfo_er.ExceptionInformation[i];
}
#endif
return (*the_low_target.set_pc) (regcache, pc);
}
+const char *
+win32_process_target::thread_name (ptid_t thread)
+{
+ windows_thread_info *th
+ = windows_process.thread_rec (current_thread_ptid (),
+ DONT_INVALIDATE_CONTEXT);
+ return th->thread_name ();
+}
+
+const char *
+win32_process_target::pid_to_exec_file (int pid)
+{
+ return windows_process.pid_to_exec_file (pid);
+}
+
/* The win32 target ops object. */
static win32_process_target the_win32_target;