Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

/projects/cubeos/src_current/libc/debug.c

Go to the documentation of this file.
00001 /*  src_experimental/libc/debug.c
00002    CubeOS Version 0.4.90 experimental
00003    Copyright (C) 1999,2000 Holger Kenn
00004 
00005    CubeOS is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or any later version.
00009 
00010    CubeOS is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015  */
00016 /*
00017  * Copyright (c) 1995, 1996 Cygnus Support
00018  *
00019  * The authors hereby grant permission to use, copy, modify, distribute,
00020  * and license this software and its documentation for any purpose, provided
00021  * that existing copyright notices are retained in all copies and that this
00022  * notice is included verbatim in any distributions. No written agreement,
00023  * license, or royalty fee is required for any of the authorized uses.
00024  * Modifications to this software may be copyrighted by their authors
00025  * and need not follow the licensing terms described here, provided that
00026  * the new terms are clearly indicated on the first page of each file where
00027  * they apply.
00028  */
00029 
00030 /*
00031  *   A debug packet whose contents are <data> looks like:
00032  *
00033  *        $ <data> # CSUM1 CSUM2
00034  *
00035  *        <data> must be ASCII alphanumeric and cannot include characters
00036  *        '$' or '#'.  If <data> starts with two characters followed by
00037  *        ':', then the existing stubs interpret this as a sequence number.
00038  *
00039  *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
00040  *        checksum of <data>, the most significant nibble is sent first.
00041  *        the hex digits 0-9,a-f are used.
00042  *
00043  *   We respond with:
00044  *
00045  *        +       - if CSUM is correct and ready for next packet
00046  *        -       - if CSUM is incorrect
00047  *
00048  *   <data> is as follows:
00049  *   Most values are encoded in ascii hex digits.
00050  */
00051 
00052 #include "debug.h"
00053 #include <signal.h>
00054 #include <kio.h>
00055 
00064 /*
00065  * buffers that hold the packets while they're being constructed.
00066  */
00067 char packet_in_buf[BUFMAX]; 
00068 char packet_out_buf[BUFMAX]; 
00069 int packet_index;       
00070 
00077 volatile int mem_err = 0; 
00078 
00085 int remote_debug = 0;
00086 
00093 int initialized = 0;
00094 
00095 /*
00096  * These variables are instantialted in the GDB stub code.
00097  */
00098 
00103 extern struct trap_info hard_trap_info[];
00104 
00109 extern void set_mem_fault_trap ();
00110 
00121 void debuglog (int level, char *msg)
00122 {
00123         char *p;
00124         unsigned char buf[BUFMAX];
00125         char newmsg[BUFMAX];
00126         int i;
00127 
00128         if (level > remote_debug)
00129                 return;
00130 
00131         if ((level < 0) || (level > 100)) {
00132                 print ("ERROR: debug print level out of range");
00133                 return;
00134         }
00135         /* convert some characters so it'll look right in the log */
00136         p = newmsg;
00137         for (i = 0; msg[i] != '\0'; i++) {
00138                 if (i > BUFMAX)
00139                         print ("\r\nERROR: Debug message too long\r\n");
00140                 switch (msg[i]) {
00141                 case '\n':      /* newlines */
00142                         *p++ = '\\';
00143                         *p++ = 'n';
00144                         continue;
00145                 case '\r':      /* carriage returns */
00146                         *p++ = '\\';
00147                         *p++ = 'r';
00148                         continue;
00149                 case '\033':    /* escape */
00150                         *p++ = '\\';
00151                         *p++ = 'e';
00152                         continue;
00153                 case '\t':      /* tab */
00154                         *p++ = '\\';
00155                         *p++ = 't';
00156                         continue;
00157                 case '\b':      /* backspace */
00158                         *p++ = '\\';
00159                         *p++ = 'b';
00160                         continue;
00161                 default:        /* no change */
00162                         *p++ = msg[i];
00163                 }
00164 
00165                 if (msg[i] < 26) {      /* modify control characters */
00166                         *p++ = '^';
00167                         *p++ = msg[i] + 'A';
00168                         continue;
00169                 }
00170                 if (msg[i] >= 127) {    /* modify control characters */
00171                         *p++ = '!';
00172                         *p++ = msg[i] + 'A';
00173                         continue;
00174                 }
00175         }
00176         *p = '\0';              /* terminate the string */
00177         print (newmsg);
00178         print ("\r\n");
00179 }
00180 
00188 int hex2digit (int digit)
00189 {
00190         if (digit == 0)
00191                 return 0;
00192 
00193         if (digit >= '0' && digit <= '9')
00194                 return digit - '0';
00195         if (digit >= 'a' && digit <= 'f')
00196                 return digit - 'a' + 10;
00197         if (digit >= 'A' && digit <= 'F')
00198                 return digit - 'A' + 10;
00199 
00200         /* shouldn't ever get this far */
00201         return ERROR;
00202 }
00203 
00211 char digit2hex (int digit)
00212 {
00213         if (digit < 10)
00214                 return '0' + digit;
00215         else
00216                 return 'a' + digit - 10;
00217 }
00218 
00230 unsigned char *
00231   mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
00232 {
00233         unsigned char ch;
00234 
00235         DEBUG (1, "In mem2hex");
00236 
00237         set_mem_fault_trap (MAY_FAULT);
00238 
00239         while (count-- > 0) {
00240                 ch = *mem++;
00241                 if (mem_err) {
00242                         DEBUG (1, "memory fault in mem2hex");
00243                         return 0;
00244                 }
00245                 *buf++ = digit2hex (ch >> 4);
00246                 *buf++ = digit2hex (ch & 0xf);
00247         }
00248 
00249         *buf = 0;
00250 
00251         set_mem_fault_trap (OK);
00252 
00253         return buf;
00254 }
00255 
00268 unsigned char *
00269   hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
00270 {
00271         int i;
00272         unsigned char ch;
00273 
00274         DEBUG (1, "In hex2mem");
00275 
00276         set_mem_fault_trap (may_fault);
00277 
00278         for (i = 0; i < count; i++) {
00279                 ch = hex2digit (*buf++) << 4;
00280                 ch |= hex2digit (*buf++);
00281                 *mem++ = ch;
00282                 if (mem_err)
00283                         return 0;
00284         }
00285 
00286         set_mem_fault_trap (0);
00287 
00288         return mem;
00289 }
00290 
00299 int hex2int (char **ptr, int *intValue)
00300 {
00301         int numChars = 0;
00302         int hexValue;
00303 
00304         *intValue = 0;
00305 
00306         while (**ptr) {
00307                 hexValue = hex2digit (**ptr);
00308                 if (hexValue < 0)
00309                         break;
00310 
00311                 *intValue = (*intValue << 4) | hexValue;
00312                 numChars++;
00313                 (*ptr)++;
00314         }
00315         return (numChars);
00316 }
00317 
00323 void getpacket (unsigned char *buffer)
00324 {
00325         unsigned char checksum;
00326         unsigned char xmitcsum;
00327         int i;
00328         int count;
00329         unsigned char ch;
00330 
00331         do {
00332                 /* wait around for the start character, ignore all other characters */
00333                 while ((ch = (_LIBC_inbyte () & 0x7f)) != '$');
00334 
00335                 checksum = 0;
00336                 xmitcsum = -1;
00337 
00338                 count = 0;
00339 
00340                 /* now, read until a # or end of buffer is found */
00341                 while (count < BUFMAX) {
00342                         ch = _LIBC_inbyte () & 0x7f;
00343                         if (ch == '#')
00344                                 break;
00345                         checksum = checksum + ch;
00346                         buffer[count] = ch;
00347                         count = count + 1;
00348                 }
00349 
00350                 if (count >= BUFMAX)
00351                         continue;
00352 
00353                 buffer[count] = 0;
00354 
00355                 if (ch == '#') {
00356                         xmitcsum = hex2digit (_LIBC_inbyte () & 0x7f) << 4;
00357                         xmitcsum |= hex2digit (_LIBC_inbyte () & 0x7f);
00358 #if 1
00359                         /* Humans shouldn't have to figure out checksums to type to it. */
00360                         _LIBC_outbyte ('+');
00361                         return;
00362 #endif
00363                         if (checksum != xmitcsum)
00364                                 _LIBC_outbyte ('-');    /* failed checksum */
00365                         else {
00366                                 _LIBC_outbyte ('+');    /* successful transfer */
00367                                 /* if a sequence char is present, reply the sequence ID */
00368                                 if (buffer[2] == ':') {
00369                                         _LIBC_outbyte (buffer[0]);
00370                                         _LIBC_outbyte (buffer[1]);
00371                                         /* remove sequence chars from buffer */
00372                                         count = strlen (buffer);
00373                                         for (i = 3; i <= count; i++)
00374                                                 buffer[i - 3] = buffer[i];
00375                                 }
00376                         }
00377                 }
00378         }
00379         while (checksum != xmitcsum);
00380 }
00381 
00387 void putpacket (unsigned char *buffer)
00388 {
00389         unsigned char checksum;
00390         int count;
00391         unsigned char ch;
00392 
00393         /* $<packet info>#<checksum>. */
00394         do {
00395                 _LIBC_outbyte ('$');
00396                 checksum = 0;
00397                 count = 0;
00398 
00399                 while (ch = buffer[count]) {
00400                         if (!_LIBC_outbyte (ch))
00401                                 return;
00402                         checksum += ch;
00403                         count += 1;
00404                 }
00405 
00406                 _LIBC_outbyte ('#');
00407                 _LIBC_outbyte (digit2hex (checksum >> 4));
00408                 _LIBC_outbyte (digit2hex (checksum & 0xf));
00409 
00410         }
00411         while ((_LIBC_inbyte () & 0x7f) != '+');
00412 }
00413 
00418 void gdb_event_loop (int sigval, unsigned long *registers)
00419 {
00420         int addr;
00421         int length;
00422         unsigned char *ptr;
00423 
00424         ptr = packet_out_buf;
00425 
00426         DEBUG (1, "In gdb_event_loop");
00427 
00428         while (1) {
00429                 packet_out_buf[0] = 0;
00430 
00431                 getpacket (packet_in_buf);
00432                 ptr = &packet_in_buf[1];
00433 
00434                 switch (packet_in_buf[0]) {
00435                 case '?':       /* get the last known signal */
00436                         gdb_last_signal (sigval);
00437                         break;
00438 
00439                 case 'd':       /* toggle debug messages from the stub */
00440                         gdb_toggle ();
00441                         break;
00442 
00443                 case 'g':       /* return the value of the CPU registers */
00444                         target_read_registers (registers);
00445                         break;
00446 
00447                 case 'G':       /* set the value of the CPU registers -
00448                                    return OK */
00449                         target_write_registers (registers);
00450                         break;
00451 
00452                 case 'm':       /* mAA..AA,LLLL  Read LLLL bytes at address
00453                                    AA..AA */
00454                         /* Try to read %x,%x.  */
00455                         if (hex2int ((char **) &ptr, &addr)
00456                             && *ptr++ == ','
00457                             && hex2int ((char **) &ptr, &length)) {
00458                                 gdb_read_memory (addr, length);
00459                         } else {
00460                                 make_return_packet (1);
00461                         }
00462                         break;
00463 
00464                 case 'M':       /* MAA..AA,LLLL: Write LLLL bytes at address
00465                                    AA.AA return OK */
00466                         /* Try to read '%x,%x:'.  */
00467                         if (hex2int ((char **) &ptr, &addr)
00468                             && *ptr++ == ','
00469                             && hex2int ((char **) &ptr, &length)
00470                             && *ptr++ == ':') {
00471                                 gdb_write_memory (addr, length, ptr);
00472                         } else {
00473                                 make_return_packet (2);
00474                         }
00475                         break;
00476 
00477                 case 'c':       /* cAA..AA    Continue at address
00478                                    AA..AA(optional) */
00479                         /* try to read optional parameter, pc unchanged if no parm */
00480                         if (hex2int ((char **) &ptr, &addr)) {
00481                                 write_pc (registers, addr);
00482                         }
00483                         /* 
00484                          * we need to flush the instruction cache here, as we may have
00485                          * deposited a breakpoint, and the icache probably has no way of
00486                          * knowing that a data ref to some location may have changed
00487                          * something that is in the instruction cache. 
00488                          */
00489 
00490                         flush_i_cache ();
00491                         /* by returning, we pick up execution where we left off */
00492                         return;
00493 
00494                         /* kill the program */
00495                 case 'k':
00496                         gdb_kill ();
00497                         break;
00498                 case 'r':       /* Reset */
00499                         target_reset ();
00500                         break;
00501                 }               /* switch */
00502 
00503                 /* reply to the request */
00504                 putpacket (packet_out_buf);
00505         }
00506         DEBUG (1, "Leaving handle_exception()");
00507 }
00508 
00511 \ingroup GDBDEBUG
00512 */
00513 int computeSignal (int tt)
00514 {
00515         struct trap_info *ht;
00516 
00517         for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
00518                 if (ht->tt == tt)
00519                         return ht->signo;
00520 
00521         return SIGHUP;          /* default for things we don't know about */
00522 }
00523 
00524 /*
00525 \brief Set up exception handlers for tracing and breakpoints
00526 \ingroup GDBDEBUG
00527 */
00528 void set_debug_traps ()
00529 {
00530         struct trap_info *ht;
00531 
00532         DEBUG (1, "Entering set_debug_traps()");
00533 
00534         if (hard_trap_info->tt == 0) {
00535                 print ("ERROR: ARG#$@%^&*!! no hard trap info!!\r\n");
00536         }
00537         for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
00538                 exception_handler (ht->tt, (unsigned long) default_trap_hook);
00539         }
00540 
00541         /* In case GDB is started before us, ack any packets (presumably "$?#xx") 
00542 
00543            sitting there.  */
00544 
00545         _LIBC_outbyte ('+');
00546         initialized = 1;
00547 
00548         DEBUG (1, "Leaving set_debug_traps()");
00549 }
00550 
00558 char *
00559   make_return_packet (int val)
00560 {
00561         if (val == 0) {
00562                 packet_out_buf[0] = 'O';
00563                 packet_out_buf[1] = 'K';
00564                 packet_out_buf[2] = 0;
00565         } else {
00566                 packet_out_buf[0] = 'E';
00567                 packet_out_buf[1] = digit2hex ((val >> 4) & 0xf);
00568                 packet_out_buf[2] = digit2hex (val & 0xf);
00569                 packet_out_buf[3] = 0;
00570         }
00571         return (packet_out_buf);
00572 }
00573 
00580 char *
00581   gdb_read_registers ()
00582 {
00583 }
00584 
00592 char *
00593   gdb_write_registers (char *regs)
00594 {
00595 }
00596 
00606 char *
00607   gdb_read_memory (long addr, int nbytes)
00608 {
00609         if (mem2hex ((char *) addr, packet_out_buf, nbytes, MAY_FAULT))
00610                 return (packet_out_buf);
00611         else {
00612                 return (make_return_packet (3));
00613         }
00614 }
00615 
00625 char *
00626   gdb_write_memory (long addr, int nbytes, char *mem)
00627 {
00628         if (hex2mem (mem, (char *) addr, nbytes, MAY_FAULT))
00629                 return (make_return_packet (OK));
00630         else {
00631                 return (make_return_packet (3));
00632         }
00633 }
00634 
00643 char *
00644   gdb_continue (int sig, long addr)
00645 {
00646 }
00647 
00656 char *
00657   gdb_step (int sig, long addr)
00658 {
00659 }
00660 
00667 char *
00668   gdb_kill ()
00669 {
00670         /* generically, we can't do anything for this command */
00671         return (make_return_packet (OK));
00672 }
00673 
00680 char *
00681   gdb_last_signal (int val)
00682 {
00683         DEBUG (1, "Entering gdb_last_signal()");
00684 
00685         packet_out_buf[0] = 'S';
00686         packet_out_buf[1] = digit2hex (val >> 4);
00687         packet_out_buf[2] = digit2hex (val & 0xf);
00688         packet_out_buf[3] = 0;
00689 
00690         DEBUG (1, "Leaving gdb_last_signal()");
00691         return (packet_out_buf);
00692 }
00693 
00701 char *
00702   gdb_baudrate (int baud)
00703 {
00704         /* generically, we can't do anything for this command */
00705         return (make_return_packet (OK));
00706 }
00707 
00725 char *
00726   gdb_dump_state ()
00727 {
00728 }
00729 
00737 char *
00738   gdb_detach ()
00739 {
00740 }
00741 
00754 char *
00755   gdb_set_thread (int cmd, int tid)
00756 {
00757         /* generically, we can't do anything for this command */
00758         return (make_return_packet (OK));
00759 }
00760 
00768 char *
00769   gdb_read_reg (int reg)
00770 {
00771         /* generically, we can't do anything for this command */
00772         return (make_return_packet (OK));
00773 }
00774 
00783 char *
00784   gdb_write_reg (int reg, long val)
00785 {
00786         /* generically, we can't do anything for this command */
00787 
00788         return (make_return_packet (OK));
00789 }
00790 
00797 char *
00798   gdb_exited ()
00799 {
00800         /* generically, we can't do anything for this command */
00801         return (make_return_packet (OK));
00802 }
00803 
00810 char *
00811   gdb_terminated ()
00812 {
00813 }
00814 
00823 char *
00824   gdb_hex (char *str, int nbytes)
00825 {
00826 }
00827 
00835 char *
00836   gdb_thread_alive (int tid)
00837 {
00838         /* generically, we can't do anything for this command */
00839         return (make_return_packet (OK));
00840 }
00841 
00848 char *
00849   gdb_extended ()
00850 {
00851         /* generically, we can't do anything for this command */
00852         return (make_return_packet (OK));
00853 }
00854 
00861 char *
00862   gdb_debug ()
00863 {
00864         if (remote_debug > 0)
00865                 remote_debug = 0;
00866         else
00867                 remote_debug = 1;
00868 
00869         return (make_return_packet (OK));
00870 }
00871 
00878 char *
00879   gdb_toggle ()
00880 {
00881         static int level = 0;
00882 
00883         if (remote_debug) {
00884                 level = remote_debug;
00885                 remote_debug = 0;
00886         } else {
00887                 remote_debug = level;
00888         }
00889 
00890         return (make_return_packet (OK));
00891 }
00892 
00899 char *
00900   gdb_reset ()
00901 {
00902         /* generically, we can't do anything for this command */
00903         return (make_return_packet (OK));
00904 }
00905 
00915 char *
00916   gdb_search (long addr, long pat, long mask)
00917 {
00918         /* generically, we can't do anything for this command */
00919         return (make_return_packet (OK));
00920 }
00921 
00929 char *
00930   gdb_get_query (char *query)
00931 {
00932         /* generically, we can't do anything for this command */
00933         return (make_return_packet (OK));
00934 }
00935 
00944 char *
00945   gdb_set (char *query)
00946 {
00947         /* generically, we can't do anything for this command */
00948         return (make_return_packet (OK));
00949 }

Generated on Thu Feb 20 15:38:45 2003 for cubeOS by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002