* wince-stub.c (FREE): New macro.
(mempool): Just free any buffer prior to reuse. Don't bother with realloc. (flag_single_step): New function. (skip_message): Detect "helpful" Windows CE messages and skip sending them to the host. (wait_for_debug_event): Use skip_message to avoid sending debug messages to the host. (dispatch): Prelimary implementation of single step detection. * wince.c: Rework SH single stepping code to be more consistent with other wince targets. (handle_output_debug_string): Allow first chance exceptions to come through since they seem to be all that we get on some versions of Windows CE. (check_for_step): New function, conditionally compiled based on target. (regptr): Delete obsolete function. (handle_exception): Detect illegal instructions. (get_child_debug_event): Return success only if event code matches target. (child_create_inferior): Reflect change to get_child_debug_event arguments.
This commit is contained in:
parent
8a892701f5
commit
61c37cee5d
4 changed files with 427 additions and 336 deletions
|
@ -1,3 +1,27 @@
|
||||||
|
2000-04-20 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* wince-stub.c (FREE): New macro.
|
||||||
|
(mempool): Just free any buffer prior to reuse. Don't bother with
|
||||||
|
realloc.
|
||||||
|
(flag_single_step): New function.
|
||||||
|
(skip_message): Detect "helpful" Windows CE messages and skip sending
|
||||||
|
them to the host.
|
||||||
|
(wait_for_debug_event): Use skip_message to avoid sending debug
|
||||||
|
messages to the host.
|
||||||
|
(dispatch): Prelimary implementation of single step detection.
|
||||||
|
* wince.c: Rework SH single stepping code to be more consistent with
|
||||||
|
other wince targets.
|
||||||
|
(handle_output_debug_string): Allow first chance exceptions to come
|
||||||
|
through since they seem to be all that we get on some versions of
|
||||||
|
Windows CE.
|
||||||
|
(check_for_step): New function, conditionally compiled based on target.
|
||||||
|
(regptr): Delete obsolete function.
|
||||||
|
(handle_exception): Detect illegal instructions.
|
||||||
|
(get_child_debug_event): Return success only if event code matches
|
||||||
|
target.
|
||||||
|
(child_create_inferior): Reflect change to get_child_debug_event
|
||||||
|
arguments.
|
||||||
|
|
||||||
2000-04-20 Christopher Faylor <cgf@cygnus.com>
|
2000-04-20 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
* win32-nat.c (thread_rec): Be more defensive about suspending already
|
* win32-nat.c (thread_rec): Be more defensive about suspending already
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Target-specific definition for Window CE
|
/* Target-specific definition for Window CE
|
||||||
Copyright 2000 Free Software Foundation, Inc.
|
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
|
|
||||||
|
|
137
gdb/wince-stub.c
137
gdb/wince-stub.c
|
@ -28,12 +28,13 @@
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#include "wince-stub.h"
|
#include "wince-stub.h"
|
||||||
|
|
||||||
#define MALLOC(n) (void *) LocalAlloc (LMEM_MOVEABLE, (UINT)(n))
|
#define MALLOC(n) (void *) LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, (UINT)(n))
|
||||||
#define REALLOC(s, n) (void *) LocalReAlloc ((HLOCAL)(s), (UINT)(n), LMEM_MOVEABLE)
|
#define REALLOC(s, n) (void *) LocalReAlloc ((HLOCAL)(s), (UINT)(n), LMEM_MOVEABLE)
|
||||||
|
#define FREE(s) LocalFree ((HLOCAL)(s))
|
||||||
|
|
||||||
static int skip_next_id = 0; /* Don't read next API code from socket */
|
static int skip_next_id = 0; /* Don't read next API code from socket */
|
||||||
|
|
||||||
/* v-style interface for handling varying argyment list error messages.
|
/* v-style interface for handling varying argument list error messages.
|
||||||
Displays the error message in a dialog box and exits when user clicks
|
Displays the error message in a dialog box and exits when user clicks
|
||||||
on OK. */
|
on OK. */
|
||||||
static void
|
static void
|
||||||
|
@ -56,6 +57,27 @@ stub_error (LPCWSTR fmt, ...)
|
||||||
vstub_error (fmt, args);
|
vstub_error (fmt, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a limited pool of memory, reallocating over unused
|
||||||
|
buffers. This assumes that there will never be more than four
|
||||||
|
"buffers" required which, so far, is a safe assumption. */
|
||||||
|
static LPVOID
|
||||||
|
mempool (unsigned int len)
|
||||||
|
{
|
||||||
|
static int outn = -1;
|
||||||
|
static LPWSTR outs[4] = {NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
|
if (++outn >= (sizeof (outs) / sizeof (outs[0])))
|
||||||
|
outn = 0;
|
||||||
|
|
||||||
|
/* Allocate space for the converted string, reusing any previously allocated
|
||||||
|
space, if applicable. */
|
||||||
|
if (outs[outn])
|
||||||
|
FREE (outs[outn]);
|
||||||
|
outs[outn] = (LPWSTR) MALLOC (len);
|
||||||
|
|
||||||
|
return outs[outn];
|
||||||
|
}
|
||||||
|
|
||||||
/* Standard "oh well" can't communicate error. Someday this might attempt
|
/* Standard "oh well" can't communicate error. Someday this might attempt
|
||||||
synchronization. */
|
synchronization. */
|
||||||
static void
|
static void
|
||||||
|
@ -88,28 +110,6 @@ sockwrite (LPCWSTR huh, int s, const void *str, size_t n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a limited pool of memory, reallocating over unused
|
|
||||||
buffers. This assumes that there will never be more than four
|
|
||||||
"buffers" required which, so far, is a safe assumption. */
|
|
||||||
static LPVOID
|
|
||||||
mempool (gdb_wince_len len)
|
|
||||||
{
|
|
||||||
static int n = -1;
|
|
||||||
static LPWSTR outs[4] = {NULL /*, NULL, etc. */};
|
|
||||||
|
|
||||||
if (++n >= (sizeof (outs) / sizeof (outs[0])))
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
/* Allocate space for the converted string, reusing any previously allocated
|
|
||||||
space, if applicable. */
|
|
||||||
if (outs[n])
|
|
||||||
outs[n] = (LPWSTR) REALLOC (outs[n], len);
|
|
||||||
else
|
|
||||||
outs[n] = (LPWSTR) MALLOC (len);
|
|
||||||
|
|
||||||
return outs[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a an ID (possibly) and a DWORD from the host gdb.
|
/* Get a an ID (possibly) and a DWORD from the host gdb.
|
||||||
Don't bother with the id if the main loop has already
|
Don't bother with the id if the main loop has already
|
||||||
read it. */
|
read it. */
|
||||||
|
@ -175,7 +175,7 @@ getmemory (LPCWSTR huh, int s, gdb_wince_id what, gdb_wince_len *inlen)
|
||||||
|
|
||||||
*inlen = getlen (huh, s, what);
|
*inlen = getlen (huh, s, what);
|
||||||
|
|
||||||
p = mempool (*inlen); /* FIXME: check for error */
|
p = mempool ((unsigned int) *inlen); /* FIXME: check for error */
|
||||||
|
|
||||||
if ((gdb_wince_len) sockread (huh, s, p, *inlen) != *inlen)
|
if ((gdb_wince_len) sockread (huh, s, p, *inlen) != *inlen)
|
||||||
stub_error (L"error getting string from host.");
|
stub_error (L"error getting string from host.");
|
||||||
|
@ -269,6 +269,49 @@ terminate_process (int s)
|
||||||
&res, sizeof (res));
|
&res, sizeof (res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stepped = 0;
|
||||||
|
/* Handle single step instruction. FIXME: unneded? */
|
||||||
|
static void
|
||||||
|
flag_single_step (int s)
|
||||||
|
{
|
||||||
|
stepped = 1;
|
||||||
|
skip_next_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct skipper
|
||||||
|
{
|
||||||
|
wchar_t *s;
|
||||||
|
int nskip;
|
||||||
|
} skippy[] =
|
||||||
|
{
|
||||||
|
{L"Undefined Instruction:", 1},
|
||||||
|
{L"Data Abort:", 2},
|
||||||
|
{NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
skip_message (DEBUG_EVENT *ev)
|
||||||
|
{
|
||||||
|
char s[80];
|
||||||
|
DWORD nread;
|
||||||
|
struct skipper *skp;
|
||||||
|
int nbytes = ev->u.DebugString.nDebugStringLength;
|
||||||
|
|
||||||
|
if (nbytes > sizeof(s))
|
||||||
|
nbytes = sizeof(s);
|
||||||
|
|
||||||
|
memset (s, 0, sizeof (s));
|
||||||
|
if (!ReadProcessMemory (curproc, ev->u.DebugString.lpDebugStringData,
|
||||||
|
s, nbytes, &nread))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (skp = skippy; skp->s != NULL; skp++)
|
||||||
|
if (wcsncmp ((wchar_t *) s, skp->s, wcslen (skp->s)) == 0)
|
||||||
|
return skp->nskip;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emulate WaitForDebugEvent. Returns the debug event on success. */
|
/* Emulate WaitForDebugEvent. Returns the debug event on success. */
|
||||||
static void
|
static void
|
||||||
wait_for_debug_event (int s)
|
wait_for_debug_event (int s)
|
||||||
|
@ -276,10 +319,32 @@ wait_for_debug_event (int s)
|
||||||
DWORD ms = getdword (L"WaitForDebugEvent ms", s, GDB_WAITFORDEBUGEVENT);
|
DWORD ms = getdword (L"WaitForDebugEvent ms", s, GDB_WAITFORDEBUGEVENT);
|
||||||
gdb_wince_result res;
|
gdb_wince_result res;
|
||||||
DEBUG_EVENT ev;
|
DEBUG_EVENT ev;
|
||||||
|
static int skip_next = 0;
|
||||||
|
|
||||||
res = WaitForDebugEvent (&ev, ms);
|
for (;;)
|
||||||
putresult (L"WaitForDebugEvent event", res, s, GDB_WAITFORDEBUGEVENT,
|
{
|
||||||
&ev, sizeof (ev));
|
res = WaitForDebugEvent (&ev, ms);
|
||||||
|
|
||||||
|
if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
|
||||||
|
{
|
||||||
|
if (skip_next)
|
||||||
|
{
|
||||||
|
skip_next--;
|
||||||
|
goto ignore;
|
||||||
|
}
|
||||||
|
if (skip_next = skip_message (&ev))
|
||||||
|
goto ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
putresult (L"WaitForDebugEvent event", res, s, GDB_WAITFORDEBUGEVENT,
|
||||||
|
&ev, sizeof (ev));
|
||||||
|
break;
|
||||||
|
|
||||||
|
ignore:
|
||||||
|
ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emulate GetThreadContext. Returns CONTEXT structure on success. */
|
/* Emulate GetThreadContext. Returns CONTEXT structure on success. */
|
||||||
|
@ -291,7 +356,7 @@ get_thread_context (int s)
|
||||||
gdb_wince_result res;
|
gdb_wince_result res;
|
||||||
|
|
||||||
memset (&c, 0, sizeof (c));
|
memset (&c, 0, sizeof (c));
|
||||||
c.ContextFlags = getdword (L"GetThreadContext handle", s, GDB_GETTHREADCONTEXT);
|
c.ContextFlags = getdword (L"GetThreadContext flags", s, GDB_GETTHREADCONTEXT);
|
||||||
|
|
||||||
res = (gdb_wince_result) GetThreadContext (h, &c);
|
res = (gdb_wince_result) GetThreadContext (h, &c);
|
||||||
putresult (L"GetThreadContext data", res, s, GDB_GETTHREADCONTEXT,
|
putresult (L"GetThreadContext data", res, s, GDB_GETTHREADCONTEXT,
|
||||||
|
@ -319,7 +384,7 @@ read_process_memory (int s)
|
||||||
HANDLE h = gethandle (L"ReadProcessMemory handle", s, GDB_READPROCESSMEMORY);
|
HANDLE h = gethandle (L"ReadProcessMemory handle", s, GDB_READPROCESSMEMORY);
|
||||||
LPVOID p = getpvoid (L"ReadProcessMemory base", s, GDB_READPROCESSMEMORY);
|
LPVOID p = getpvoid (L"ReadProcessMemory base", s, GDB_READPROCESSMEMORY);
|
||||||
gdb_wince_len len = getlen (L"ReadProcessMemory size", s, GDB_READPROCESSMEMORY);
|
gdb_wince_len len = getlen (L"ReadProcessMemory size", s, GDB_READPROCESSMEMORY);
|
||||||
LPVOID buf = mempool ((gdb_wince_len) len);
|
LPVOID buf = mempool ((unsigned int) len);
|
||||||
DWORD outlen;
|
DWORD outlen;
|
||||||
gdb_wince_result res;
|
gdb_wince_result res;
|
||||||
|
|
||||||
|
@ -400,12 +465,6 @@ close_handle (int s)
|
||||||
putresult (L"CloseHandle result", res, s, GDB_CLOSEHANDLE, &res, sizeof (res));
|
putresult (L"CloseHandle result", res, s, GDB_CLOSEHANDLE, &res, sizeof (res));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle single step instruction */
|
|
||||||
static void
|
|
||||||
single_step (int s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main loop for reading requests from gdb host on the socket. */
|
/* Main loop for reading requests from gdb host on the socket. */
|
||||||
static void
|
static void
|
||||||
dispatch (int s)
|
dispatch (int s)
|
||||||
|
@ -458,8 +517,8 @@ dispatch (int s)
|
||||||
terminate_process (s);
|
terminate_process (s);
|
||||||
return;
|
return;
|
||||||
case GDB_SINGLESTEP:
|
case GDB_SINGLESTEP:
|
||||||
single_step (s);
|
flag_single_step (s);
|
||||||
return;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
WCHAR buf[80];
|
WCHAR buf[80];
|
||||||
|
@ -495,8 +554,6 @@ WinMain (HINSTANCE hi, HINSTANCE hp, LPWSTR cmd, int show)
|
||||||
wcstombs (host, whost, 80); /* Convert from UNICODE to ascii */
|
wcstombs (host, whost, 80); /* Convert from UNICODE to ascii */
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBoxW (NULL, whost, L"GDB", MB_ICONERROR);
|
|
||||||
|
|
||||||
/* Winsock initialization. */
|
/* Winsock initialization. */
|
||||||
if (WSAStartup (MAKEWORD (1, 1), &wd))
|
if (WSAStartup (MAKEWORD (1, 1), &wd))
|
||||||
stub_error (L"Couldn't initialize WINSOCK.");
|
stub_error (L"Couldn't initialize WINSOCK.");
|
||||||
|
|
600
gdb/wince.c
600
gdb/wince.c
|
@ -55,6 +55,7 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include "wince-stub.h"
|
#include "wince-stub.h"
|
||||||
#include "dcache.h"
|
#include "dcache.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
/* The ui's event loop. */
|
/* The ui's event loop. */
|
||||||
extern int (*ui_loop_hook) PARAMS ((int signo));
|
extern int (*ui_loop_hook) PARAMS ((int signo));
|
||||||
|
@ -147,7 +148,6 @@ typedef struct thread_info_struct
|
||||||
int suspend_count;
|
int suspend_count;
|
||||||
int stepped; /* True if stepped. */
|
int stepped; /* True if stepped. */
|
||||||
CORE_ADDR step_pc;
|
CORE_ADDR step_pc;
|
||||||
unsigned long step_instr;
|
|
||||||
unsigned long step_prev;
|
unsigned long step_prev;
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,7 @@ thread_info;
|
||||||
|
|
||||||
static thread_info thread_head =
|
static thread_info thread_head =
|
||||||
{NULL};
|
{NULL};
|
||||||
|
static thread_info * thread_rec (DWORD id, int get_context);
|
||||||
|
|
||||||
/* The process and thread handles for the above context. */
|
/* The process and thread handles for the above context. */
|
||||||
|
|
||||||
|
@ -374,24 +375,21 @@ static const int mappings[NUM_REGS + 1] =
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This vector maps the target's idea of an exception (extracted
|
/* Return a pointer into a CONTEXT field indexed by gdb register number.
|
||||||
from the DEBUG_EVENT structure) to GDB's idea. */
|
Return a pointer to an address pointing to zero if there is no
|
||||||
|
corresponding CONTEXT field for the given register number.
|
||||||
struct xlate_exception
|
*/
|
||||||
{
|
static ULONG *
|
||||||
int them;
|
regptr (LPCONTEXT c, int r)
|
||||||
enum target_signal us;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct xlate_exception
|
|
||||||
xlate[] =
|
|
||||||
{
|
{
|
||||||
{EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
|
static ULONG zero = 0;
|
||||||
{STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
|
ULONG *p;
|
||||||
{EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
|
if (mappings[r] < 0)
|
||||||
{DBG_CONTROL_C, TARGET_SIGNAL_INT},
|
p = &zero;
|
||||||
{EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
|
else
|
||||||
{-1, -1}};
|
p = (ULONG *) (((char *) c) + mappings[r]);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/******************** Beginning of stub interface ********************/
|
/******************** Beginning of stub interface ********************/
|
||||||
|
|
||||||
|
@ -629,6 +627,7 @@ towide (const char *s, gdb_wince_len * out_len)
|
||||||
typedef in wince-stub.h and change the putlen/getlen macros in this file and in
|
typedef in wince-stub.h and change the putlen/getlen macros in this file and in
|
||||||
the stub.
|
the stub.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_process (LPSTR exec_file, LPSTR args, DWORD flags, PROCESS_INFORMATION * pi)
|
create_process (LPSTR exec_file, LPSTR args, DWORD flags, PROCESS_INFORMATION * pi)
|
||||||
{
|
{
|
||||||
|
@ -798,6 +797,227 @@ stop_stub ()
|
||||||
/******************** End of emulation routines. ********************/
|
/******************** End of emulation routines. ********************/
|
||||||
/******************** End of stub interface ********************/
|
/******************** End of stub interface ********************/
|
||||||
|
|
||||||
|
#define check_for_step(a, x) (x)
|
||||||
|
|
||||||
|
#ifdef MIPS
|
||||||
|
static void
|
||||||
|
undoSStep (thread_info * th)
|
||||||
|
{
|
||||||
|
if (th->stepped)
|
||||||
|
{
|
||||||
|
memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
th->stepped = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
unsigned long pc;
|
||||||
|
thread_info *th = current_thread; /* Info on currently selected thread */
|
||||||
|
CORE_ADDR mips_next_pc (CORE_ADDR pc);
|
||||||
|
|
||||||
|
if (!insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
undoSStep (th);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
th->stepped = 1;
|
||||||
|
pc = read_register (PC_REGNUM);
|
||||||
|
th->step_pc = mips_next_pc (pc);
|
||||||
|
th->step_prev = 0;
|
||||||
|
memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#elif SHx
|
||||||
|
/* Hitachi SH architecture instruction encoding masks */
|
||||||
|
|
||||||
|
#define COND_BR_MASK 0xff00
|
||||||
|
#define UCOND_DBR_MASK 0xe000
|
||||||
|
#define UCOND_RBR_MASK 0xf0df
|
||||||
|
#define TRAPA_MASK 0xff00
|
||||||
|
|
||||||
|
#define COND_DISP 0x00ff
|
||||||
|
#define UCOND_DISP 0x0fff
|
||||||
|
#define UCOND_REG 0x0f00
|
||||||
|
|
||||||
|
/* Hitachi SH instruction opcodes */
|
||||||
|
|
||||||
|
#define BF_INSTR 0x8b00
|
||||||
|
#define BT_INSTR 0x8900
|
||||||
|
#define BRA_INSTR 0xa000
|
||||||
|
#define BSR_INSTR 0xb000
|
||||||
|
#define JMP_INSTR 0x402b
|
||||||
|
#define JSR_INSTR 0x400b
|
||||||
|
#define RTS_INSTR 0x000b
|
||||||
|
#define RTE_INSTR 0x002b
|
||||||
|
#define TRAPA_INSTR 0xc300
|
||||||
|
#define SSTEP_INSTR 0xc3ff
|
||||||
|
|
||||||
|
|
||||||
|
#define T_BIT_MASK 0x0001
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
sh_get_next_pc (CONTEXT *c)
|
||||||
|
{
|
||||||
|
short *instrMem;
|
||||||
|
int displacement;
|
||||||
|
int reg;
|
||||||
|
unsigned short opcode;
|
||||||
|
|
||||||
|
instrMem = (short *) c->Fir;
|
||||||
|
|
||||||
|
opcode = read_memory_integer ((CORE_ADDR) c->Fir, sizeof (opcode));
|
||||||
|
|
||||||
|
if ((opcode & COND_BR_MASK) == BT_INSTR)
|
||||||
|
{
|
||||||
|
if (c->Psr & T_BIT_MASK)
|
||||||
|
{
|
||||||
|
displacement = (opcode & COND_DISP) << 1;
|
||||||
|
if (displacement & 0x80)
|
||||||
|
displacement |= 0xffffff00;
|
||||||
|
/*
|
||||||
|
* Remember PC points to second instr.
|
||||||
|
* after PC of branch ... so add 4
|
||||||
|
*/
|
||||||
|
instrMem = (short *) (c->Fir + displacement + 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
instrMem += 1;
|
||||||
|
}
|
||||||
|
else if ((opcode & COND_BR_MASK) == BF_INSTR)
|
||||||
|
{
|
||||||
|
if (c->Psr & T_BIT_MASK)
|
||||||
|
instrMem += 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
displacement = (opcode & COND_DISP) << 1;
|
||||||
|
if (displacement & 0x80)
|
||||||
|
displacement |= 0xffffff00;
|
||||||
|
/*
|
||||||
|
* Remember PC points to second instr.
|
||||||
|
* after PC of branch ... so add 4
|
||||||
|
*/
|
||||||
|
instrMem = (short *) (c->Fir + displacement + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
|
||||||
|
{
|
||||||
|
displacement = (opcode & UCOND_DISP) << 1;
|
||||||
|
if (displacement & 0x0800)
|
||||||
|
displacement |= 0xfffff000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember PC points to second instr.
|
||||||
|
* after PC of branch ... so add 4
|
||||||
|
*/
|
||||||
|
instrMem = (short *) (c->Fir + displacement + 4);
|
||||||
|
}
|
||||||
|
else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
|
||||||
|
{
|
||||||
|
reg = (char) ((opcode & UCOND_REG) >> 8);
|
||||||
|
|
||||||
|
instrMem = (short *) *regptr (c, reg);
|
||||||
|
}
|
||||||
|
else if (opcode == RTS_INSTR)
|
||||||
|
instrMem = (short *) c->PR;
|
||||||
|
else if (opcode == RTE_INSTR)
|
||||||
|
instrMem = (short *) *regptr (c, 15);
|
||||||
|
else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
|
||||||
|
instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
|
||||||
|
else
|
||||||
|
instrMem += 1;
|
||||||
|
|
||||||
|
return (CORE_ADDR) instrMem;
|
||||||
|
}
|
||||||
|
/* Single step (in a painstaking fashion) by inspecting the current
|
||||||
|
instruction and setting a breakpoint on the "next" instruction
|
||||||
|
which would be executed. This code hails from sh-stub.c.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
undoSStep (thread_info * th)
|
||||||
|
{
|
||||||
|
if (th->stepped)
|
||||||
|
{
|
||||||
|
memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
th->stepped = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Single step (in a painstaking fashion) by inspecting the current
|
||||||
|
instruction and setting a breakpoint on the "next" instruction
|
||||||
|
which would be executed. This code hails from sh-stub.c.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
thread_info *th = current_thread; /* Info on currently selected thread */
|
||||||
|
|
||||||
|
if (!insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
undoSStep (th);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
th->stepped = 1;
|
||||||
|
th->step_pc = sh_get_next_pc (&th->context);
|
||||||
|
th->step_prev = 0;
|
||||||
|
memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#elif defined (ARM)
|
||||||
|
#undef check_for_step
|
||||||
|
|
||||||
|
static enum target_signal
|
||||||
|
check_for_step (DEBUG_EVENT *ev, enum target_signal x)
|
||||||
|
{
|
||||||
|
thread_info *th = thread_rec (ev->dwThreadId, 1);
|
||||||
|
|
||||||
|
if (th->stepped &&
|
||||||
|
th->step_pc == (CORE_ADDR) ev->u.Exception.ExceptionRecord.ExceptionAddress)
|
||||||
|
return TARGET_SIGNAL_TRAP;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Single step (in a painstaking fashion) by inspecting the current
|
||||||
|
instruction and setting a breakpoint on the "next" instruction
|
||||||
|
which would be executed. This code hails from sh-stub.c.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
undoSStep (thread_info * th)
|
||||||
|
{
|
||||||
|
if (th->stepped)
|
||||||
|
{
|
||||||
|
memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
th->stepped = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
unsigned long pc;
|
||||||
|
thread_info *th = current_thread; /* Info on currently selected thread */
|
||||||
|
CORE_ADDR mips_next_pc (CORE_ADDR pc);
|
||||||
|
|
||||||
|
if (!insert_breakpoints_p)
|
||||||
|
{
|
||||||
|
undoSStep (th);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
th->stepped = 1;
|
||||||
|
pc = read_register (PC_REGNUM);
|
||||||
|
th->step_pc = arm_get_next_pc (pc);
|
||||||
|
th->step_prev = 0;
|
||||||
|
memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Find a thread record given a thread id.
|
/* Find a thread record given a thread id.
|
||||||
If get_context then also retrieve the context for this
|
If get_context then also retrieve the context for this
|
||||||
thread. */
|
thread. */
|
||||||
|
@ -893,22 +1113,6 @@ check (BOOL ok, const char *file, int line)
|
||||||
printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
|
printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a pointer into a CONTEXT field indexed by gdb register number.
|
|
||||||
Return a pointer to an address pointing to zero if there is no
|
|
||||||
corresponding CONTEXT field for the given register number.
|
|
||||||
*/
|
|
||||||
static ULONG *
|
|
||||||
regptr (LPCONTEXT c, int r)
|
|
||||||
{
|
|
||||||
static ULONG zero = 0;
|
|
||||||
ULONG *p;
|
|
||||||
if (mappings[r] < 0)
|
|
||||||
p = &zero;
|
|
||||||
else
|
|
||||||
p = (ULONG *) (((char *) c) + mappings[r]);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_child_fetch_inferior_registers (int r)
|
do_child_fetch_inferior_registers (int r)
|
||||||
{
|
{
|
||||||
|
@ -991,7 +1195,9 @@ handle_load_dll (PTR dummy)
|
||||||
out:
|
out:
|
||||||
if (!len)
|
if (!len)
|
||||||
return 1;
|
return 1;
|
||||||
|
#if 0
|
||||||
dll_buf[len] = '\0';
|
dll_buf[len] = '\0';
|
||||||
|
#endif
|
||||||
dll_name = alloca (len);
|
dll_name = alloca (len);
|
||||||
|
|
||||||
if (!dll_name)
|
if (!dll_name)
|
||||||
|
@ -1021,22 +1227,12 @@ out:
|
||||||
FIXME: Is this the real reason that we need the 0x1000 ? */
|
FIXME: Is this the real reason that we need the 0x1000 ? */
|
||||||
|
|
||||||
printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
|
printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
|
||||||
#if 0 /* FIXME: Need to use RAPI stuff to read the file someday. */
|
|
||||||
{
|
|
||||||
struct section_addr_info section_addrs;
|
|
||||||
memset (§ion_addrs, 0, sizeof (section_addrs));
|
|
||||||
section_addrs.text_addr = (int) event->lpBaseOfDll + 0x1000;
|
|
||||||
symbol_file_add (dll_name, 0, §ion_addrs, 0, OBJF_SHARED);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
printf_unfiltered ("\n");
|
printf_unfiltered ("\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle DEBUG_STRING output from child process.
|
/* Handle DEBUG_STRING output from child process. */
|
||||||
Cygwin prepends its messages with a "cygwin:". Interpret this as
|
|
||||||
a Cygwin signal. Otherwise just print the string as a warning. */
|
|
||||||
static void
|
static void
|
||||||
handle_output_debug_string (struct target_waitstatus *ourstatus)
|
handle_output_debug_string (struct target_waitstatus *ourstatus)
|
||||||
{
|
{
|
||||||
|
@ -1068,6 +1264,7 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
warning (s);
|
warning (s);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1075,16 +1272,13 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
|
||||||
static int
|
static int
|
||||||
handle_exception (struct target_waitstatus *ourstatus)
|
handle_exception (struct target_waitstatus *ourstatus)
|
||||||
{
|
{
|
||||||
thread_info *th;
|
#if 0
|
||||||
|
|
||||||
if (current_event.u.Exception.dwFirstChance)
|
if (current_event.u.Exception.dwFirstChance)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
|
|
||||||
/* Record the context of the current thread */
|
|
||||||
th = thread_rec (current_event.dwThreadId, -1);
|
|
||||||
|
|
||||||
switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
|
switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
|
||||||
{
|
{
|
||||||
case EXCEPTION_ACCESS_VIOLATION:
|
case EXCEPTION_ACCESS_VIOLATION:
|
||||||
|
@ -1114,10 +1308,15 @@ handle_exception (struct target_waitstatus *ourstatus)
|
||||||
(unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
|
(unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
|
||||||
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
|
||||||
break;
|
break;
|
||||||
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||||
|
DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
|
||||||
|
current_event.u.Exception.ExceptionRecord.ExceptionAddress));
|
||||||
|
ourstatus->value.sig = check_for_step (¤t_event, TARGET_SIGNAL_ILL);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* This may be a structured exception handling exception. In
|
/* This may be a structured exception handling exception. In
|
||||||
that case, we want to let the program try to handle it, and
|
that case, we want to let the program try to handle it, and
|
||||||
only break if we see the exception a second time. */
|
only break if we see the exception a second time. */
|
||||||
|
|
||||||
printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
|
printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
|
||||||
current_event.u.Exception.ExceptionRecord.ExceptionCode,
|
current_event.u.Exception.ExceptionRecord.ExceptionCode,
|
||||||
|
@ -1159,23 +1358,29 @@ child_continue (DWORD continue_status, int id)
|
||||||
handling by WFI (or whatever).
|
handling by WFI (or whatever).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * event_code, int *retval)
|
get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
|
||||||
|
DWORD target_event_code, int *retval)
|
||||||
{
|
{
|
||||||
|
int breakout = 0;
|
||||||
BOOL debug_event;
|
BOOL debug_event;
|
||||||
DWORD continue_status;
|
DWORD continue_status, event_code;
|
||||||
int breakout = 1;
|
thread_info *th = NULL;
|
||||||
|
static thread_info dummy_thread_info;
|
||||||
|
|
||||||
if (!(debug_event = wait_for_debug_event (¤t_event, 1000)))
|
if (!(debug_event = wait_for_debug_event (¤t_event, 1000)))
|
||||||
{
|
{
|
||||||
breakout = *retval = *event_code = 0;
|
*retval = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
this_thread = thread_rec (current_event.dwThreadId, FALSE);
|
|
||||||
event_count++;
|
event_count++;
|
||||||
continue_status = DBG_CONTINUE;
|
continue_status = DBG_CONTINUE;
|
||||||
*retval = 0;
|
*retval = 0;
|
||||||
switch (*event_code = current_event.dwDebugEventCode)
|
|
||||||
|
event_code = current_event.dwDebugEventCode;
|
||||||
|
breakout = event_code == target_event_code;
|
||||||
|
|
||||||
|
switch (event_code)
|
||||||
{
|
{
|
||||||
case CREATE_THREAD_DEBUG_EVENT:
|
case CREATE_THREAD_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
||||||
|
@ -1183,8 +1388,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event.dwThreadId,
|
||||||
"CREATE_THREAD_DEBUG_EVENT"));
|
"CREATE_THREAD_DEBUG_EVENT"));
|
||||||
/* Record the existence of this thread */
|
/* Record the existence of this thread */
|
||||||
child_add_thread (current_event.dwThreadId,
|
th = child_add_thread (current_event.dwThreadId,
|
||||||
current_event.u.CreateThread.hThread);
|
current_event.u.CreateThread.hThread);
|
||||||
if (info_verbose)
|
if (info_verbose)
|
||||||
printf_unfiltered ("[New %s]\n",
|
printf_unfiltered ("[New %s]\n",
|
||||||
target_pid_to_str (current_event.dwThreadId));
|
target_pid_to_str (current_event.dwThreadId));
|
||||||
|
@ -1196,6 +1401,7 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event.dwThreadId,
|
||||||
"EXIT_THREAD_DEBUG_EVENT"));
|
"EXIT_THREAD_DEBUG_EVENT"));
|
||||||
child_delete_thread (current_event.dwThreadId);
|
child_delete_thread (current_event.dwThreadId);
|
||||||
|
th = &dummy_thread_info;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
|
@ -1207,8 +1413,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
|
|
||||||
main_thread_id = inferior_pid = current_event.dwThreadId;
|
main_thread_id = inferior_pid = current_event.dwThreadId;
|
||||||
/* Add the main thread */
|
/* Add the main thread */
|
||||||
current_thread = child_add_thread (inferior_pid,
|
th = child_add_thread (inferior_pid,
|
||||||
current_event.u.CreateProcessInfo.hThread);
|
current_event.u.CreateProcessInfo.hThread);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
|
@ -1220,7 +1426,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
|
ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
|
||||||
close_handle (current_process_handle);
|
close_handle (current_process_handle);
|
||||||
*retval = current_event.dwProcessId;
|
*retval = current_event.dwProcessId;
|
||||||
goto out;
|
breakout = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case LOAD_DLL_DEBUG_EVENT:
|
case LOAD_DLL_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
|
DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
|
||||||
|
@ -1244,14 +1451,12 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event.dwThreadId,
|
||||||
"EXCEPTION_DEBUG_EVENT"));
|
"EXCEPTION_DEBUG_EVENT"));
|
||||||
if (handle_exception (ourstatus))
|
if (handle_exception (ourstatus))
|
||||||
|
*retval = current_event.dwThreadId;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char buf[32];
|
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
*retval = current_event.dwThreadId;
|
breakout = 0;
|
||||||
remote_read_bytes (read_pc (), buf, sizeof (buf));
|
|
||||||
dcache_xfer_memory (remote_dcache, read_pc (), buf, sizeof (buf), 0);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
|
case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
|
||||||
|
@ -1259,7 +1464,7 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event.dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event.dwThreadId,
|
||||||
"OUTPUT_DEBUG_STRING_EVENT"));
|
"OUTPUT_DEBUG_STRING_EVENT"));
|
||||||
handle_output_debug_string (ourstatus);
|
handle_output_debug_string ( ourstatus);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
|
printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
|
||||||
|
@ -1270,8 +1475,10 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus, DWORD * eve
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
breakout = 0;
|
if (breakout)
|
||||||
CHECK (child_continue (continue_status, -1));
|
this_thread = current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
|
||||||
|
else
|
||||||
|
CHECK (child_continue (continue_status, -1));
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return breakout;
|
return breakout;
|
||||||
|
@ -1291,7 +1498,7 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
|
||||||
isn't necessarily what you think it is. */
|
isn't necessarily what you think it is. */
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
if (get_child_debug_event (pid, ourstatus, &event_code, &retval))
|
if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval))
|
||||||
return retval;
|
return retval;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1351,14 +1558,15 @@ char *
|
||||||
upload_to_device (const char *to, const char *from)
|
upload_to_device (const char *to, const char *from)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
const char *dir = remote_directory ? : "\\gdb";
|
const char *dir = remote_directory ?: "\\gdb";
|
||||||
int len;
|
int len;
|
||||||
static char *remotefile = NULL;
|
static char *remotefile = NULL;
|
||||||
LPWSTR wstr;
|
LPWSTR wstr;
|
||||||
char *p;
|
char *p;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
const char *in_to = to;
|
const char *in_to = to;
|
||||||
FILETIME ctime, atime, wtime;
|
FILETIME crtime, actime, wrtime;
|
||||||
|
time_t utime;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -1397,15 +1605,25 @@ upload_to_device (const char *to, const char *from)
|
||||||
|
|
||||||
/* Some kind of problem? */
|
/* Some kind of problem? */
|
||||||
err = CeGetLastError ();
|
err = CeGetLastError ();
|
||||||
if (h == NULL)
|
if (h == NULL || h == INVALID_HANDLE_VALUE)
|
||||||
error ("error creating file to \"%s\". Windows error %d.",
|
error ("error opening file \"%s\". Windows error %d.",
|
||||||
remotefile, err);
|
remotefile, err);
|
||||||
|
|
||||||
|
CeGetFileTime (h, &crtime, &actime, &wrtime);
|
||||||
|
utime = to_time_t (&wrtime);
|
||||||
|
#if 0
|
||||||
|
if (utime < st.st_mtime)
|
||||||
|
{
|
||||||
|
char buf[80];
|
||||||
|
strcpy (buf, ctime(&utime));
|
||||||
|
printf ("%s < %s\n", buf, ctime(&st.st_mtime));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* See if we need to upload the file. */
|
/* See if we need to upload the file. */
|
||||||
if (upload_when == UPLOAD_ALWAYS ||
|
if (upload_when == UPLOAD_ALWAYS ||
|
||||||
err != ERROR_ALREADY_EXISTS ||
|
err != ERROR_ALREADY_EXISTS ||
|
||||||
!CeGetFileTime (h, &ctime, &atime, &wtime) ||
|
!CeGetFileTime (h, &crtime, &actime, &wrtime) ||
|
||||||
to_time_t (&wtime) < st.st_mtime)
|
to_time_t (&wrtime) < st.st_mtime)
|
||||||
{
|
{
|
||||||
DWORD nbytes;
|
DWORD nbytes;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
@ -1419,7 +1637,8 @@ upload_to_device (const char *to, const char *from)
|
||||||
}
|
}
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
CeCloseHandle (h);
|
if (!CeCloseHandle (h))
|
||||||
|
error ("error closing remote file - %d.", CeGetLastError ());
|
||||||
|
|
||||||
return remotefile;
|
return remotefile;
|
||||||
}
|
}
|
||||||
|
@ -1555,11 +1774,10 @@ child_create_inferior (char *exec_file, char *args, char **env)
|
||||||
target_terminal_init ();
|
target_terminal_init ();
|
||||||
target_terminal_inferior ();
|
target_terminal_inferior ();
|
||||||
|
|
||||||
|
|
||||||
/* Run until process and threads are loaded */
|
/* Run until process and threads are loaded */
|
||||||
do
|
while (!get_child_debug_event (inferior_pid, &dummy,
|
||||||
get_child_debug_event (inferior_pid, &dummy, &event_code, &ret);
|
CREATE_PROCESS_DEBUG_EVENT, &ret))
|
||||||
while (event_code != CREATE_PROCESS_DEBUG_EVENT);
|
continue;
|
||||||
|
|
||||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
|
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
|
||||||
}
|
}
|
||||||
|
@ -1607,213 +1825,6 @@ child_kill_inferior (void)
|
||||||
target_mourn_inferior (); /* or just child_mourn_inferior? */
|
target_mourn_inferior (); /* or just child_mourn_inferior? */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MIPS
|
|
||||||
static void
|
|
||||||
undoSStep (thread_info * th)
|
|
||||||
{
|
|
||||||
if (th->stepped)
|
|
||||||
{
|
|
||||||
memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
|
|
||||||
th->stepped = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
|
||||||
{
|
|
||||||
unsigned long pc;
|
|
||||||
thread_info *th = current_thread; /* Info on currently selected thread */
|
|
||||||
CORE_ADDR mips_next_pc (CORE_ADDR pc);
|
|
||||||
|
|
||||||
if (!insert_breakpoints_p)
|
|
||||||
{
|
|
||||||
undoSStep (th);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
th->stepped = 1;
|
|
||||||
pc = read_register (PC_REGNUM);
|
|
||||||
th->step_pc = mips_next_pc (pc);
|
|
||||||
th->step_prev = 0;
|
|
||||||
memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
|
|
||||||
}
|
|
||||||
#elif SHx
|
|
||||||
/* Hitachi SH architecture instruction encoding masks */
|
|
||||||
|
|
||||||
#define COND_BR_MASK 0xff00
|
|
||||||
#define UCOND_DBR_MASK 0xe000
|
|
||||||
#define UCOND_RBR_MASK 0xf0df
|
|
||||||
#define TRAPA_MASK 0xff00
|
|
||||||
|
|
||||||
#define COND_DISP 0x00ff
|
|
||||||
#define UCOND_DISP 0x0fff
|
|
||||||
#define UCOND_REG 0x0f00
|
|
||||||
|
|
||||||
/* Hitachi SH instruction opcodes */
|
|
||||||
|
|
||||||
#define BF_INSTR 0x8b00
|
|
||||||
#define BT_INSTR 0x8900
|
|
||||||
#define BRA_INSTR 0xa000
|
|
||||||
#define BSR_INSTR 0xb000
|
|
||||||
#define JMP_INSTR 0x402b
|
|
||||||
#define JSR_INSTR 0x400b
|
|
||||||
#define RTS_INSTR 0x000b
|
|
||||||
#define RTE_INSTR 0x002b
|
|
||||||
#define TRAPA_INSTR 0xc300
|
|
||||||
#define SSTEP_INSTR 0xc3ff
|
|
||||||
|
|
||||||
|
|
||||||
#define T_BIT_MASK 0x0001
|
|
||||||
|
|
||||||
/* Undo the effect of a previous doSStep. If we single stepped,
|
|
||||||
restore the old instruction. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
undoSStep (thread_info * th)
|
|
||||||
{
|
|
||||||
if (th->stepped)
|
|
||||||
{
|
|
||||||
gdb_wince_len done;
|
|
||||||
write_process_memory (current_process_handle, (LPVOID) th->step_pc,
|
|
||||||
(LPVOID) & th->step_instr, sizeof (short), &done);
|
|
||||||
if (done != sizeof (short))
|
|
||||||
error ("error unsetting single step.");
|
|
||||||
th->stepped = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Single step (in a painstaking fashion) by inspecting the current
|
|
||||||
instruction and setting a breakpoint on the "next" instruction
|
|
||||||
which would be executed. This code hails from sh-stub.c.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
|
||||||
{
|
|
||||||
thread_info *th = current_thread; /* Info on currently selected thread */
|
|
||||||
|
|
||||||
if (!insert_breakpoints_p)
|
|
||||||
undoSStep (th);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
short *instrMem;
|
|
||||||
int displacement;
|
|
||||||
int reg;
|
|
||||||
unsigned short opcode;
|
|
||||||
gdb_wince_len done;
|
|
||||||
LPCONTEXT c = &th->context;
|
|
||||||
|
|
||||||
instrMem = (short *) c->Fir;
|
|
||||||
|
|
||||||
read_process_memory (current_process_handle, (LPCVOID) c->Fir, &opcode,
|
|
||||||
sizeof (opcode), &done);
|
|
||||||
if (done != sizeof (opcode))
|
|
||||||
error ("couldn't retrieve opcode");
|
|
||||||
th->stepped = 1;
|
|
||||||
|
|
||||||
if ((opcode & COND_BR_MASK) == BT_INSTR)
|
|
||||||
{
|
|
||||||
if (c->Psr & T_BIT_MASK)
|
|
||||||
{
|
|
||||||
displacement = (opcode & COND_DISP) << 1;
|
|
||||||
if (displacement & 0x80)
|
|
||||||
displacement |= 0xffffff00;
|
|
||||||
/*
|
|
||||||
* Remember PC points to second instr.
|
|
||||||
* after PC of branch ... so add 4
|
|
||||||
*/
|
|
||||||
instrMem = (short *) (c->Fir + displacement + 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
instrMem += 1;
|
|
||||||
}
|
|
||||||
else if ((opcode & COND_BR_MASK) == BF_INSTR)
|
|
||||||
{
|
|
||||||
if (c->Psr & T_BIT_MASK)
|
|
||||||
instrMem += 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
displacement = (opcode & COND_DISP) << 1;
|
|
||||||
if (displacement & 0x80)
|
|
||||||
displacement |= 0xffffff00;
|
|
||||||
/*
|
|
||||||
* Remember PC points to second instr.
|
|
||||||
* after PC of branch ... so add 4
|
|
||||||
*/
|
|
||||||
instrMem = (short *) (c->Fir + displacement + 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
|
|
||||||
{
|
|
||||||
displacement = (opcode & UCOND_DISP) << 1;
|
|
||||||
if (displacement & 0x0800)
|
|
||||||
displacement |= 0xfffff000;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remember PC points to second instr.
|
|
||||||
* after PC of branch ... so add 4
|
|
||||||
*/
|
|
||||||
instrMem = (short *) (c->Fir + displacement + 4);
|
|
||||||
}
|
|
||||||
else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
|
|
||||||
{
|
|
||||||
reg = (char) ((opcode & UCOND_REG) >> 8);
|
|
||||||
|
|
||||||
instrMem = (short *) *regptr (c, reg);
|
|
||||||
}
|
|
||||||
else if (opcode == RTS_INSTR)
|
|
||||||
instrMem = (short *) c->PR;
|
|
||||||
else if (opcode == RTE_INSTR)
|
|
||||||
instrMem = (short *) *regptr (c, 15);
|
|
||||||
else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
|
|
||||||
instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
|
|
||||||
else
|
|
||||||
instrMem += 1;
|
|
||||||
|
|
||||||
th->step_pc = (CORE_ADDR) instrMem;
|
|
||||||
|
|
||||||
read_process_memory (current_process_handle, (LPVOID) instrMem,
|
|
||||||
(LPVOID) & th->step_instr, sizeof (short), &done);
|
|
||||||
opcode = SSTEP_INSTR;
|
|
||||||
write_process_memory (current_process_handle, (LPVOID) instrMem,
|
|
||||||
(LPVOID) & opcode, sizeof (short), &done);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined (ARM)
|
|
||||||
/* Single step (in a painstaking fashion) by inspecting the current
|
|
||||||
instruction and setting a breakpoint on the "next" instruction
|
|
||||||
which would be executed. This code hails from sh-stub.c.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
undoSStep (thread_info * th)
|
|
||||||
{
|
|
||||||
if (th->stepped)
|
|
||||||
{
|
|
||||||
memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
|
|
||||||
th->stepped = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
|
|
||||||
{
|
|
||||||
unsigned long pc;
|
|
||||||
thread_info *th = current_thread; /* Info on currently selected thread */
|
|
||||||
CORE_ADDR mips_next_pc (CORE_ADDR pc);
|
|
||||||
|
|
||||||
if (!insert_breakpoints_p)
|
|
||||||
{
|
|
||||||
undoSStep (th);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
th->stepped = 1;
|
|
||||||
pc = read_register (PC_REGNUM);
|
|
||||||
th->step_pc = arm_get_next_pc (pc);
|
|
||||||
th->step_prev = 0;
|
|
||||||
memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Resume the child after an exception. */
|
/* Resume the child after an exception. */
|
||||||
void
|
void
|
||||||
child_resume (int pid, int step, enum target_signal sig)
|
child_resume (int pid, int step, enum target_signal sig)
|
||||||
|
@ -1917,8 +1928,8 @@ init_child_ops (void)
|
||||||
/* Handle 'set remoteupload' parameter. */
|
/* Handle 'set remoteupload' parameter. */
|
||||||
|
|
||||||
#define replace_upload(what) \
|
#define replace_upload(what) \
|
||||||
upload_when = UPLOAD_NEWER; \
|
upload_when = what; \
|
||||||
remote_upload = realloc (remote_upload, strlen (upload_options[upload_when].name)); \
|
remote_upload = realloc (remote_upload, strlen (upload_options[upload_when].name) + 1); \
|
||||||
strcpy (remote_upload, upload_options[upload_when].name);
|
strcpy (remote_upload, upload_options[upload_when].name);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1940,8 +1951,7 @@ set_upload_type (char *ignore, int from_tty)
|
||||||
if (len >= upload_options[i].abbrev &&
|
if (len >= upload_options[i].abbrev &&
|
||||||
strncasecmp (remote_upload, upload_options[i].name, len) == 0)
|
strncasecmp (remote_upload, upload_options[i].name, len) == 0)
|
||||||
{
|
{
|
||||||
remote_upload = (char *) upload_options[i].name;
|
replace_upload (i);
|
||||||
upload_when = i;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue