#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "symtab.h"
#include "inferior.h"
#include "breakpoint.h"
#include "symfile.h"
#include "target.h"
#include "objfiles.h"
#include "gdbcore.h"
#include "value.h"
#include "command.h"
#include "regcache.h"
#include <tcl.h>
#include <windows.h>
#include <winuser.h>
extern unsigned long int strtoul (const char *nptr, char **endptr,
int base);
struct MessageIO
{
int size;
char *buf;
};
extern void break_command (char *, int);
extern int (*ui_loop_hook) (int);
static int init_hidden_window (void);
static LRESULT CALLBACK v850ice_wndproc (HWND, UINT, WPARAM, LPARAM);
static void v850ice_files_info (struct target_ops *ignore);
static int v850ice_xfer_memory (CORE_ADDR memaddr, char *myaddr,
int len, int should_write,
struct target_ops *target);
static void v850ice_prepare_to_store (void);
static void v850ice_fetch_registers (int regno);
static void v850ice_resume (ptid_t ptid, int step,
enum target_signal siggnal);
static void v850ice_open (char *name, int from_tty);
static void v850ice_close (int quitting);
static void v850ice_stop (void);
static void v850ice_store_registers (int regno);
static void v850ice_mourn (void);
static ptid_t v850ice_wait (ptid_t ptid,
struct target_waitstatus *status);
static void v850ice_kill (void);
static void v850ice_detach (char *args, int from_tty);
static int v850ice_insert_breakpoint (CORE_ADDR, char *);
static int v850ice_remove_breakpoint (CORE_ADDR, char *);
static void v850ice_command (char *, int);
static int ice_disassemble (unsigned long, int, char *);
static int ice_lookup_addr (unsigned long *, char *, char *);
static int ice_lookup_symbol (unsigned long, char *);
static void ice_SimulateDisassemble (char *, int);
static void ice_SimulateAddrLookup (char *, int);
static void ice_Simulate_SymLookup (char *, int);
static void ice_fputs (const char *, struct ui_file *);
static int ice_file (char *);
static int ice_cont (char *);
static int ice_stepi (char *);
static int ice_nexti (char *);
static void togdb_force_update (void);
static void view_source (CORE_ADDR);
static void do_gdb (char *, char *, void (*func) (char *, int), int);
static HWND hidden_hwnd;
long (__stdcall * ExeAppReq) (char *, long, char *, struct MessageIO *);
long (__stdcall * RegisterClient) (HWND);
long (__stdcall * UnregisterClient) (void);
extern Tcl_Interp *gdbtk_interp;
static int ice_open = 0;
static char *v850_CB_Result;
static int SimulateCallback;
#define MAX_BLOCK_SIZE 64*1024
#define GSINGLESTEP 0x200
#define GRESUME 0x201
#define GREADREG 0x202
#define GWRITEREG 0x203
#define GWRITEBLOCK 0x204
#define GREADBLOCK 0x205
#define GSETBREAK 0x206
#define GREMOVEBREAK 0x207
#define GHALT 0x208
#define GCHECKSTATUS 0x209
#define GMDIREPLY 0x210
#define GDOWNLOAD 0x211
#define GCOMMAND 0x212
#define GLOADFILENAME 0x213
#define GWRITEMEM 0x214
#define ICE_Idle 0x00
#define ICE_Breakpoint 0x01
#define ICE_Stepped 0x02
#define ICE_Exception 0x03
#define ICE_Halted 0x04
#define ICE_Exited 0x05
#define ICE_Terminated 0x06
#define ICE_Running 0x07
#define ICE_Unknown 0x99
#define WM_STATE_CHANGE WM_USER+101
#define WM_SYM_TO_ADDR WM_USER+102
#define WM_ADDR_TO_SYM WM_USER+103
#define WM_DISASSEMBLY WM_USER+104
#define WM_SOURCE WM_USER+105
#define STATE_CHANGE_REGS 1
#define STATE_CHANGE_LOAD 2
#define STATE_CHANGE_RESET 3
#define STATE_CHANGE_CONT 4
#define STATE_CHANGE_STOP 5
#define STATE_CHANGE_STEPI 6
#define STATE_CHANGE_NEXTI 7
static struct target_ops v850ice_ops;
static int
init_hidden_window (void)
{
WNDCLASS class;
if (hidden_hwnd != NULL)
return 1;
class.style = 0;
class.cbClsExtra = 0;
class.cbWndExtra = 0;
class.hInstance = GetModuleHandle (0);
class.hbrBackground = NULL;
class.lpszMenuName = NULL;
class.lpszClassName = "gdb_v850ice";
class.lpfnWndProc = v850ice_wndproc;
class.hIcon = NULL;
class.hCursor = NULL;
if (!RegisterClass (&class))
return 0;
hidden_hwnd = CreateWindow ("gdb_v850ice", "gdb_v850ice", WS_TILED,
0, 0, 0, 0, NULL, NULL, class.hInstance,
NULL);
if (hidden_hwnd == NULL)
{
char buf[200];
DWORD err;
err = GetLastError ();
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
0, buf, 200, NULL);
printf_unfiltered ("Could not create window: %s", buf);
return 0;
}
return 1;
}
static LRESULT CALLBACK
v850ice_wndproc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = FALSE;
switch (message)
{
case WM_SYM_TO_ADDR:
MessageBox (0, "Symbol resolution\nNot implemented", "GDB", MB_OK);
break;
case WM_ADDR_TO_SYM:
MessageBox (0, "Address resolution\nNot implemented", "GDB", MB_OK);
break;
case WM_SOURCE:
view_source ((CORE_ADDR) lParam);
break;
case WM_STATE_CHANGE:
switch (wParam)
{
case STATE_CHANGE_LOAD:
{
struct MessageIO iob;
char buf[128];
iob.buf = buf;
iob.size = 128;
ExeAppReq ("GDB", GLOADFILENAME, NULL, &iob);
if (!catch_errors ((catch_errors_ftype *) ice_file, iob.buf, "", RETURN_MASK_ALL))
printf_unfiltered ("load errored\n");
}
break;
case STATE_CHANGE_RESET:
registers_changed ();
flush_cached_frames ();
togdb_force_update ();
result = TRUE;
break;
case STATE_CHANGE_REGS:
registers_changed ();
togdb_force_update ();
result = TRUE;
break;
case STATE_CHANGE_CONT:
if (!catch_errors ((catch_errors_ftype *) ice_cont, NULL, "", RETURN_MASK_ALL))
printf_unfiltered ("continue errored\n");
result = TRUE;
break;
case STATE_CHANGE_STEPI:
if (!catch_errors ((catch_errors_ftype *) ice_stepi, (int) lParam, "",
RETURN_MASK_ALL))
printf_unfiltered ("stepi errored\n");
result = TRUE;
break;
case STATE_CHANGE_NEXTI:
if (!catch_errors ((catch_errors_ftype *) ice_nexti, (int) lParam, "",
RETURN_MASK_ALL))
printf_unfiltered ("nexti errored\n");
result = TRUE;
break;
}
}
if (result == FALSE)
return DefWindowProc (hwnd, message, wParam, lParam);
return FALSE;
}
static void
v850ice_open (char *name, int from_tty)
{
HINSTANCE handle;
if (name)
error ("Too many arguments.");
target_preopen (from_tty);
unpush_target (&v850ice_ops);
if (from_tty)
puts_filtered ("V850ice debugging\n");
push_target (&v850ice_ops);
target_terminal_init ();
if (ExeAppReq == NULL)
{
handle = LoadLibrary ("necmsg.dll");
if (handle == NULL)
error ("Cannot load necmsg.dll");
ExeAppReq = (long (*) (char *, long, char *, struct MessageIO *))
GetProcAddress (handle, "ExeAppReq");
RegisterClient = (long (*) (HWND))
GetProcAddress (handle, "RegisterClient");
UnregisterClient = (long (*) (void))
GetProcAddress (handle, "UnregisterClient");
if (ExeAppReq == NULL || RegisterClient == NULL || UnregisterClient == NULL)
error ("Could not find requisite functions in necmsg.dll.");
if (!init_hidden_window ())
error ("could not initialize message handling");
}
RegisterClient (hidden_hwnd);
ice_open = 1;
inferior_ptid = pid_to_ptid (42000);
start_remote ();
return;
}
static void
v850ice_close (int quitting)
{
if (ice_open)
{
UnregisterClient ();
ice_open = 0;
inferior_ptid = null_ptid;
}
}
static void
v850ice_stop (void)
{
v850ice_command ("stop", 0);
}
static void
v850ice_detach (char *args, int from_tty)
{
if (args)
error ("Argument given to \"detach\" when remotely debugging.");
pop_target ();
if (from_tty)
puts_filtered ("Ending v850ice debugging.\n");
}
static void
v850ice_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
long retval;
char buf[256];
struct MessageIO iob;
iob.size = 0;
iob.buf = buf;
if (step)
retval = ExeAppReq ("GDB", GSINGLESTEP, "step", &iob);
else
retval = ExeAppReq ("GDB", GRESUME, "run", &iob);
if (retval)
error ("ExeAppReq (step = %d) returned %d", step, retval);
}
static ptid_t
v850ice_wait (ptid_t ptid, struct target_waitstatus *status)
{
long v850_status;
char buf[256];
struct MessageIO iob;
int done = 0;
int count = 0;
iob.size = 0;
iob.buf = buf;
do
{
if (count++ % 100000)
{
ui_loop_hook (0);
count = 0;
}
v850_status = ExeAppReq ("GDB", GCHECKSTATUS, NULL, &iob);
switch (v850_status)
{
case ICE_Idle:
case ICE_Breakpoint:
case ICE_Stepped:
case ICE_Halted:
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
done = 1;
break;
case ICE_Exception:
status->kind = TARGET_WAITKIND_SIGNALLED;
status->value.sig = TARGET_SIGNAL_SEGV;
done = 1;
break;
case ICE_Exited:
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
done = 1;
break;
case ICE_Terminated:
status->kind = TARGET_WAITKIND_SIGNALLED;
status->value.sig = TARGET_SIGNAL_KILL;
done = 1;
break;
default:
break;
}
}
while (!done);
return inferior_ptid;
}
static int
convert_register (int regno, char *buf)
{
if (regno <= 31)
sprintf (buf, "r%d", regno);
else if (REGISTER_NAME (regno)[0] == 's'
&& REGISTER_NAME (regno)[1] == 'r')
return 0;
else
sprintf (buf, "%s", REGISTER_NAME (regno));
return 1;
}
static void
v850ice_fetch_registers (int regno)
{
long retval;
char cmd[100];
char val[100];
struct MessageIO iob;
unsigned long regval;
char *p;
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
v850ice_fetch_registers (regno);
return;
}
strcpy (cmd, "reg ");
if (!convert_register (regno, &cmd[4]))
return;
iob.size = sizeof val;
iob.buf = val;
retval = ExeAppReq ("GDB", GREADREG, cmd, &iob);
if (retval)
error ("1: ExeAppReq returned %d: cmd = %s", retval, cmd);
regval = strtoul (val, NULL, 16);
if (regval == 0 && p == val)
error ("v850ice_fetch_registers (%d): bad value from ICE: %s.",
regno, val);
store_unsigned_integer (val, REGISTER_RAW_SIZE (regno), regval);
supply_register (regno, val);
}
static void
v850ice_store_registers (int regno)
{
long retval;
char cmd[100];
unsigned long regval;
char buf[256];
struct MessageIO iob;
iob.size = 0;
iob.buf = buf;
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
v850ice_store_registers (regno);
return;
}
regval = extract_unsigned_integer (&deprecated_registers[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno));
strcpy (cmd, "reg ");
if (!convert_register (regno, &cmd[4]))
return;
sprintf (cmd + strlen (cmd), "=0x%x", regval);
retval = ExeAppReq ("GDB", GWRITEREG, cmd, &iob);
if (retval)
error ("2: ExeAppReq returned %d: cmd = %s", retval, cmd);
}
static void
v850ice_prepare_to_store (void)
{
}
static int
v850ice_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
int should_write, struct target_ops *target)
{
long retval;
char cmd[100];
struct MessageIO iob;
int sent;
if (should_write)
{
if (len == 4 || len == 2 || len == 1)
{
long value = 0;
char buf[256];
char c;
iob.size = 0;
iob.buf = buf;
sent = 0;
switch (len)
{
case 4:
c = 'w';
value |= (long) ((myaddr[3] << 24) & 0xff000000);
value |= (long) ((myaddr[2] << 16) & 0x00ff0000);
value |= (long) ((myaddr[1] << 8) & 0x0000ff00);
value |= (long) (myaddr[0] & 0x000000ff);
break;
case 2:
c = 'h';
value |= (long) ((myaddr[1] << 8) & 0xff00);
value |= (long) (myaddr[0] & 0x00ff);
break;
case 1:
c = 'b';
value |= (long) (myaddr[0] & 0xff);
break;
}
sprintf (cmd, "memory %c c 0x%x=0x%x", c, (int) memaddr, value);
retval = ExeAppReq ("GDB", GWRITEMEM, cmd, &iob);
if (retval == 0)
sent = len;
}
else
{
sent = 0;
do
{
iob.size = len > MAX_BLOCK_SIZE ? MAX_BLOCK_SIZE : len;
iob.buf = myaddr;
sprintf (cmd, "memory b c 0x%x=0x00 l=%d", (int) memaddr, iob.size);
retval = ExeAppReq ("GDB", GWRITEBLOCK, cmd, &iob);
if (retval != 0)
break;
len -= iob.size;
memaddr += iob.size;
myaddr += iob.size;
sent += iob.size;
}
while (len > 0);
}
}
else
{
unsigned char *tmp;
unsigned char *t;
int i;
tmp = alloca (len + 100);
t = tmp;
memset (tmp + len, 0xff, 100);
sent = 0;
do
{
iob.size = len > MAX_BLOCK_SIZE ? MAX_BLOCK_SIZE : len;
iob.buf = tmp;
sprintf (cmd, "memory b 0x%x l=%d", (int) memaddr, iob.size);
retval = ExeAppReq ("GDB", GREADBLOCK, cmd, &iob);
if (retval != 0)
break;
len -= iob.size;
memaddr += iob.size;
sent += iob.size;
tmp += iob.size;
}
while (len > 0);
if (retval == 0)
{
for (i = 0; i < 100; i++)
{
if (t[sent + i] != 0xff)
{
warning ("GREADBLOCK trashed bytes after transfer area.");
break;
}
}
memcpy (myaddr, t, sent);
}
}
if (retval != 0)
error ("3: ExeAppReq returned %d: cmd = %s", retval, cmd);
return sent;
}
static void
v850ice_files_info (struct target_ops *ignore)
{
puts_filtered ("Debugging a target via the NEC V850 ICE.\n");
}
static int
v850ice_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
{
long retval;
char cmd[100];
char buf[256];
struct MessageIO iob;
iob.size = 0;
iob.buf = buf;
sprintf (cmd, "%d, ", addr);
retval = ExeAppReq ("GDB", GSETBREAK, cmd, &iob);
if (retval)
error ("ExeAppReq (GSETBREAK) returned %d: cmd = %s", retval, cmd);
return 0;
}
static int
v850ice_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
{
long retval;
char cmd[100];
char buf[256];
struct MessageIO iob;
iob.size = 0;
iob.buf = buf;
sprintf (cmd, "%d, ", addr);
retval = ExeAppReq ("GDB", GREMOVEBREAK, cmd, &iob);
if (retval)
error ("ExeAppReq (GREMOVEBREAK) returned %d: cmd = %s", retval, cmd);
return 0;
}
static void
v850ice_kill (void)
{
target_mourn_inferior ();
inferior_ptid = null_ptid;
}
static void
v850ice_mourn (void)
{
}
static void
v850ice_load (char *filename, int from_tty)
{
struct MessageIO iob;
char buf[256];
iob.size = 0;
iob.buf = buf;
generic_load (filename, from_tty);
ExeAppReq ("GDB", GDOWNLOAD, filename, &iob);
}
static int
ice_file (char *arg)
{
char *s;
target_detach (NULL, 0);
pop_target ();
printf_unfiltered ("\n");
s = arg;
while (*s != '\0')
{
if (*s == '\\')
*s = '/';
s++;
}
delete_command (NULL, 0);
printf_unfiltered ("Reading symbols from %s...", arg);
exec_open (arg, 0);
symbol_file_add_main (arg, 0);
printf_unfiltered ("done\n");
v850ice_open (NULL, 0);
togdb_force_update ();
return 1;
}
static int
ice_cont (char *c)
{
printf_filtered ("continue (ice)\n");
ReplyMessage ((LRESULT) 1);
if (gdbtk_interp == NULL)
{
continue_command (NULL, 1);
}
else
Tcl_Eval (gdbtk_interp, "gdb_immediate continue");
return 1;
}
static void
do_gdb (char *cmd, char *str, void (*func) (char *, int), int count)
{
ReplyMessage ((LRESULT) 1);
while (count--)
{
printf_unfiltered (str);
if (gdbtk_interp == NULL)
{
func (NULL, 0);
}
else
Tcl_Eval (gdbtk_interp, cmd);
}
}
static int
ice_stepi (char *c)
{
int count = (int) c;
do_gdb ("gdb_immediate stepi", "stepi (ice)\n", stepi_command, count);
return 1;
}
static int
ice_nexti (char *c)
{
int count = (int) c;
do_gdb ("gdb_immediate nexti", "nexti (ice)\n", nexti_command, count);
return 1;
}
static void
v850ice_command (char *arg, int from_tty)
{
struct MessageIO iob;
char buf[256];
iob.buf = buf;
iob.size = 0;
ExeAppReq ("GDB", GCOMMAND, arg, &iob);
}
static void
togdb_force_update (void)
{
if (gdbtk_interp != NULL)
Tcl_Eval (gdbtk_interp, "gdbtk_update");
}
static void
view_source (CORE_ADDR addr)
{
char c[256];
if (gdbtk_interp != NULL)
{
sprintf (c, "catch {set src [lindex [ManagedWin::find SrcWin] 0]\n$src location BROWSE [gdb_loc *0x%x]}", addr);
Tcl_Eval (gdbtk_interp, c);
}
}
static void
init_850ice_ops (void)
{
v850ice_ops.to_shortname = "ice";
v850ice_ops.to_longname = "NEC V850 ICE interface";
v850ice_ops.to_doc = "Debug a system controlled by a NEC 850 ICE.";
v850ice_ops.to_open = v850ice_open;
v850ice_ops.to_close = v850ice_close;
v850ice_ops.to_detach = v850ice_detach;
v850ice_ops.to_resume = v850ice_resume;
v850ice_ops.to_wait = v850ice_wait;
v850ice_ops.to_fetch_registers = v850ice_fetch_registers;
v850ice_ops.to_store_registers = v850ice_store_registers;
v850ice_ops.to_prepare_to_store = v850ice_prepare_to_store;
v850ice_ops.to_xfer_memory = v850ice_xfer_memory;
v850ice_ops.to_files_info = v850ice_files_info;
v850ice_ops.to_insert_breakpoint = v850ice_insert_breakpoint;
v850ice_ops.to_remove_breakpoint = v850ice_remove_breakpoint;
v850ice_ops.to_kill = v850ice_kill;
v850ice_ops.to_load = v850ice_load;
v850ice_ops.to_mourn_inferior = v850ice_mourn;
v850ice_ops.to_stop = v850ice_stop;
v850ice_ops.to_stratum = process_stratum;
v850ice_ops.to_has_all_memory = 1;
v850ice_ops.to_has_memory = 1;
v850ice_ops.to_has_stack = 1;
v850ice_ops.to_has_registers = 1;
v850ice_ops.to_has_execution = 1;
v850ice_ops.to_magic = OPS_MAGIC;
}
void
_initialize_v850ice (void)
{
init_850ice_ops ();
add_target (&v850ice_ops);
add_com ("ice", class_obscure, v850ice_command,
"Send command to ICE");
}