diff options
Diffstat (limited to 'libgloss/debug.c')
-rw-r--r-- | libgloss/debug.c | 848 |
1 files changed, 0 insertions, 848 deletions
diff --git a/libgloss/debug.c b/libgloss/debug.c deleted file mode 100644 index 3b1c8ff..0000000 --- a/libgloss/debug.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Copyright (c) 1995, 1996 Cygnus Support - * - * The authors hereby grant permission to use, copy, modify, distribute, - * and license this software and its documentation for any purpose, provided - * that existing copyright notices are retained in all copies and that this - * notice is included verbatim in any distributions. No written agreement, - * license, or royalty fee is required for any of the authorized uses. - * Modifications to this software may be copyrighted by their authors - * and need not follow the licensing terms described here, provided that - * the new terms are clearly indicated on the first page of each file where - * they apply. - */ - -/* - * A debug packet whose contents are <data> looks like: - * - * $ <data> # CSUM1 CSUM2 - * - * <data> must be ASCII alphanumeric and cannot include characters - * '$' or '#'. If <data> starts with two characters followed by - * ':', then the existing stubs interpret this as a sequence number. - * - * CSUM1 and CSUM2 are ascii hex representation of an 8-bit - * checksum of <data>, the most significant nibble is sent first. - * the hex digits 0-9,a-f are used. - * - * We respond with: - * - * + - if CSUM is correct and ready for next packet - * - - if CSUM is incorrect - * - * <data> is as follows: - * Most values are encoded in ascii hex digits. - */ - -#include "debug.h" -#include <signal.h> - -/* - * buffers that hold the packets while they're being constructed. - */ -char packet_in_buf[BUFMAX]; -char packet_out_buf[BUFMAX]; -int packet_index; - -/* - * indicate to caller of mem2hex or hex2mem that there has been an error. - * 0 means ok, 1 means error - */ -volatile int mem_err = 0; - -/* - * 1 means print debugging messages from the target, 0 means be quiet. This is - * changed by gdb_debug(). - */ -int remote_debug = 0; - -/* - * indicate whether the debug vectors ahave been initialized - * 0 means not yet, 1 means yep, it's ready. - */ -int initialized = 0; - -/* - * These variables are instantialted in the GDB stub code. - */ - -/* this is a list of signal to exception mappings. */ -extern struct trap_info hard_trap_info[]; - -/* this is a memory fault exception handler, used by mem2hex & hex2mem */ -extern void set_mem_fault_trap(); - -/* - * print debugging messages. This uses print, rather than one of the - * stdio routines, cause if there are stack or memory problems, the - * stdio routines don't work. - * params are the debug level, and the string to print - * it doesn't return anything. - */ -void -debuglog(int level, char *msg) -{ - char *p; - unsigned char buf[BUFMAX]; - char newmsg[BUFMAX]; - int i; - - if (level > remote_debug) - return; - - if ((level <0) || (level > 100)) { - print ("ERROR: debug print level out of range"); - return; - } - - /* convert some characters so it'll look right in the log */ - p = newmsg; - for (i = 0 ; msg[i] != '\0'; i++) { - if (i > BUFMAX) - print ("\r\nERROR: Debug message too long\r\n"); - switch (msg[i]) { - case '\n': /* newlines */ - *p++ = '\\'; - *p++ = 'n'; - continue; - case '\r': /* carriage returns */ - *p++ = '\\'; - *p++ = 'r'; - continue; - case '\033': /* escape */ - *p++ = '\\'; - *p++ = 'e'; - continue; - case '\t': /* tab */ - *p++ = '\\'; - *p++ = 't'; - continue; - case '\b': /* backspace */ - *p++ = '\\'; - *p++ = 'b'; - continue; - default: /* no change */ - *p++ = msg[i]; - } - - if (msg[i] < 26) { /* modify control characters */ - *p++ = '^'; - *p++ = msg[i] + 'A'; - continue; - } - if (msg[i] >= 127) { /* modify control characters */ - *p++ = '!'; - *p++ = msg[i] + 'A'; - continue; - } - } - *p = '\0'; /* terminate the string */ - print (newmsg); - print ("\r\n"); -} - -/* - * convert an ascii hex digit to a number. - * param is hex digit. - * returns a decimal digit. - */ -int -hex2digit (int digit) -{ - if (digit == 0) - return 0; - - if (digit >= '0' && digit <= '9') - return digit - '0'; - if (digit >= 'a' && digit <= 'f') - return digit - 'a' + 10; - if (digit >= 'A' && digit <= 'F') - return digit - 'A' + 10; - - /* shouldn't ever get this far */ - return ERROR; -} - -/* - * convert number NIB to a hex digit. - * param is a decimal digit. - * returns a hex digit. - */ -char -digit2hex(int digit) -{ - if (digit < 10) - return '0' + digit; - else - return 'a' + digit - 10; -} - -/* - * Convert the memory pointed to by mem into hex, placing result in buf. - * Return a pointer to the last char put in buf (null), in case of mem fault, - * return 0. - * If MAY_FAULT is non-zero, then we will handle memory faults by returning - * a 0, else treat a fault like any other fault in the stub. - */ -unsigned char * -mem2hex(unsigned char *mem, unsigned char *buf, int count, int may_fault) -{ - unsigned char ch; - - DEBUG (1, "In mem2hex"); - - set_mem_fault_trap(MAY_FAULT); - - while (count-- > 0) { - ch = *mem++; - if (mem_err) { - DEBUG (1, "memory fault in mem2hex"); - return 0; - } - *buf++ = digit2hex(ch >> 4); - *buf++ = digit2hex(ch & 0xf); - } - - *buf = 0; - - set_mem_fault_trap(OK); - - return buf; -} - -/* - * Convert the hex array pointed to by buf into binary to be placed in mem - * return a pointer to the character AFTER the last byte written - */ -unsigned char * -hex2mem(unsigned char *buf, unsigned char *mem, int count, int may_fault) -{ - int i; - unsigned char ch; - - DEBUG (1, "In hex2mem"); - - set_mem_fault_trap(may_fault); - - for (i=0; i<count; i++) { - ch = hex2digit(*buf++) << 4; - ch |= hex2digit(*buf++); - *mem++ = ch; - if (mem_err) - return 0; - } - - set_mem_fault_trap(0); - - return mem; -} - -/* - * while we find nice hex chars, build an int. - * param is a pointer to the string. - * returns the int in the param field, and the number of chars processed. - */ -int -hex2int (char **ptr, int *intValue) -{ - int numChars = 0; - int hexValue; - - *intValue = 0; - - while (**ptr) - { - hexValue = hex2digit(**ptr); - if (hexValue < 0) - break; - - *intValue = (*intValue << 4) | hexValue; - numChars ++; - (*ptr)++; - } - return (numChars); -} - -/* - * Scan for the sequence $<data>#<checksum> - */ -void -getpacket(unsigned char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - unsigned char ch; - - do { - /* wait around for the start character, ignore all other characters */ - while ((ch = (inbyte() & 0x7f)) != '$') ; - - checksum = 0; - xmitcsum = -1; - - count = 0; - - /* now, read until a # or end of buffer is found */ - while (count < BUFMAX) { - ch = inbyte() & 0x7f; - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - - if (count >= BUFMAX) - continue; - - buffer[count] = 0; - - if (ch == '#') { - xmitcsum = hex2digit(inbyte() & 0x7f) << 4; - xmitcsum |= hex2digit(inbyte() & 0x7f); -#if 1 - /* Humans shouldn't have to figure out checksums to type to it. */ - outbyte ('+'); - return; -#endif - if (checksum != xmitcsum) - outbyte('-'); /* failed checksum */ - else { - outbyte('+'); /* successful transfer */ - /* if a sequence char is present, reply the sequence ID */ - if (buffer[2] == ':') { - outbyte(buffer[0]); - outbyte(buffer[1]); - /* remove sequence chars from buffer */ - count = strlen(buffer); - for (i=3; i <= count; i++) - buffer[i-3] = buffer[i]; - } - } - } - } - while (checksum != xmitcsum); -} - -/* - * Send the packet in buffer. - */ -void -putpacket(unsigned char *buffer) -{ - unsigned char checksum; - int count; - unsigned char ch; - - /* $<packet info>#<checksum>. */ - do { - outbyte('$'); - checksum = 0; - count = 0; - - while (ch = buffer[count]) { - if (! outbyte(ch)) - return; - checksum += ch; - count += 1; - } - - outbyte('#'); - outbyte(digit2hex(checksum >> 4)); - outbyte(digit2hex(checksum & 0xf)); - - } - while ((inbyte() & 0x7f) != '+'); -} - -/* - * - */ -void -gdb_event_loop(int sigval, unsigned long *registers) -{ - int addr; - int length; - unsigned char *ptr; - ptr = packet_out_buf; - - DEBUG (1, "In gdb_event_loop"); - - while (1) { - packet_out_buf[0] = 0; - - getpacket(packet_in_buf); - ptr = &packet_in_buf[1]; - - switch (packet_in_buf[0]) { - case '?': /* get the last known signal */ - gdb_last_signal(sigval); - break; - - case 'd': /* toggle debug messages from the stub */ - gdb_toggle(); - break; - - case 'g': /* return the value of the CPU registers */ - target_read_registers(registers); - break; - - case 'G': /* set the value of the CPU registers - return OK */ - target_write_registers(registers); - break; - - case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ - /* Try to read %x,%x. */ - if (hex2int((char **)&ptr, &addr) - && *ptr++ == ',' - && hex2int((char **)&ptr, &length)) { - gdb_read_memory(addr, length); - } else { - make_return_packet(1); - } - break; - - case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ - /* Try to read '%x,%x:'. */ - if (hex2int((char **)&ptr, &addr) - && *ptr++ == ',' - && hex2int((char **)&ptr, &length) - && *ptr++ == ':') { - gdb_write_memory (addr, length, ptr); - } else { - make_return_packet(2); - } - break; - - case 'c': /* cAA..AA Continue at address AA..AA(optional) */ - /* try to read optional parameter, pc unchanged if no parm */ - if (hex2int((char **)&ptr, &addr)) { - write_pc(registers, addr); - } - - /* - * we need to flush the instruction cache here, as we may have - * deposited a breakpoint, and the icache probably has no way of - * knowing that a data ref to some location may have changed - * something that is in the instruction cache. - */ - - flush_i_cache(); - /* by returning, we pick up execution where we left off */ - return; - - /* kill the program */ - case 'k' : - gdb_kill(); - break; - case 'r': /* Reset */ - target_reset(); - break; - } /* switch */ - - /* reply to the request */ - putpacket(packet_out_buf); - } - DEBUG (1, "Leaving handle_exception()"); -} - -/* Convert the hardware trap type code to a unix signal number. */ - -int -computeSignal(int tt) -{ - struct trap_info *ht; - - for (ht = hard_trap_info; ht->tt && ht->signo; ht++) - if (ht->tt == tt) - return ht->signo; - - return SIGHUP; /* default for things we don't know about */ -} - -/* - * Set up exception handlers for tracing and breakpoints - */ -void -set_debug_traps() -{ - struct trap_info *ht; - - DEBUG (1, "Entering set_debug_traps()"); - - if (hard_trap_info->tt == 0) { - print ("ERROR: ARG#$@%^&*!! no hard trap info!!\r\n"); - } - - for (ht = hard_trap_info; ht->tt && ht->signo; ht++) { - exception_handler(ht->tt, (unsigned long)default_trap_hook); - } - - /* In case GDB is started before us, ack any packets (presumably - "$?#xx") sitting there. */ - - outbyte ('+'); - initialized = 1; - - DEBUG (1, "Leaving set_debug_traps()"); -} - -/* - * make a return packet. - * param is the value to return. - * 0 = OK, any other value is converted to a two digit hex number. - * returns a string or "OK" or "ENN", where NN is the error number. Each N - * is an ASCII encoded hex digit. - */ -char * -make_return_packet(int val) -{ - if (val == 0) { - packet_out_buf[0] = 'O'; - packet_out_buf[1] = 'K'; - packet_out_buf[2] = 0; - } else { - packet_out_buf[0] = 'E'; - packet_out_buf[1] = digit2hex((val >> 4) & 0xf); - packet_out_buf[2] = digit2hex(val & 0xf); - packet_out_buf[3] = 0; - } - return(packet_out_buf); -} - -/* - * g - read registers. - * no params. - * returns a vector of words, size is NUM_REGS. - */ -char * -gdb_read_registers() -{ -} - -/* - * G - write registers. - * param is a vector of words, size is NUM_REGS. - * returns an OK or an error number. - */ -char * -gdb_write_registers(char *regs) -{ -} - -/* - * m - read memory. - * params are the address to start the read at and the number of - * bytes to read. - * returns a vector of nbytes or an error number. - * Can be fewer bytes than requested if able to read only part of the - * data. - */ -char * -gdb_read_memory(long addr, int nbytes) -{ - if (mem2hex((char *)addr, packet_out_buf, nbytes, MAY_FAULT)) - return(packet_out_buf); - else { - return(make_return_packet(3)); - } -} - -/* - * M write memory - * params are the address to start writing to, the number of - * bytes to write, and the new values of the bytes. - * returns an OK or an error number. - */ -char * -gdb_write_memory(long addr, int nbytes, char *mem) -{ - if (hex2mem(mem, (char *)addr, nbytes, MAY_FAULT)) - return(make_return_packet(OK)); - else { - return(make_return_packet(3)); - } -} - -/* - * c - continue at address. - * param is the address to start at, and an optional signal. If - * sig is zero, then ignore it. - * returns an OK or an error number. - */ -char * -gdb_continue(int sig, long addr) -{ -} - -/* - * s - step instruction(s) - * param is the address to start at, and an optional signal. If - * sig is zero, then ignore it. - * returns an OK or an error number. - */ -char * -gdb_step(int sig, long addr) -{ -} - -/* - * k - kill program. - * no params. - * returns an OK or an error number. - */ -char * -gdb_kill() -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * ? - last signal. - * no params. - * returns the last signal number. - */ -char * -gdb_last_signal(int val) -{ - DEBUG (1, "Entering gdb_last_signal()"); - - packet_out_buf[0] = 'S'; - packet_out_buf[1] = digit2hex(val >> 4); - packet_out_buf[2] = digit2hex(val & 0xf); - packet_out_buf[3] = 0; - - DEBUG (1, "Leaving gdb_last_signal()"); - return (packet_out_buf); -} - -/* - * b - change baud rate. - * param is the new baudrate - * returns the baud rate. - */ -char * -gdb_baudrate(int baud) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * T - dump state. - * no params. - * returns the signal number, the registers, the thread ID, and - * possible extensions in a vector that looks like: - * TAAn...:r...;n...:r...;n...:r...; where: - * AA = signal number - * n... = register number (hex) - * r... = register contents - * n... = `thread' - * r... = thread process ID. This is a hex integer. - * n... = other string not starting with valid hex digit. - * gdb should ignore this n,r pair and go on to - * the next. This way we can extend the protocol. - */ -char * -gdb_dump_state() -{ -} - -/* - * D - host requests a detach - * no params. - * returns either a S, T, W, or X command. - * returns an OK or an error number. - */ -char * -gdb_detach() -{ -} - -/* - * H - set thread. - * params are the command to execute and the thread ID. - * cmd = 'c' for thread used in step and continue; - * cmd = 'g' for thread used in other operations. - * tid = -1 for all threads. - * tid = zero, pick a thread,any thread. - * returns an OK or an error number. - */ -char * -gdb_set_thread(int cmd, int tid) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * p - read one register. - * param is the register number. - * returns the register value or ENN. - */ -char * -gdb_read_reg(int reg) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * P - write one register. - * params are the register number, and it's new value. - * returns the register value or ENN. - */ -char * -gdb_write_reg(int reg, long val) -{ - /* generically, we can't do anything for this command */ - - return(make_return_packet(OK)); -} - -/* - * W - process exited. - * no params. - * returns the exit status. - */ -char * -gdb_exited() -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * X - process terminated. - * no params. - * returns the last signal. - */ -char * -gdb_terminated() -{ -} - -/* - * O - hex encoding. - * params are a vector of bytes, and the number of bytes to encode. - * returns a vector of ASCII encoded hex numbers. - */ -char * -gdb_hex(char *str, int nbytes) -{ -} - -/* - * A - tread alive request. - * param is the thread ID. - * returns an OK or an error number. - */ -char * -gdb_thread_alive(int tid) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * ! - extended protocol. - * no params. - * returns an OK or an error number. - */ -char * -gdb_extended() -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * d - toggle gdb stub diagnostics. - * no params. - * returns an OK or an error number. - */ -char * -gdb_debug() -{ - if (remote_debug > 0) - remote_debug = 0; - else - remote_debug = 1; - - return(make_return_packet(OK)); -} - -/* - * d - toggle gdb stub. - * no params. - * returns an OK or an error number. - */ -char * -gdb_toggle() -{ - static int level = 0; - - if (remote_debug) { - level = remote_debug; - remote_debug = 0; - } else { - remote_debug = level; - } - - return(make_return_packet(OK)); -} - -/* - * r - reset target - * no params. - * returns an OK or an error number. - */ -char * -gdb_reset() -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * t - search backwards. - * params are the address to start searching from, a pattern to match, and - * the mask to use. - * FIXME: not entirely sure what this is supposed to return. - */ -char * -gdb_search(long addr, long pat, long mask) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * q - general get query. - * param is a string, that's the query to be executed. - * FIXME: not entirely sure what this is supposed to return. - */ -char * -gdb_get_query(char *query) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - -/* - * Q - general set query - * param is a string, that's the query to be executed. - * FIXME: not entirely sure what this means. - * returns an OK or an error number. - */ -char * -gdb_set(char *query) -{ - /* generically, we can't do anything for this command */ - return(make_return_packet(OK)); -} - - |