* win32-low.c: Commit leftover changes from 2007-03-29.
This commit is contained in:
parent
7ce5900041
commit
ed50f18f18
2 changed files with 226 additions and 160 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2007-03-30 Pedro Alves <pedro_alves@portugalmail.pt>
|
||||||
|
|
||||||
|
* win32-low.c: Commit leftover changes from 2007-03-29.
|
||||||
|
|
||||||
2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
|
2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* i387-fp.c (struct i387_fsave, struct i387_fxsave): Make 16-bit
|
* i387-fp.c (struct i387_fsave, struct i387_fxsave): Make 16-bit
|
||||||
|
|
|
@ -23,8 +23,11 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "gdb/signals.h"
|
#include "gdb/signals.h"
|
||||||
|
#include "mem-break.h"
|
||||||
|
#include "win32-low.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <winnt.h>
|
||||||
#include <imagehlp.h>
|
#include <imagehlp.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -41,7 +44,15 @@
|
||||||
#if LOG
|
#if LOG
|
||||||
#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
|
#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
|
||||||
#else
|
#else
|
||||||
#define OUTMSG2(X)
|
#define OUTMSG2(X) do ; while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _T
|
||||||
|
#define _T(x) TEXT (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef COUNTOF
|
||||||
|
#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int using_threads = 1;
|
int using_threads = 1;
|
||||||
|
@ -56,25 +67,28 @@ static DEBUG_EVENT current_event;
|
||||||
|
|
||||||
static int debug_registers_changed = 0;
|
static int debug_registers_changed = 0;
|
||||||
static int debug_registers_used = 0;
|
static int debug_registers_used = 0;
|
||||||
static unsigned dr[8];
|
|
||||||
|
#define NUM_REGS (the_low_target.num_regs)
|
||||||
|
|
||||||
typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
|
typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
|
||||||
typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
|
typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
|
||||||
|
|
||||||
#define FLAG_TRACE_BIT 0x100
|
#ifndef CONTEXT_EXTENDED_REGISTERS
|
||||||
|
#define CONTEXT_EXTENDED_REGISTERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONTEXT_FLOATING_POINT
|
||||||
|
#define CONTEXT_FLOATING_POINT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONTEXT_DEBUG_REGISTERS
|
||||||
|
#define CONTEXT_DEBUG_REGISTERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
|
#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
|
||||||
#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
|
#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
|
||||||
| CONTEXT_EXTENDED_REGISTERS
|
| CONTEXT_EXTENDED_REGISTERS
|
||||||
|
|
||||||
/* Thread information structure used to track extra information about
|
|
||||||
each thread. */
|
|
||||||
typedef struct win32_thread_info
|
|
||||||
{
|
|
||||||
DWORD tid;
|
|
||||||
HANDLE h;
|
|
||||||
int suspend_count;
|
|
||||||
CONTEXT context;
|
|
||||||
} win32_thread_info;
|
|
||||||
static DWORD main_thread_id = 0;
|
static DWORD main_thread_id = 0;
|
||||||
|
|
||||||
/* Get the thread ID from the current selected inferior (the current
|
/* Get the thread ID from the current selected inferior (the current
|
||||||
|
@ -113,12 +127,8 @@ thread_rec (DWORD id, int get_context)
|
||||||
if (id == current_event.dwThreadId)
|
if (id == current_event.dwThreadId)
|
||||||
{
|
{
|
||||||
/* Copy dr values from that thread. */
|
/* Copy dr values from that thread. */
|
||||||
dr[0] = th->context.Dr0;
|
if (the_low_target.store_debug_registers != NULL)
|
||||||
dr[1] = th->context.Dr1;
|
(*the_low_target.store_debug_registers) (th);
|
||||||
dr[2] = th->context.Dr2;
|
|
||||||
dr[3] = th->context.Dr3;
|
|
||||||
dr[6] = th->context.Dr6;
|
|
||||||
dr[7] = th->context.Dr7;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,20 +155,16 @@ child_add_thread (DWORD tid, HANDLE h)
|
||||||
new_register_cache ());
|
new_register_cache ());
|
||||||
|
|
||||||
/* Set the debug registers for the new thread if they are used. */
|
/* Set the debug registers for the new thread if they are used. */
|
||||||
if (debug_registers_used)
|
if (debug_registers_used
|
||||||
|
&& the_low_target.load_debug_registers != NULL)
|
||||||
{
|
{
|
||||||
/* Only change the value of the debug registers. */
|
/* Only change the value of the debug registers. */
|
||||||
th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
|
th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
|
||||||
|
|
||||||
GetThreadContext (th->h, &th->context);
|
GetThreadContext (th->h, &th->context);
|
||||||
|
|
||||||
th->context.Dr0 = dr[0];
|
(*the_low_target.load_debug_registers) (th);
|
||||||
th->context.Dr1 = dr[1];
|
|
||||||
th->context.Dr2 = dr[2];
|
|
||||||
th->context.Dr3 = dr[3];
|
|
||||||
/* th->context.Dr6 = dr[6];
|
|
||||||
FIXME: should we set dr6 also ?? */
|
|
||||||
th->context.Dr7 = dr[7];
|
|
||||||
SetThreadContext (th->h, &th->context);
|
SetThreadContext (th->h, &th->context);
|
||||||
th->context.ContextFlags = 0;
|
th->context.ContextFlags = 0;
|
||||||
}
|
}
|
||||||
|
@ -257,60 +263,26 @@ struct target_waitstatus
|
||||||
value;
|
value;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_REGS 41
|
/* Return a pointer into a CONTEXT field indexed by gdb register number.
|
||||||
#define FCS_REGNUM 27
|
Return a pointer to an dummy register holding zero if there is no
|
||||||
#define FOP_REGNUM 31
|
corresponding CONTEXT field for the given register number. */
|
||||||
|
char *
|
||||||
|
regptr (CONTEXT* c, int r)
|
||||||
|
{
|
||||||
|
if (the_low_target.regmap[r] < 0)
|
||||||
|
{
|
||||||
|
static ULONG zero;
|
||||||
|
/* Always force value to zero, in case the user tried to write
|
||||||
|
to this register before. */
|
||||||
|
zero = 0;
|
||||||
|
return (char *) &zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (char *) c + the_low_target.regmap[r];
|
||||||
|
}
|
||||||
|
|
||||||
#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
|
|
||||||
static const int mappings[] = {
|
|
||||||
context_offset (Eax),
|
|
||||||
context_offset (Ecx),
|
|
||||||
context_offset (Edx),
|
|
||||||
context_offset (Ebx),
|
|
||||||
context_offset (Esp),
|
|
||||||
context_offset (Ebp),
|
|
||||||
context_offset (Esi),
|
|
||||||
context_offset (Edi),
|
|
||||||
context_offset (Eip),
|
|
||||||
context_offset (EFlags),
|
|
||||||
context_offset (SegCs),
|
|
||||||
context_offset (SegSs),
|
|
||||||
context_offset (SegDs),
|
|
||||||
context_offset (SegEs),
|
|
||||||
context_offset (SegFs),
|
|
||||||
context_offset (SegGs),
|
|
||||||
context_offset (FloatSave.RegisterArea[0 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[1 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[2 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[3 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[4 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[5 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[6 * 10]),
|
|
||||||
context_offset (FloatSave.RegisterArea[7 * 10]),
|
|
||||||
context_offset (FloatSave.ControlWord),
|
|
||||||
context_offset (FloatSave.StatusWord),
|
|
||||||
context_offset (FloatSave.TagWord),
|
|
||||||
context_offset (FloatSave.ErrorSelector),
|
|
||||||
context_offset (FloatSave.ErrorOffset),
|
|
||||||
context_offset (FloatSave.DataSelector),
|
|
||||||
context_offset (FloatSave.DataOffset),
|
|
||||||
context_offset (FloatSave.ErrorSelector),
|
|
||||||
/* XMM0-7 */
|
|
||||||
context_offset (ExtendedRegisters[10 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[11 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[12 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[13 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[14 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[15 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[16 * 16]),
|
|
||||||
context_offset (ExtendedRegisters[17 * 16]),
|
|
||||||
/* MXCSR */
|
|
||||||
context_offset (ExtendedRegisters[24])
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef context_offset
|
/* Clear out any old thread list and reinitialize it to a pristine
|
||||||
|
|
||||||
/* Clear out any old thread list and reintialize it to a pristine
|
|
||||||
state. */
|
state. */
|
||||||
static void
|
static void
|
||||||
child_init_thread_list (void)
|
child_init_thread_list (void)
|
||||||
|
@ -321,17 +293,17 @@ child_init_thread_list (void)
|
||||||
static void
|
static void
|
||||||
do_initial_child_stuff (DWORD pid)
|
do_initial_child_stuff (DWORD pid)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
last_sig = TARGET_SIGNAL_0;
|
last_sig = TARGET_SIGNAL_0;
|
||||||
|
|
||||||
debug_registers_changed = 0;
|
debug_registers_changed = 0;
|
||||||
debug_registers_used = 0;
|
debug_registers_used = 0;
|
||||||
for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
|
|
||||||
dr[i] = 0;
|
|
||||||
memset (¤t_event, 0, sizeof (current_event));
|
memset (¤t_event, 0, sizeof (current_event));
|
||||||
|
|
||||||
child_init_thread_list ();
|
child_init_thread_list ();
|
||||||
|
|
||||||
|
if (the_low_target.initial_stuff != NULL)
|
||||||
|
(*the_low_target.initial_stuff) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume all artificially suspended threads if we are continuing
|
/* Resume all artificially suspended threads if we are continuing
|
||||||
|
@ -354,13 +326,10 @@ continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
|
||||||
{
|
{
|
||||||
/* Only change the value of the debug registers. */
|
/* Only change the value of the debug registers. */
|
||||||
th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||||
th->context.Dr0 = dr[0];
|
|
||||||
th->context.Dr1 = dr[1];
|
if (the_low_target.load_debug_registers != NULL)
|
||||||
th->context.Dr2 = dr[2];
|
the_low_target.load_debug_registers (th);
|
||||||
th->context.Dr3 = dr[3];
|
|
||||||
/* th->context.Dr6 = dr[6];
|
|
||||||
FIXME: should we set dr6 also ?? */
|
|
||||||
th->context.Dr7 = dr[7];
|
|
||||||
SetThreadContext (th->h, &th->context);
|
SetThreadContext (th->h, &th->context);
|
||||||
th->context.ContextFlags = 0;
|
th->context.ContextFlags = 0;
|
||||||
}
|
}
|
||||||
|
@ -384,26 +353,6 @@ child_continue (DWORD continue_status, int thread_id)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch register(s) from gdbserver regcache data. */
|
|
||||||
static void
|
|
||||||
do_child_fetch_inferior_registers (win32_thread_info *th, int r)
|
|
||||||
{
|
|
||||||
char *context_offset = ((char *) &th->context) + mappings[r];
|
|
||||||
long l;
|
|
||||||
if (r == FCS_REGNUM)
|
|
||||||
{
|
|
||||||
l = *((long *) context_offset) & 0xffff;
|
|
||||||
supply_register (r, (char *) &l);
|
|
||||||
}
|
|
||||||
else if (r == FOP_REGNUM)
|
|
||||||
{
|
|
||||||
l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
|
|
||||||
supply_register (r, (char *) &l);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
supply_register (r, context_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch register(s) from the current thread context. */
|
/* Fetch register(s) from the current thread context. */
|
||||||
static void
|
static void
|
||||||
child_fetch_inferior_registers (int r)
|
child_fetch_inferior_registers (int r)
|
||||||
|
@ -414,14 +363,14 @@ child_fetch_inferior_registers (int r)
|
||||||
child_fetch_inferior_registers (NUM_REGS);
|
child_fetch_inferior_registers (NUM_REGS);
|
||||||
else
|
else
|
||||||
for (regno = 0; regno < r; regno++)
|
for (regno = 0; regno < r; regno++)
|
||||||
do_child_fetch_inferior_registers (th, regno);
|
(*the_low_target.fetch_inferior_registers) (th, regno);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get register from gdbserver regcache data. */
|
/* Get register from gdbserver regcache data. */
|
||||||
static void
|
static void
|
||||||
do_child_store_inferior_registers (win32_thread_info *th, int r)
|
do_child_store_inferior_registers (win32_thread_info *th, int r)
|
||||||
{
|
{
|
||||||
collect_register (r, ((char *) &th->context) + mappings[r]);
|
collect_register (r, regptr (&th->context, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store a new register value into the current thread context. We don't
|
/* Store a new register value into the current thread context. We don't
|
||||||
|
@ -438,6 +387,61 @@ child_store_inferior_registers (int r)
|
||||||
do_child_store_inferior_registers (th, regno);
|
do_child_store_inferior_registers (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 */
|
||||||
|
(LPVOID)&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 (%ld)", error);
|
||||||
|
|
||||||
|
SetLastError (lasterr);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start a new process.
|
/* Start a new process.
|
||||||
PROGRAM is a path to the program to execute.
|
PROGRAM is a path to the program to execute.
|
||||||
ARGS is a standard NULL-terminated array of arguments,
|
ARGS is a standard NULL-terminated array of arguments,
|
||||||
|
@ -451,21 +455,22 @@ win32_create_inferior (char *program, char **program_args)
|
||||||
char real_path[MAXPATHLEN];
|
char real_path[MAXPATHLEN];
|
||||||
char *orig_path, *new_path, *path_ptr;
|
char *orig_path, *new_path, *path_ptr;
|
||||||
#endif
|
#endif
|
||||||
char *winenv = NULL;
|
|
||||||
STARTUPINFO si;
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
char *args;
|
char *args;
|
||||||
int argslen;
|
int argslen;
|
||||||
int argc;
|
int argc;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
#ifndef __MINGW32CE__
|
||||||
|
STARTUPINFO si = { sizeof (STARTUPINFO) };
|
||||||
|
char *winenv = NULL;
|
||||||
|
#else
|
||||||
|
wchar_t *wargs, *wprogram;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!program)
|
if (!program)
|
||||||
error ("No executable specified, specify executable to debug.\n");
|
error ("No executable specified, specify executable to debug.\n");
|
||||||
|
|
||||||
memset (&si, 0, sizeof (si));
|
|
||||||
si.cb = sizeof (si);
|
|
||||||
|
|
||||||
flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
||||||
|
|
||||||
#ifndef USE_WIN32API
|
#ifndef USE_WIN32API
|
||||||
|
@ -483,11 +488,11 @@ win32_create_inferior (char *program, char **program_args)
|
||||||
program = real_path;
|
program = real_path;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
argslen = strlen (program) + 1;
|
argslen = 1;
|
||||||
for (argc = 1; program_args[argc]; argc++)
|
for (argc = 1; program_args[argc]; argc++)
|
||||||
argslen += strlen (program_args[argc]) + 1;
|
argslen += strlen (program_args[argc]) + 1;
|
||||||
args = alloca (argslen);
|
args = alloca (argslen);
|
||||||
strcpy (args, program);
|
args[0] = '\0';
|
||||||
for (argc = 1; program_args[argc]; argc++)
|
for (argc = 1; program_args[argc]; argc++)
|
||||||
{
|
{
|
||||||
/* FIXME: Can we do better about quoting? How does Cygwin
|
/* FIXME: Can we do better about quoting? How does Cygwin
|
||||||
|
@ -495,17 +500,40 @@ win32_create_inferior (char *program, char **program_args)
|
||||||
strcat (args, " ");
|
strcat (args, " ");
|
||||||
strcat (args, program_args[argc]);
|
strcat (args, program_args[argc]);
|
||||||
}
|
}
|
||||||
OUTMSG2 (("Command line is %s\n", args));
|
OUTMSG2 (("Command line is \"%s\"\n", args));
|
||||||
|
|
||||||
|
#ifdef CREATE_NEW_PROCESS_GROUP
|
||||||
flags |= CREATE_NEW_PROCESS_GROUP;
|
flags |= CREATE_NEW_PROCESS_GROUP;
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = CreateProcess (0, args, /* command line */
|
#ifdef __MINGW32CE__
|
||||||
NULL, /* Security */
|
to_back_slashes (program);
|
||||||
|
wargs = alloca (argslen * sizeof (wchar_t));
|
||||||
|
mbstowcs (wargs, args, argslen);
|
||||||
|
wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
|
||||||
|
mbstowcs (wprogram, program, strlen (program) + 1);
|
||||||
|
ret = CreateProcessW (wprogram, /* image name */
|
||||||
|
wargs, /* command line */
|
||||||
|
NULL, /* security, not supported */
|
||||||
|
NULL, /* thread, not supported */
|
||||||
|
FALSE, /* inherit handles, not supported */
|
||||||
|
flags, /* start flags */
|
||||||
|
NULL, /* environment, not supported */
|
||||||
|
NULL, /* current directory, not supported */
|
||||||
|
NULL, /* start info, not supported */
|
||||||
|
&pi); /* proc info */
|
||||||
|
#else
|
||||||
|
ret = CreateProcess (program, /* image name */
|
||||||
|
args, /* command line */
|
||||||
|
NULL, /* security */
|
||||||
NULL, /* thread */
|
NULL, /* thread */
|
||||||
TRUE, /* inherit handles */
|
TRUE, /* inherit handles */
|
||||||
flags, /* start flags */
|
flags, /* start flags */
|
||||||
winenv, NULL, /* current directory */
|
winenv, /* environment */
|
||||||
&si, &pi);
|
NULL, /* current directory */
|
||||||
|
&si, /* start info */
|
||||||
|
&pi); /* proc info */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USE_WIN32API
|
#ifndef USE_WIN32API
|
||||||
if (orig_path)
|
if (orig_path)
|
||||||
|
@ -514,15 +542,21 @@ win32_create_inferior (char *program, char **program_args)
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
error ("Error creating process %s, (error %d): %s\n", args,
|
DWORD err = GetLastError ();
|
||||||
(int) GetLastError (), strerror (GetLastError ()));
|
error ("Error creating process \"%s%s\", (error %d): %s\n",
|
||||||
|
program, args, (int) err, strwinerror (err));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OUTMSG2 (("Process created: %s\n", (char *) args));
|
OUTMSG2 (("Process created: %s\n", (char *) args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32_WCE
|
||||||
|
/* On Windows CE this handle can't be closed. The OS reuses
|
||||||
|
it in the debug events, while the 9x/NT versions of Windows
|
||||||
|
probably use a DuplicateHandle'd one. */
|
||||||
CloseHandle (pi.hThread);
|
CloseHandle (pi.hThread);
|
||||||
|
#endif
|
||||||
|
|
||||||
current_process_handle = pi.hProcess;
|
current_process_handle = pi.hProcess;
|
||||||
current_process_id = pi.dwProcessId;
|
current_process_id = pi.dwProcessId;
|
||||||
|
@ -539,16 +573,18 @@ static int
|
||||||
win32_attach (unsigned long pid)
|
win32_attach (unsigned long pid)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
|
|
||||||
winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
|
winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
|
||||||
winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
|
|
||||||
|
|
||||||
DebugActiveProcessStop =
|
winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
|
||||||
(winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
|
#ifdef _WIN32_WCE
|
||||||
"DebugActiveProcessStop");
|
HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
|
||||||
DebugSetProcessKillOnExit =
|
#else
|
||||||
(winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
|
HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
|
||||||
"DebugSetProcessKillOnExit");
|
#endif
|
||||||
|
DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
|
||||||
|
GetProcAddress (dll, _T("DebugActiveProcessStop"));
|
||||||
|
DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
|
||||||
|
GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
|
||||||
|
|
||||||
res = DebugActiveProcess (pid) ? 1 : 0;
|
res = DebugActiveProcess (pid) ? 1 : 0;
|
||||||
|
|
||||||
|
@ -571,8 +607,6 @@ win32_attach (unsigned long pid)
|
||||||
if (res)
|
if (res)
|
||||||
do_initial_child_stuff (pid);
|
do_initial_child_stuff (pid);
|
||||||
|
|
||||||
FreeLibrary (kernel32);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,6 +651,8 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
|
||||||
static void
|
static void
|
||||||
win32_kill (void)
|
win32_kill (void)
|
||||||
{
|
{
|
||||||
|
win32_thread_info *current_thread;
|
||||||
|
|
||||||
if (current_process_handle == NULL)
|
if (current_process_handle == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -635,22 +671,32 @@ win32_kill (void)
|
||||||
handle_output_debug_string (&our_status);
|
handle_output_debug_string (&our_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloseHandle (current_process_handle);
|
||||||
|
|
||||||
|
current_thread = inferior_target_data (current_inferior);
|
||||||
|
if (current_thread && current_thread->h)
|
||||||
|
{
|
||||||
|
/* This may fail in an attached process, so don't check. */
|
||||||
|
(void) CloseHandle (current_thread->h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach from all inferiors. */
|
/* Detach from all inferiors. */
|
||||||
static void
|
static void
|
||||||
win32_detach (void)
|
win32_detach (void)
|
||||||
{
|
{
|
||||||
HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
|
|
||||||
winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
|
winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
|
||||||
winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
|
winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
DebugActiveProcessStop =
|
HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
|
||||||
(winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
|
#else
|
||||||
"DebugActiveProcessStop");
|
HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
|
||||||
DebugSetProcessKillOnExit =
|
#endif
|
||||||
(winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
|
DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
|
||||||
"DebugSetProcessKillOnExit");
|
GetProcAddress (dll, _T("DebugActiveProcessStop"));
|
||||||
|
DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
|
||||||
|
GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
|
||||||
|
|
||||||
if (DebugSetProcessKillOnExit != NULL)
|
if (DebugSetProcessKillOnExit != NULL)
|
||||||
DebugSetProcessKillOnExit (FALSE);
|
DebugSetProcessKillOnExit (FALSE);
|
||||||
|
@ -659,8 +705,6 @@ win32_detach (void)
|
||||||
DebugActiveProcessStop (current_process_id);
|
DebugActiveProcessStop (current_process_id);
|
||||||
else
|
else
|
||||||
win32_kill ();
|
win32_kill ();
|
||||||
|
|
||||||
FreeLibrary (kernel32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 iff the thread with thread ID TID is alive. */
|
/* Return 1 iff the thread with thread ID TID is alive. */
|
||||||
|
@ -733,23 +777,21 @@ win32_resume (struct thread_resume *resume_info)
|
||||||
if (th->context.ContextFlags)
|
if (th->context.ContextFlags)
|
||||||
{
|
{
|
||||||
if (debug_registers_changed)
|
if (debug_registers_changed)
|
||||||
{
|
if (the_low_target.load_debug_registers != NULL)
|
||||||
th->context.Dr0 = dr[0];
|
(*the_low_target.load_debug_registers) (th);
|
||||||
th->context.Dr1 = dr[1];
|
|
||||||
th->context.Dr2 = dr[2];
|
|
||||||
th->context.Dr3 = dr[3];
|
|
||||||
/* th->context.Dr6 = dr[6];
|
|
||||||
FIXME: should we set dr6 also ?? */
|
|
||||||
th->context.Dr7 = dr[7];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move register values from the inferior into the thread
|
/* Move register values from the inferior into the thread
|
||||||
context structure. */
|
context structure. */
|
||||||
regcache_invalidate ();
|
regcache_invalidate ();
|
||||||
|
|
||||||
if (step)
|
if (step)
|
||||||
th->context.EFlags |= FLAG_TRACE_BIT;
|
{
|
||||||
|
if (the_low_target.single_step != NULL)
|
||||||
|
(*the_low_target.single_step) (th);
|
||||||
|
else
|
||||||
|
error ("Single stepping is not supported "
|
||||||
|
"in this configuration.\n");
|
||||||
|
}
|
||||||
SetThreadContext (th->h, &th->context);
|
SetThreadContext (th->h, &th->context);
|
||||||
th->context.ContextFlags = 0;
|
th->context.ContextFlags = 0;
|
||||||
}
|
}
|
||||||
|
@ -825,6 +867,11 @@ handle_exception (struct target_waitstatus *ourstatus)
|
||||||
case EXCEPTION_BREAKPOINT:
|
case EXCEPTION_BREAKPOINT:
|
||||||
OUTMSG2 (("EXCEPTION_BREAKPOINT"));
|
OUTMSG2 (("EXCEPTION_BREAKPOINT"));
|
||||||
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
/* Remove the initial breakpoint. */
|
||||||
|
check_breakpoints ((CORE_ADDR) (long) current_event
|
||||||
|
.u.Exception.ExceptionRecord.ExceptionAddress);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case DBG_CONTROL_C:
|
case DBG_CONTROL_C:
|
||||||
OUTMSG2 (("DBG_CONTROL_C"));
|
OUTMSG2 (("DBG_CONTROL_C"));
|
||||||
|
@ -934,6 +981,14 @@ in:
|
||||||
current_event.u.CreateProcessInfo.hThread);
|
current_event.u.CreateProcessInfo.hThread);
|
||||||
|
|
||||||
retval = ourstatus->value.related_pid = current_event.dwThreadId;
|
retval = ourstatus->value.related_pid = current_event.dwThreadId;
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
/* Windows CE doesn't set the initial breakpoint automatically
|
||||||
|
like the desktop versions of Windows do. We add it explicitly
|
||||||
|
here. It will be removed as soon as it is hit. */
|
||||||
|
set_breakpoint_at ((CORE_ADDR) (long) current_event.u
|
||||||
|
.CreateProcessInfo.lpStartAddress,
|
||||||
|
delete_breakpoint_at);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
|
@ -1037,8 +1092,13 @@ win32_wait (char *status)
|
||||||
}
|
}
|
||||||
else if (our_status.kind == TARGET_WAITKIND_STOPPED)
|
else if (our_status.kind == TARGET_WAITKIND_STOPPED)
|
||||||
{
|
{
|
||||||
|
#ifndef __MINGW32CE__
|
||||||
OUTMSG2 (("Child Stopped with signal = %x \n",
|
OUTMSG2 (("Child Stopped with signal = %x \n",
|
||||||
WSTOPSIG (our_status.value.sig)));
|
WSTOPSIG (our_status.value.sig)));
|
||||||
|
#else
|
||||||
|
OUTMSG2 (("Child Stopped with signal = %x \n",
|
||||||
|
our_status.value.sig));
|
||||||
|
#endif
|
||||||
|
|
||||||
*status = 'T';
|
*status = 'T';
|
||||||
|
|
||||||
|
@ -1082,7 +1142,7 @@ win32_store_inferior_registers (int regno)
|
||||||
static int
|
static int
|
||||||
win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
|
win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
|
||||||
{
|
{
|
||||||
return child_xfer_memory (memaddr, myaddr, len, 0, 0) != len;
|
return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write memory to the inferior process. This should generally be
|
/* Write memory to the inferior process. This should generally be
|
||||||
|
@ -1099,7 +1159,7 @@ win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
|
||||||
static const char *
|
static const char *
|
||||||
win32_arch_string (void)
|
win32_arch_string (void)
|
||||||
{
|
{
|
||||||
return "i386";
|
return the_low_target.arch_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct target_ops win32_target_ops = {
|
static struct target_ops win32_target_ops = {
|
||||||
|
@ -1131,6 +1191,8 @@ void
|
||||||
initialize_low (void)
|
initialize_low (void)
|
||||||
{
|
{
|
||||||
set_target_ops (&win32_target_ops);
|
set_target_ops (&win32_target_ops);
|
||||||
|
if (the_low_target.breakpoint != NULL)
|
||||||
|
set_breakpoint_data (the_low_target.breakpoint,
|
||||||
|
the_low_target.breakpoint_len);
|
||||||
init_registers ();
|
init_registers ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue