/* Low level interface to Windows debugging, for gdbserver.
- Copyright (C) 2006-2014 Free Software Foundation, Inc.
+ Copyright (C) 2006-2017 Free Software Foundation, Inc.
Contributed by Leo Zayas. Based on "win32-nat.c" from GDB.
#include "server.h"
#include "regcache.h"
-#include "gdb/signals.h"
#include "gdb/fileio.h"
#include "mem-break.h"
#include "win32-low.h"
#include "gdbthread.h"
#include "dll.h"
#include "hostio.h"
-
-#include <stdint.h>
#include <windows.h>
#include <winnt.h>
#include <imagehlp.h>
/* Get the thread ID from the current selected inferior (the current
thread). */
static ptid_t
-current_inferior_ptid (void)
+current_thread_ptid (void)
{
return current_ptid;
}
win32_get_thread_context (win32_thread_info *th)
{
memset (&th->context, 0, sizeof (CONTEXT));
- (*the_low_target.get_thread_context) (th, ¤t_event);
+ (*the_low_target.get_thread_context) (th);
#ifdef _WIN32_WCE
memcpy (&th->base_context, &th->context, sizeof (CONTEXT));
#endif
it between stopping and resuming. */
if (memcmp (&th->context, &th->base_context, sizeof (CONTEXT)) != 0)
#endif
- (*the_low_target.set_thread_context) (th, ¤t_event);
+ SetThreadContext (th->h, &th->context);
}
-/* Find a thread record given a thread id. If GET_CONTEXT is set then
- also retrieve the context for this thread. */
-static win32_thread_info *
-thread_rec (ptid_t ptid, int get_context)
+/* Set the thread context of the thread associated with TH. */
+
+static void
+win32_prepare_to_resume (win32_thread_info *th)
{
- struct thread_info *thread;
- win32_thread_info *th;
+ if (the_low_target.prepare_to_resume != NULL)
+ (*the_low_target.prepare_to_resume) (th);
+}
- thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
- if (thread == NULL)
- return NULL;
+/* See win32-low.h. */
- th = inferior_target_data (thread);
- if (get_context && th->context.ContextFlags == 0)
+void
+win32_require_context (win32_thread_info *th)
+{
+ if (th->context.ContextFlags == 0)
{
if (!th->suspended)
{
win32_get_thread_context (th);
}
+}
+
+/* Find a thread record given a thread id. If GET_CONTEXT is set then
+ also retrieve the context for this thread. */
+static win32_thread_info *
+thread_rec (ptid_t ptid, int get_context)
+{
+ struct thread_info *thread;
+ win32_thread_info *th;
+
+ thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
+ if (thread == NULL)
+ return NULL;
+ th = (win32_thread_info *) thread_target_data (thread);
+ if (get_context)
+ win32_require_context (th);
return th;
}
if ((th = thread_rec (ptid, FALSE)))
return th;
- th = xcalloc (1, sizeof (*th));
+ th = XCNEW (win32_thread_info);
th->tid = tid;
th->h = h;
th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
/* Delete a thread from the list of threads. */
static void
-delete_thread_info (struct inferior_list_entry *thread)
+delete_thread_info (struct inferior_list_entry *entry)
{
- win32_thread_info *th = inferior_target_data ((struct thread_info *) thread);
+ struct thread_info *thread = (struct thread_info *) entry;
+ win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
- remove_thread ((struct thread_info *) thread);
+ remove_thread (thread);
CloseHandle (th->h);
free (th);
}
if the low target has registered a corresponding function. */
static int
-win32_insert_point (char type, CORE_ADDR addr, int len)
+win32_supports_z_point_type (char z_type)
+{
+ return (the_low_target.supports_z_point_type != NULL
+ && the_low_target.supports_z_point_type (z_type));
+}
+
+static int
+win32_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, struct raw_breakpoint *bp)
{
if (the_low_target.insert_point != NULL)
- return the_low_target.insert_point (type, addr, len);
+ return the_low_target.insert_point (type, addr, size, bp);
else
/* Unsupported (see target.h). */
return 1;
}
static int
-win32_remove_point (char type, CORE_ADDR addr, int len)
+win32_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, struct raw_breakpoint *bp)
{
if (the_low_target.remove_point != NULL)
- return the_low_target.remove_point (type, addr, len);
+ return the_low_target.remove_point (type, addr, size, bp);
else
/* Unsupported (see target.h). */
return 1;
{
struct thread_info *thread = (struct thread_info *) this_thread;
int thread_id = * (int *) id_ptr;
- win32_thread_info *th = inferior_target_data (thread);
+ win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
- if ((thread_id == -1 || thread_id == th->tid)
- && th->suspended)
+ if (thread_id == -1 || thread_id == th->tid)
{
- if (th->context.ContextFlags)
- {
- win32_set_thread_context (th);
- th->context.ContextFlags = 0;
- }
+ win32_prepare_to_resume (th);
- if (ResumeThread (th->h) == (DWORD) -1)
+ if (th->suspended)
{
- DWORD err = GetLastError ();
- OUTMSG (("warning: ResumeThread failed in continue_one_thread, "
- "(error %d): %s\n", (int) err, strwinerror (err)));
+ if (th->context.ContextFlags)
+ {
+ win32_set_thread_context (th);
+ th->context.ContextFlags = 0;
+ }
+
+ if (ResumeThread (th->h) == (DWORD) -1)
+ {
+ DWORD err = GetLastError ();
+ OUTMSG (("warning: ResumeThread failed in continue_one_thread, "
+ "(error %d): %s\n", (int) err, strwinerror (err)));
+ }
+ th->suspended = 0;
}
- th->suspended = 0;
}
return 0;
child_fetch_inferior_registers (struct regcache *regcache, int r)
{
int regno;
- win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
+ win32_thread_info *th = thread_rec (current_thread_ptid (), TRUE);
if (r == -1 || r > NUM_REGS)
child_fetch_inferior_registers (regcache, NUM_REGS);
else
child_store_inferior_registers (struct regcache *regcache, int r)
{
int regno;
- win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
+ win32_thread_info *th = thread_rec (current_thread_ptid (), TRUE);
if (r == -1 || r == 0 || r > NUM_REGS)
child_store_inferior_registers (regcache, NUM_REGS);
else
NULL,
error,
0, /* Default language */
- (LPVOID)&msgbuf,
+ (LPTSTR) &msgbuf,
0,
NULL);
if (chars != 0)
}
/* Start a new process.
- PROGRAM is a path to the program to execute.
- ARGS is a standard NULL-terminated array of arguments,
- to be passed to the inferior as ``argv''.
+ PROGRAM is the program name.
+ PROGRAM_ARGS is the vector containing the inferior's args.
Returns the new PID on success, -1 on failure. Registers the new
process with the process list. */
static int
-win32_create_inferior (char *program, char **program_args)
+win32_create_inferior (const char *program,
+ const std::vector<char *> &program_args)
{
#ifndef USE_WIN32API
char real_path[PATH_MAX];
#endif
BOOL ret;
DWORD flags;
- char *args;
int argslen;
int argc;
PROCESS_INFORMATION pi;
DWORD err;
+ std::string str_program_args = stringify_argv (program_args);
+ char *args = (char *) str_program_args.c_str ();
/* win32_wait needs to know we're not attaching. */
attaching = 0;
if (path_ptr)
{
int size = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, NULL, 0);
- orig_path = alloca (strlen (path_ptr) + 1);
- new_path = alloca (size);
+ orig_path = (char *) alloca (strlen (path_ptr) + 1);
+ new_path = (char *) alloca (size);
strcpy (orig_path, path_ptr);
cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, new_path, size);
setenv ("PATH", new_path, 1);
program = real_path;
#endif
- argslen = 1;
- for (argc = 1; program_args[argc]; argc++)
- argslen += strlen (program_args[argc]) + 1;
- args = alloca (argslen);
- args[0] = '\0';
- for (argc = 1; program_args[argc]; argc++)
- {
- /* FIXME: Can we do better about quoting? How does Cygwin
- handle this? */
- strcat (args, " ");
- strcat (args, program_args[argc]);
- }
OUTMSG2 (("Command line is \"%s\"\n", args));
#ifdef CREATE_NEW_PROCESS_GROUP
err = GetLastError ();
if (!ret && err == ERROR_FILE_NOT_FOUND)
{
- char *exename = alloca (strlen (program) + 5);
+ char *exename = (char *) alloca (strlen (program) + 5);
strcat (strcpy (exename, program), ".exe");
ret = create_process (exename, args, flags, &pi);
err = GetLastError ();
/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
static void
-handle_output_debug_string (struct target_waitstatus *ourstatus)
+handle_output_debug_string (void)
{
#define READ_BUFFER_LEN 1024
CORE_ADDR addr;
return;
}
- if (strncmp (s, "cYg", 3) != 0)
+ if (!startswith (s, "cYg"))
{
if (!server_waiting)
{
if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
break;
else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
- {
- struct target_waitstatus our_status = { 0 };
- handle_output_debug_string (&our_status);
- }
+ handle_output_debug_string ();
}
win32_clear_inferiors ();
if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
{
- sig = resume_info[0].sig;
+ sig = gdb_signal_from_host (resume_info[0].sig);
step = resume_info[0].kind == resume_step;
}
else
{
- sig = 0;
+ sig = GDB_SIGNAL_0;
step = 0;
}
{
if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
- OUTMSG (("Cannot continue with signal %d here.\n", sig));
+ OUTMSG (("Cannot continue with signal %s here.\n",
+ gdb_signal_to_string (sig)));
}
else if (sig == last_sig)
continue_status = DBG_EXCEPTION_NOT_HANDLED;
else
- OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
+ OUTMSG (("Can only continue with received signal %s.\n",
+ gdb_signal_to_string (last_sig)));
}
last_sig = GDB_SIGNAL_0;
th = thread_rec (ptid, FALSE);
if (th)
{
+ win32_prepare_to_resume (th);
+
if (th->context.ContextFlags)
{
/* Move register values from the inferior into the thread
ReadProcessMemory (h, address_ptr, buf, len, &done);
else
{
- WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
+ WCHAR *unicode_address = XALLOCAVEC (WCHAR, len);
ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
&done);
suspend_one_thread (struct inferior_list_entry *entry)
{
struct thread_info *thread = (struct thread_info *) entry;
- win32_thread_info *th = inferior_target_data (thread);
+ win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
if (!th->suspended)
{
child_delete_thread (current_event.dwProcessId,
current_event.dwThreadId);
- current_inferior = (struct thread_info *) all_threads.head;
+ current_thread = (struct thread_info *) all_threads.head;
return 1;
case CREATE_PROCESS_DEBUG_EVENT:
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
main_thread_id = current_event.dwThreadId;
- ourstatus->kind = TARGET_WAITKIND_EXECD;
- ourstatus->value.execd_pathname = "Main executable";
-
/* Add the main thread. */
child_add_thread (current_event.dwProcessId,
main_thread_id,
current_event.u.CreateProcessInfo.hThread,
current_event.u.CreateProcessInfo.lpThreadLocalBase);
- ourstatus->value.related_pid = debug_event_ptid (¤t_event);
#ifdef _WIN32_WCE
if (!attaching)
{
"for pid=%u tid=%x\n",
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId));
- handle_output_debug_string (ourstatus);
+ handle_output_debug_string ();
break;
default:
}
ptid = debug_event_ptid (¤t_event);
- current_inferior =
+ current_thread =
(struct thread_info *) find_inferior_id (&all_threads, ptid);
return 1;
}
OUTMSG2 (("Child Stopped with signal = %d \n",
ourstatus->value.sig));
- regcache = get_thread_regcache (current_inferior, 1);
+ regcache = get_thread_regcache (current_thread, 1);
child_fetch_inferior_registers (regcache, -1);
return debug_event_ptid (¤t_event);
default:
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */
case TARGET_WAITKIND_SPURIOUS:
- case TARGET_WAITKIND_EXECD:
/* do nothing, just continue */
child_continue (DBG_CONTINUE, -1);
break;
return 1;
}
+/* Implementation of the target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+win32_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = the_low_target.breakpoint_len;
+ return the_low_target.breakpoint;
+}
+
static struct target_ops win32_target_ops = {
win32_create_inferior,
+ NULL, /* post_create_inferior */
win32_attach,
win32_kill,
win32_detach,
NULL, /* lookup_symbols */
win32_request_interrupt,
NULL, /* read_auxv */
+ win32_supports_z_point_type,
win32_insert_point,
win32_remove_point,
+ NULL, /* stopped_by_sw_breakpoint */
+ NULL, /* supports_stopped_by_sw_breakpoint */
+ NULL, /* stopped_by_hw_breakpoint */
+ NULL, /* supports_stopped_by_hw_breakpoint */
+ target_can_do_hardware_single_step,
win32_stopped_by_watchpoint,
win32_stopped_data_address,
NULL, /* read_offsets */
NULL, /* async */
NULL, /* start_non_stop */
NULL, /* supports_multi_process */
+ NULL, /* supports_fork_events */
+ NULL, /* supports_vfork_events */
+ NULL, /* supports_exec_events */
+ NULL, /* handle_new_gdb_connection */
NULL, /* handle_monitor_command */
NULL, /* core_of_thread */
NULL, /* read_loadmap */
NULL, /* read_pc */
NULL, /* write_pc */
NULL, /* thread_stopped */
- win32_get_tib_address
+ win32_get_tib_address,
+ NULL, /* pause_all */
+ NULL, /* unpause_all */
+ NULL, /* stabilize_threads */
+ NULL, /* install_fast_tracepoint_jump_pad */
+ NULL, /* emit_ops */
+ NULL, /* supports_disable_randomization */
+ NULL, /* get_min_fast_tracepoint_insn_len */
+ NULL, /* qxfer_libraries_svr4 */
+ NULL, /* support_agent */
+ NULL, /* support_btrace */
+ NULL, /* enable_btrace */
+ NULL, /* disable_btrace */
+ NULL, /* read_btrace */
+ NULL, /* read_btrace_conf */
+ NULL, /* supports_range_stepping */
+ NULL, /* pid_to_exec_file */
+ NULL, /* multifs_open */
+ NULL, /* multifs_unlink */
+ NULL, /* multifs_readlink */
+ NULL, /* breakpoint_kind_from_pc */
+ win32_sw_breakpoint_from_kind,
};
/* Initialize the Win32 backend. */
initialize_low (void)
{
set_target_ops (&win32_target_ops);
- if (the_low_target.breakpoint != NULL)
- set_breakpoint_data (the_low_target.breakpoint,
- the_low_target.breakpoint_len);
the_low_target.arch_setup ();
}