#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include <ctype.h>
#include <sys/types.h>
#include "gdb_string.h"
#include "command.h"
#include "serial.h"
#include "monitor.h"
#include "remote-utils.h"
#include "inferior.h"
#include "version.h"
#include "regcache.h"
extern int baud_rate;
#define ARRAY_PROMPT ">> "
static void debuglogs (int, char *, ...);
static void array_open ();
static void array_close ();
static void array_detach ();
static void array_attach ();
static void array_resume (ptid_t ptid, int step, enum target_signal sig);
static void array_fetch_register ();
static void array_store_register ();
static void array_fetch_registers ();
static void array_store_registers ();
static void array_prepare_to_store ();
static void array_files_info ();
static void array_kill ();
static void array_create_inferior ();
static void array_mourn_inferior ();
static void make_gdb_packet ();
static int array_xfer_memory ();
static ptid_t array_wait (ptid_t ptid,
struct target_waitstatus *status);
static int array_insert_breakpoint ();
static int array_remove_breakpoint ();
static int tohex ();
static int to_hex ();
static int from_hex ();
static int array_send_packet ();
static int array_get_packet ();
static unsigned long ascii2hexword ();
static void hexword2ascii ();
#define LOG_FILE "monitor.log"
#if defined (LOG_FILE)
FILE *log_file;
#endif
static int timeout = 30;
#define PBUFSIZ 400
struct serial *array_desc = NULL;
extern char *tmp_mips_processor_type;
extern int mips_set_processor_type ();
static struct target_ops array_ops;
static void
init_array_ops (void)
{
array_ops.to_shortname = "array";
array_ops.to_longname =
"Debug using the standard GDB remote protocol for the Array Tech target.",
array_ops.to_doc =
"Debug using the standard GDB remote protocol for the Array Tech target.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
array_ops.to_open = array_open;
array_ops.to_close = array_close;
array_ops.to_attach = NULL;
array_ops.to_post_attach = NULL;
array_ops.to_require_attach = NULL;
array_ops.to_detach = array_detach;
array_ops.to_require_detach = NULL;
array_ops.to_resume = array_resume;
array_ops.to_wait = array_wait;
array_ops.to_post_wait = NULL;
array_ops.to_fetch_registers = array_fetch_registers;
array_ops.to_store_registers = array_store_registers;
array_ops.to_prepare_to_store = array_prepare_to_store;
array_ops.to_xfer_memory = array_xfer_memory;
array_ops.to_files_info = array_files_info;
array_ops.to_insert_breakpoint = array_insert_breakpoint;
array_ops.to_remove_breakpoint = array_remove_breakpoint;
array_ops.to_terminal_init = 0;
array_ops.to_terminal_inferior = 0;
array_ops.to_terminal_ours_for_output = 0;
array_ops.to_terminal_ours = 0;
array_ops.to_terminal_info = 0;
array_ops.to_kill = array_kill;
array_ops.to_load = 0;
array_ops.to_lookup_symbol = 0;
array_ops.to_create_inferior = array_create_inferior;
array_ops.to_post_startup_inferior = NULL;
array_ops.to_acknowledge_created_inferior = NULL;
array_ops.to_clone_and_follow_inferior = NULL;
array_ops.to_post_follow_inferior_by_clone = NULL;
array_ops.to_insert_fork_catchpoint = NULL;
array_ops.to_remove_fork_catchpoint = NULL;
array_ops.to_insert_vfork_catchpoint = NULL;
array_ops.to_remove_vfork_catchpoint = NULL;
array_ops.to_has_forked = NULL;
array_ops.to_has_vforked = NULL;
array_ops.to_can_follow_vfork_prior_to_exec = NULL;
array_ops.to_post_follow_vfork = NULL;
array_ops.to_insert_exec_catchpoint = NULL;
array_ops.to_remove_exec_catchpoint = NULL;
array_ops.to_has_execd = NULL;
array_ops.to_reported_exec_events_per_exec_call = NULL;
array_ops.to_has_exited = NULL;
array_ops.to_mourn_inferior = array_mourn_inferior;
array_ops.to_can_run = 0;
array_ops.to_notice_signals = 0;
array_ops.to_thread_alive = 0;
array_ops.to_stop = 0;
array_ops.to_pid_to_exec_file = NULL;
array_ops.to_stratum = process_stratum;
array_ops.DONT_USE = 0;
array_ops.to_has_all_memory = 1;
array_ops.to_has_memory = 1;
array_ops.to_has_stack = 1;
array_ops.to_has_registers = 1;
array_ops.to_has_execution = 1;
array_ops.to_sections = 0;
array_ops.to_sections_end = 0;
array_ops.to_magic = OPS_MAGIC;
};
static void
printf_monitor (char *pattern,...)
{
va_list args;
char buf[PBUFSIZ];
int i;
va_start (args, pattern);
vsprintf (buf, pattern, args);
debuglogs (1, "printf_monitor(), Sending: \"%s\".", buf);
if (strlen (buf) > PBUFSIZ)
error ("printf_monitor(): string too long");
if (serial_write (array_desc, buf, strlen (buf)))
fprintf (stderr, "serial_write failed: %s\n", safe_strerror (errno));
}
static void
write_monitor (char data[], int len)
{
if (serial_write (array_desc, data, len))
fprintf (stderr, "serial_write failed: %s\n", safe_strerror (errno));
*(data + len + 1) = '\0';
debuglogs (1, "write_monitor(), Sending: \"%s\".", data);
}
static void
debuglogs (int level, char *pattern,...)
{
va_list args;
char *p;
unsigned char buf[PBUFSIZ];
char newbuf[PBUFSIZ];
int i;
va_start (args, pattern);
if ((level < 0) || (level > 100))
{
error ("Bad argument passed to debuglogs(), needs debug level");
return;
}
vsprintf (buf, pattern, args);
p = newbuf;
for (i = 0; buf[i] != '\0'; i++)
{
if (i > PBUFSIZ)
error ("Debug message too long");
switch (buf[i])
{
case '\n':
*p++ = '\\';
*p++ = 'n';
continue;
case '\r':
*p++ = '\\';
*p++ = 'r';
continue;
case '\033':
*p++ = '\\';
*p++ = 'e';
continue;
case '\t':
*p++ = '\\';
*p++ = 't';
continue;
case '\b':
*p++ = '\\';
*p++ = 'b';
continue;
default:
*p++ = buf[i];
}
if (buf[i] < 26)
{
*p++ = '^';
*p++ = buf[i] + 'A';
continue;
}
if (buf[i] >= 128)
{
*p++ = '!';
*p++ = buf[i] + 'A';
continue;
}
}
*p = '\0';
if (sr_get_debug () > level)
printf_unfiltered ("%s\n", newbuf);
#ifdef LOG_FILE
if (log_file != 0x0)
{
fputs (newbuf, log_file);
fputc ('\n', log_file);
fflush (log_file);
}
#endif
}
static int
readchar (int timeout)
{
int c;
c = serial_readchar (array_desc, abs (timeout));
if (sr_get_debug () > 5)
{
putchar (c & 0x7f);
debuglogs (5, "readchar: timeout = %d\n", timeout);
}
#ifdef LOG_FILE
if (isascii (c))
putc (c & 0x7f, log_file);
#endif
if (c >= 0)
return c & 0x7f;
if (c == SERIAL_TIMEOUT)
{
if (timeout <= 0)
return c;
error ("Timeout reading from remote system.");
#ifdef LOG_FILE
fputs ("ERROR: Timeout reading from remote system", log_file);
#endif
}
perror_with_name ("readchar");
}
static void
expect (char *string, int discard)
{
char *p = string;
int c;
debuglogs (1, "Expecting \"%s\".", string);
immediate_quit++;
while (1)
{
c = readchar (timeout);
if (!isascii (c))
continue;
if (c == *p++)
{
if (*p == '\0')
{
immediate_quit--;
debuglogs (4, "Matched");
return;
}
}
else
{
if (!discard)
{
fputc_unfiltered (c, gdb_stdout);
}
p = string;
}
}
}
static void
expect_prompt (int discard)
{
expect (ARRAY_PROMPT, discard);
}
static int
junk (char ch)
{
switch (ch)
{
case '\0':
case ' ':
case '-':
case '\t':
case '\r':
case '\n':
if (sr_get_debug () > 5)
debuglogs (5, "Ignoring \'%c\'.", ch);
return 1;
default:
if (sr_get_debug () > 5)
debuglogs (5, "Accepting \'%c\'.", ch);
return 0;
}
}
static int
get_hex_digit (int ignore)
{
static int ch;
while (1)
{
ch = readchar (timeout);
if (junk (ch))
continue;
if (sr_get_debug () > 4)
{
debuglogs (4, "get_hex_digit() got a 0x%x(%c)", ch, ch);
}
else
{
#ifdef LOG_FILE
if (log_file != 0x0)
{
fputs ("get_hex_digit() got a 0x", log_file);
fputc (ch, log_file);
fputc ('\n', log_file);
fflush (log_file);
}
#endif
}
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch == ' ' && ignore)
;
else
{
expect_prompt (1);
debuglogs (4, "Invalid hex digit from remote system. (0x%x)", ch);
error ("Invalid hex digit from remote system. (0x%x)", ch);
}
}
}
static void
get_hex_byte (char *byt)
{
int val;
val = get_hex_digit (1) << 4;
debuglogs (4, "get_hex_byte() -- Read first nibble 0x%x", val);
val |= get_hex_digit (0);
debuglogs (4, "get_hex_byte() -- Read second nibble 0x%x", val);
*byt = val;
debuglogs (4, "get_hex_byte() -- Read a 0x%x", val);
}
static int
get_hex_word (void)
{
long val, newval;
int i;
val = 0;
for (i = 0; i < 8; i++)
val = (val << 4) + get_hex_digit (i == 0);
debuglogs (4, "get_hex_word() got a 0x%x.", val);
return val;
}
static void
array_create_inferior (char *execfile, char *args, char **env)
{
int entry_pt;
if (args && *args)
error ("Can't pass arguments to remote MONITOR process");
if (execfile == 0 || exec_bfd == 0)
error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
clear_proceed_status ();
init_wait_for_inferior ();
target_terminal_init ();
target_terminal_inferior ();
proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
static int baudrate = 9600;
static char dev_name[100];
static void
array_open (char *args, char *name, int from_tty)
{
char packet[PBUFSIZ];
if (args == NULL)
error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
array_close (0);
target_preopen (from_tty);
unpush_target (&array_ops);
tmp_mips_processor_type = "lsi33k";
mips_set_processor_type_command ("lsi33k", 0);
strcpy (dev_name, args);
array_desc = serial_open (dev_name);
if (array_desc == NULL)
perror_with_name (dev_name);
if (baud_rate != -1)
{
if (serial_setbaudrate (array_desc, baud_rate))
{
serial_close (array_desc);
perror_with_name (name);
}
}
serial_raw (array_desc);
#if defined (LOG_FILE)
log_file = fopen (LOG_FILE, "w");
if (log_file == NULL)
perror_with_name (LOG_FILE);
fprintf (log_file, "GDB %s (%s", version, host_name);
fprintf (log_file, " --target %s)\n", array_ops.to_shortname);
fprintf (log_file, "Remote target %s connected to %s\n\n", array_ops.to_shortname, dev_name);
#endif
debuglogs (3, "Trying to ACK the target's debug stub");
printf_monitor ("@");
expect_prompt (1);
#ifdef TEST_ARRAY
make_gdb_packet (packet, "?");
if (array_send_packet (packet) == 0)
error ("Couldn't transmit packet\n");
printf_monitor ("@\n");
expect_prompt (1);
#endif
push_target (&array_ops);
if (from_tty)
printf ("Remote target %s connected to %s\n", array_ops.to_shortname, dev_name);
}
static void
array_close (int quitting)
{
serial_close (array_desc);
array_desc = NULL;
debuglogs (1, "array_close (quitting=%d)", quitting);
#if defined (LOG_FILE)
if (log_file)
{
if (ferror (log_file))
printf_filtered ("Error writing log file.\n");
if (fclose (log_file) != 0)
printf_filtered ("Error closing log file.\n");
}
#endif
}
static void
array_detach (int from_tty)
{
debuglogs (1, "array_detach ()");
pop_target ();
if (from_tty)
printf ("Ending remote %s debugging\n", target_shortname);
}
static void
array_attach (char *args, int from_tty)
{
if (from_tty)
printf ("Starting remote %s debugging\n", target_shortname);
debuglogs (1, "array_attach (args=%s)", args);
printf_monitor ("go %x\n");
expect ("go %x\n", 1);
}
static void
array_resume (ptid_t ptid, int step, enum target_signal sig)
{
debuglogs (1, "array_resume (step=%d, sig=%d)", step, sig);
if (step)
{
printf_monitor ("s\n");
}
else
{
printf_monitor ("go\n");
}
}
#define TMPBUFSIZ 5
static ptid_t
array_wait (ptid_t ptid, struct target_waitstatus *status)
{
int old_timeout = timeout;
int result, i;
char c;
struct serial *tty_desc;
serial_ttystate ttystate;
debuglogs (1, "array_wait (), printing extraneous text.");
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
timeout = 0;
#if !defined(__GO32__) && !defined(__MSDOS__) && !defined(_WIN32)
tty_desc = serial_fdopen (0);
ttystate = serial_get_tty_state (tty_desc);
serial_raw (tty_desc);
i = 0;
while (1)
{
c = readchar (timeout);
if (c > 0)
{
if (c == *(ARRAY_PROMPT + i))
{
if (++i >= strlen (ARRAY_PROMPT))
{
debuglogs (4, "array_wait(), got the expect_prompt.");
break;
}
}
else
{
i = 0;
}
fputc_unfiltered (c, gdb_stdout);
gdb_flush (gdb_stdout);
}
c = serial_readchar (tty_desc, timeout);
if (c > 0)
{
serial_write (array_desc, &c, 1);
if (c == 3)
break;
#if 0
fputc_unfiltered (c, gdb_stdout);
gdb_flush (gdb_stdout);
#endif
}
}
serial_set_tty_state (tty_desc, ttystate);
#else
expect_prompt (1);
debuglogs (4, "array_wait(), got the expect_prompt.");
#endif
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
timeout = old_timeout;
return inferior_ptid;
}
static void
array_fetch_registers (int ignored)
{
char *reg = alloca (MAX_REGISTER_RAW_SIZE);
int regno;
char *p;
char *packet = alloca (PBUFSIZ);
debuglogs (1, "array_fetch_registers (ignored=%d)\n", ignored);
memset (packet, 0, PBUFSIZ);
make_gdb_packet (packet, "g");
if (array_send_packet (packet) == 0)
error ("Couldn't transmit packet\n");
if (array_get_packet (packet) == 0)
error ("Couldn't receive packet\n");
debuglogs (4, "array_fetch_registers: Got a \"%s\" back\n", packet);
for (regno = 0; regno <= PC_REGNUM + 4; regno++)
{
LONGEST i = ascii2hexword (packet + (regno * 8));
debuglogs (5, "Adding register %d = %x\n", regno, i);
store_unsigned_integer (®, REGISTER_RAW_SIZE (regno), i);
supply_register (regno, (char *) ®);
}
}
static void
array_fetch_register (int ignored)
{
array_fetch_registers (0 );
}
static void
array_store_registers (int ignored)
{
int regno;
unsigned long i;
char packet[PBUFSIZ];
char buf[PBUFSIZ];
char num[9];
debuglogs (1, "array_store_registers()");
memset (packet, 0, PBUFSIZ);
memset (buf, 0, PBUFSIZ);
buf[0] = 'G';
for (regno = 0; regno < 41; regno++)
{
i = (unsigned long) read_register (regno);
hexword2ascii (num, i);
strcpy (buf + (regno * 8) + 1, num);
}
*(buf + (regno * 8) + 2) = 0;
make_gdb_packet (packet, buf);
if (array_send_packet (packet) == 0)
error ("Couldn't transmit packet\n");
if (array_get_packet (packet) == 0)
error ("Couldn't receive packet\n");
registers_changed ();
}
static void
array_store_register (int ignored)
{
array_store_registers (0 );
}
static void
array_prepare_to_store (void)
{
}
static void
array_files_info (void)
{
printf ("\tAttached to %s at %d baud.\n",
dev_name, baudrate);
}
static int
array_write_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
unsigned long i;
int j;
char packet[PBUFSIZ];
char buf[PBUFSIZ];
char num[9];
char *p;
debuglogs (1, "array_write_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
memset (buf, '\0', PBUFSIZ);
p = buf;
*p++ = 'M';
hexword2ascii (num, memaddr);
strcpy (p, num);
p += 8;
*p++ = ',';
hexword2ascii (num, len);
*p++ = num[4];
*p++ = num[5];
*p++ = num[6];
*p++ = num[7];
*p++ = ':';
for (j = 0; j < len; j++)
{
*p++ = tohex ((myaddr[j] >> 4) & 0xf);
*p++ = tohex (myaddr[j] & 0xf);
}
make_gdb_packet (packet, buf);
if (array_send_packet (packet) == 0)
error ("Couldn't transmit packet\n");
if (array_get_packet (packet) == 0)
error ("Couldn't receive packet\n");
return len;
}
static int
array_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
int j;
char buf[20];
char packet[PBUFSIZ];
int count;
unsigned long startaddr;
int len_this_pass;
debuglogs (1, "array_read_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
if (((memaddr - 1) + len) < memaddr)
{
errno = EIO;
return 0;
}
for (count = 0, startaddr = memaddr; count < len; startaddr += len_this_pass)
{
len_this_pass = 16;
if ((startaddr % 16) != 0)
{
len_this_pass -= startaddr % 16;
}
if (len_this_pass > (len - count))
{
len_this_pass = (len - count);
}
debuglogs (3, "read %d bytes from inferior address %x", len_this_pass,
startaddr);
sprintf (buf, "m%08lx,%04x", startaddr, len_this_pass);
make_gdb_packet (packet, buf);
if (array_send_packet (packet) == 0)
{
error ("Couldn't transmit packet\n");
}
if (array_get_packet (packet) == 0)
{
error ("Couldn't receive packet\n");
}
if (*packet == 0)
{
error ("Got no data in the GDB packet\n");
}
debuglogs (4, "array_read_inferior_memory: Got a \"%s\" back\n", packet);
for (j = 0; j < len_this_pass; j++)
{
myaddr[count++] = from_hex (*(packet + (j * 2))) * 16 + from_hex (*(packet + (j * 2) + 1));
debuglogs (5, "myaddr[%d] set to %x\n", count - 1, myaddr[count - 1]);
}
}
return (count);
}
static int
array_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct mem_attrib *attrib, struct target_ops *target)
{
if (write)
return array_write_inferior_memory (memaddr, myaddr, len);
else
return array_read_inferior_memory (memaddr, myaddr, len);
}
static void
array_kill (char *args, int from_tty)
{
return;
}
static void
array_mourn_inferior (void)
{
remove_breakpoints ();
generic_mourn_inferior ();
}
#define MAX_ARRAY_BREAKPOINTS 16
static CORE_ADDR breakaddr[MAX_ARRAY_BREAKPOINTS] =
{0};
static int
array_insert_breakpoint (CORE_ADDR addr, char *shadow)
{
int i;
int bp_size = 0;
CORE_ADDR bp_addr = addr;
debuglogs (1, "array_insert_breakpoint() addr = 0x%x", addr);
BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
for (i = 0; i <= MAX_ARRAY_BREAKPOINTS; i++)
{
if (breakaddr[i] == 0)
{
breakaddr[i] = addr;
if (sr_get_debug () > 4)
printf ("Breakpoint at %s\n", paddr_nz (addr));
array_read_inferior_memory (bp_addr, shadow, bp_size);
printf_monitor ("b 0x%x\n", addr);
expect_prompt (1);
return 0;
}
}
fprintf (stderr, "Too many breakpoints (> 16) for monitor\n");
return 1;
}
static int
array_remove_breakpoint (CORE_ADDR addr, char *shadow)
{
int i;
debuglogs (1, "array_remove_breakpoint() addr = 0x%x", addr);
for (i = 0; i < MAX_ARRAY_BREAKPOINTS; i++)
{
if (breakaddr[i] == addr)
{
breakaddr[i] = 0;
printf_monitor ("bd %x\n", i);
expect_prompt (1);
return 0;
}
}
fprintf (stderr, "Can't find breakpoint associated with 0x%s\n",
paddr_nz (addr));
return 1;
}
static void
array_stop (void)
{
debuglogs (1, "array_stop()");
printf_monitor ("\003");
expect_prompt (1);
}
static void
monitor_command (char *args, int fromtty)
{
debuglogs (1, "monitor_command (args=%s)", args);
if (array_desc == NULL)
error ("monitor target not open.");
if (!args)
error ("Missing command.");
printf_monitor ("%s\n", args);
expect_prompt (0);
}
static void
make_gdb_packet (char *buf, char *data)
{
int i;
unsigned char csum = 0;
int cnt;
char *p;
debuglogs (3, "make_gdb_packet(%s)\n", data);
cnt = strlen (data);
if (cnt > PBUFSIZ)
error ("make_gdb_packet(): to much data\n");
p = buf;
*p++ = '$';
for (i = 0; i < cnt; i++)
{
csum += data[i];
*p++ = data[i];
}
*p++ = '#';
*p++ = tohex ((csum >> 4) & 0xf);
*p++ = tohex (csum & 0xf);
*p = 0x0;
}
static int
array_send_packet (char *packet)
{
int c, retries, i;
char junk[PBUFSIZ];
retries = 0;
#if 0
for (i = 0; i < strlen (packet); i++)
{
debuglogs (5, "array_send_packet(): Scanning \'%c\'\n", packet[i]);
if ((isxdigit (packet[i])) || (isalpha (packet[i])))
continue;
switch (packet[i])
{
case '+':
case '-':
case '#':
case '$':
continue;
default:
retries++;
debuglogs (4, "array_send_packet(): Found a non-ascii digit \'%c\' in the packet.\n", packet[i]);
}
}
#endif
if (retries > 0)
error ("Can't send packet, found %d non-ascii characters", retries);
retries = 0;
while (retries++ <= 10)
{
printf_monitor ("%s", packet);
while (retries <= 10)
{
c = readchar (-timeout);
debuglogs (3, "Reading a GDB protocol packet... Got a '%c'\n", c);
switch (c)
{
case '+':
debuglogs (3, "Got Ack\n");
return 1;
case SERIAL_TIMEOUT:
debuglogs (3, "Timed out reading serial port\n");
printf_monitor ("@");
expect_prompt (1);
break;
case '-':
debuglogs (3, "Got NAK\n");
printf_monitor ("@");
expect_prompt (1);
break;
case '$':
debuglogs (3, "Got a junk packet\n");
i = 0;
do
{
c = readchar (timeout);
junk[i++] = c;
}
while (c != '#');
c = readchar (timeout);
junk[i++] = c;
c = readchar (timeout);
junk[i++] = c;
junk[i++] = '\0';
debuglogs (3, "Reading a junk packet, got a \"%s\"\n", junk);
continue;
default:
continue;
}
retries++;
debuglogs (3, "Retransmitting packet \"%s\"\n", packet);
break;
}
}
return 0;
}
static int
array_get_packet (char *packet)
{
int c;
int retries;
unsigned char csum;
unsigned char pktcsum;
char *bp;
csum = 0;
bp = packet;
memset (packet, 1, PBUFSIZ);
retries = 0;
while (retries <= 10)
{
do
{
c = readchar (timeout);
if (c == SERIAL_TIMEOUT)
{
debuglogs (3, "array_get_packet: got time out from serial port.\n");
}
debuglogs (3, "Waiting for a '$', got a %c\n", c);
}
while (c != '$');
retries = 0;
while (retries <= 10)
{
c = readchar (timeout);
debuglogs (3, "array_get_packet: got a '%c'\n", c);
switch (c)
{
case SERIAL_TIMEOUT:
debuglogs (3, "Timeout in mid-packet, retrying\n");
return 0;
case '$':
debuglogs (3, "Saw new packet start in middle of old one\n");
return 0;
case '#':
*bp = '\0';
pktcsum = from_hex (readchar (timeout)) << 4;
pktcsum |= from_hex (readchar (timeout));
if (csum == 0)
debuglogs (3, "\nGDB packet checksum zero, must be a bogus packet\n");
if (csum == pktcsum)
{
debuglogs (3, "\nGDB packet checksum correct, packet data is \"%s\",\n", packet);
printf_monitor ("@");
expect_prompt (1);
return 1;
}
debuglogs (3, "Bad checksum, sentsum=0x%x, csum=0x%x\n", pktcsum, csum);
return 0;
case '*':
debuglogs (5, "Run length encoding in packet\n");
csum += c;
c = readchar (timeout);
csum += c;
c = c - ' ' + 3;
if (c > 0 && c < 255 && bp + c - 1 < packet + PBUFSIZ - 1)
{
memset (bp, *(bp - 1), c);
bp += c;
continue;
}
*bp = '\0';
printf_filtered ("Repeat count %d too large for buffer.\n", c);
return 0;
default:
if ((!isxdigit (c)) && (!ispunct (c)))
debuglogs (4, "Got a non-ascii digit \'%c\'.\\n", c);
if (bp < packet + PBUFSIZ - 1)
{
*bp++ = c;
csum += c;
continue;
}
*bp = '\0';
puts_filtered ("Remote packet too long.\n");
return 0;
}
}
}
return 0;
}
static unsigned long
ascii2hexword (unsigned char *mem)
{
unsigned long val;
int i;
char buf[9];
val = 0;
for (i = 0; i < 8; i++)
{
val <<= 4;
if (mem[i] >= 'A' && mem[i] <= 'F')
val = val + mem[i] - 'A' + 10;
if (mem[i] >= 'a' && mem[i] <= 'f')
val = val + mem[i] - 'a' + 10;
if (mem[i] >= '0' && mem[i] <= '9')
val = val + mem[i] - '0';
buf[i] = mem[i];
}
buf[8] = '\0';
debuglogs (4, "ascii2hexword() got a 0x%x from %s(%x).\n", val, buf, mem);
return val;
}
static void
hexword2ascii (unsigned char *mem, unsigned long num)
{
int i;
unsigned char ch;
debuglogs (4, "hexword2ascii() converting %x ", num);
for (i = 7; i >= 0; i--)
{
mem[i] = tohex ((num >> 4) & 0xf);
mem[i] = tohex (num & 0xf);
num = num >> 4;
}
mem[8] = '\0';
debuglogs (4, "\tto a %s", mem);
}
static int
from_hex (int a)
{
if (a == 0)
return 0;
debuglogs (4, "from_hex got a 0x%x(%c)\n", a, a);
if (a >= '0' && a <= '9')
return a - '0';
if (a >= 'a' && a <= 'f')
return a - 'a' + 10;
if (a >= 'A' && a <= 'F')
return a - 'A' + 10;
else
{
error ("Reply contains invalid hex digit 0x%x", a);
}
}
static int
tohex (int nib)
{
if (nib < 10)
return '0' + nib;
else
return 'a' + nib - 10;
}
void
_initialize_remote_monitors (void)
{
add_com ("monitor", class_obscure, monitor_command,
"Send a command to the debug monitor.");
}
void
_initialize_array (void)
{
init_array_ops ();
add_target (&array_ops);
}