Annotation of hatari/src/debugui.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   debugui.c - this is the code for the mini-debugger, when the pause button is pressed,
        !             5:   the emulator is (hopefully) halted and this little CLI can be used (in the terminal
        !             6:   box) for debugging tasks like memory and register dumps
        !             7:   
        !             8:   (Personal note: Writing this reminded me how much I dislike writing syntax parsers,
        !             9:   especially with languages with weak string-handling, like C. Also,
        !            10:   please have oversight with any ugly code: This was written at 4 a.m. /Sven )
        !            11: */
        !            12: 
        !            13: #include <ctype.h>
        !            14: 
        !            15: #include "main.h"
        !            16: #include "configuration.h"
        !            17: #include "decode.h"
        !            18: #include "gemdos.h"
        !            19: #include "intercept.h"
        !            20: #include "reset.h"
        !            21: #include "m68000.h"
        !            22: #include "memorySnapShot.h"
        !            23: #include "screen.h"
        !            24: #include "sound.h"
        !            25: #include "timer.h"
        !            26: #include "tos.h"
        !            27: #include "video.h"
        !            28: 
        !            29: #include "uae-cpu/hatari-glue.h"
        !            30: 
        !            31: 
        !            32: #define DEBUG_QUIT     0
        !            33: #define DEBUG_CMD      1
        !            34: 
        !            35: #define MEMDUMP_COLS   16      /* memdump, number of bytes per row */
        !            36: #define MEMDUMP_ROWS   4       /* memdump, number of rows */
        !            37: #define DISASM_INSTS   5       /* disasm - number of instructions */
        !            38: 
        !            39: BOOL bMemDump;         /* has memdump been called? */
        !            40: unsigned long memdump_addr; /* memdump address */
        !            41: unsigned long disasm_addr;  /* disasm address */
        !            42: 
        !            43: /* convert string to lowercase */
        !            44: void string_tolower(char *str)
        !            45: {
        !            46:   int i=0;
        !            47:   while(str[i] != '\0'){
        !            48:     if(isupper(str[i])) str[i] = tolower(str[i]);
        !            49:     i++;
        !            50:   }
        !            51: }
        !            52: 
        !            53: /* truncate string at first unprintable char (e.g. newline) */
        !            54: void string_trunc(char *str){
        !            55:   int i=0;
        !            56:   while(str[i] != '\0'){
        !            57:     if(!isprint(str[i])) str[i] = '\0';
        !            58:     i++;
        !            59:   }
        !            60: }
        !            61: 
        !            62: /* check if string is valid hex number. */
        !            63: BOOL isHex(char *str)
        !            64: {
        !            65:   int i=0;
        !            66:   while(str[i] != '\0' && str[i] != ' '){
        !            67:     if(!isxdigit(str[i]))return(FALSE);
        !            68:     i++;
        !            69:   }
        !            70:   return(TRUE);
        !            71: }
        !            72: 
        !            73: /*-----------------------------------------------------------------------*/
        !            74: /*
        !            75:   Load a binary file to a memory address.
        !            76: */
        !            77: void DebugUI_LoadBin(char *args){
        !            78:   FILE *fp;
        !            79:   unsigned char c;
        !            80:   char dummy[100];
        !            81:   char filename[200];
        !            82:   unsigned long address;
        !            83:   int i=0;
        !            84: 
        !            85:   if(sscanf(args, "%s%s%lx", dummy, filename, &address) != 3){
        !            86:     fprintf(stderr, "Invalid arguments!\n");
        !            87:     return;
        !            88:   }
        !            89:   address &= 0x00FFFFFF;
        !            90:   if((fp = fopen(filename, "rb")) == NULL){
        !            91:     fprintf(stderr,"Cannot open file!\n");
        !            92:   }
        !            93: 
        !            94:   c = fgetc(fp);
        !            95:   while(!feof(fp)){
        !            96:     i++;
        !            97:     STMemory_WriteByte(address++, c);    
        !            98:     c = fgetc(fp);
        !            99:   }
        !           100:   fprintf(stderr,"  Read 0x%x bytes.\n", i);
        !           101:   fclose(fp);
        !           102: }
        !           103: 
        !           104: /*-----------------------------------------------------------------------*/
        !           105: /*
        !           106:   Dump memory from an address to a binary file.
        !           107: */
        !           108: void DebugUI_SaveBin(char *args){
        !           109:   FILE *fp;
        !           110:   unsigned char c;
        !           111:   char filename[200];
        !           112:   char dummy[100];
        !           113:   unsigned long address;
        !           114:   unsigned long bytes;
        !           115:   int i=0;
        !           116: 
        !           117:   if(sscanf(args, "%s%s%lx%lx", dummy, filename, &address, &bytes) != 4){
        !           118:     fprintf(stderr, "  Invalid arguments!");
        !           119:     return;
        !           120:   }
        !           121:   address &= 0x00FFFFFF;
        !           122:   if((fp = fopen(filename, "wb")) == NULL){
        !           123:     fprintf(stderr,"  Cannot open file!\n");
        !           124:   }
        !           125: 
        !           126:   while(i < bytes){
        !           127:     c = STMemory_ReadByte(address++);    
        !           128:     fputc(c, fp);
        !           129:     i++;
        !           130:   }
        !           131:   fclose(fp);
        !           132:   fprintf(stderr, "  Wrote 0x%x bytes.\n", bytes); 
        !           133: }
        !           134: 
        !           135: /*-----------------------------------------------------------------------*/
        !           136: /*
        !           137:   Do a register dump.
        !           138: */
        !           139: void DebugUI_RegDump()
        !           140: {
        !           141:   int i;
        !           142: 
        !           143:   fprintf(stderr, "D0 = $%8.8lx\tA0 = $%8.8lx\n", Regs[REG_D0], Regs[REG_A0]);
        !           144:   fprintf(stderr, "D1 = $%8.8lx\tA1 = $%8.8lx\n", Regs[REG_D1], Regs[REG_A1]);
        !           145:   fprintf(stderr, "D2 = $%8.8lx\tA2 = $%8.8lx\n", Regs[REG_D2], Regs[REG_A2]);
        !           146:   fprintf(stderr, "D3 = $%8.8lx\tA3 = $%8.8lx\n", Regs[REG_D3], Regs[REG_A3]);
        !           147:   fprintf(stderr, "D4 = $%8.8lx\tA4 = $%8.8lx\n", Regs[REG_D4], Regs[REG_A4]);
        !           148:   fprintf(stderr, "D5 = $%8.8lx\tA5 = $%8.8lx\n", Regs[REG_D5], Regs[REG_A5]);
        !           149:   fprintf(stderr, "D6 = $%8.8lx\tA6 = $%8.8lx\n", Regs[REG_D6], Regs[REG_A6]);
        !           150:   fprintf(stderr, "D7 = $%8.8lx\tA7 = $%8.8lx\n", Regs[REG_D7], Regs[REG_A7]);
        !           151:   fprintf(stderr, "PC = $%8.8lx\tSR = %%", m68k_getpc());
        !           152:   /* Rather obfuscated way of printing SR in binary */
        !           153:   for(i=0;i<8;i++)fprintf(stderr, "%i", (SR & (1 << (15-i)))?1:0);
        !           154:   fprintf(stderr," "); /* space between bytes */
        !           155:   for(i=8;i<16;i++)fprintf(stderr, "%i", (SR & (1 << (15-i)))?1:0);
        !           156:   fprintf(stderr,"\n");
        !           157: }
        !           158: 
        !           159: 
        !           160: /*-----------------------------------------------------------------------*/
        !           161: /*
        !           162:   Dissassemble - arg = starting address, or PC.
        !           163: */
        !           164: void DebugUI_DisAsm(char *arg, BOOL cont)
        !           165: { 
        !           166:   int i;
        !           167:   uaecptr nextpc;
        !           168:   
        !           169:   if(cont != TRUE){    
        !           170:     if(!isHex(arg)) {
        !           171:       fprintf(stderr,"Invalid address!\n");
        !           172:       return;
        !           173:     }
        !           174:     i = sscanf(arg, "%lx", &disasm_addr);
        !           175:     
        !           176:     if(i == 0){
        !           177:       fprintf(stderr,"Invalid address!\n");
        !           178:       return;
        !           179:     }
        !           180:   } else 
        !           181:     if(!disasm_addr) disasm_addr = m68k_getpc();
        !           182: 
        !           183:   disasm_addr &= 0x00FFFFFF;
        !           184: 
        !           185:   m68k_disasm(stderr, (uaecptr)disasm_addr, &nextpc, 5);
        !           186:   disasm_addr = nextpc;
        !           187: }
        !           188: 
        !           189: /*-----------------------------------------------------------------------*/
        !           190: /*
        !           191:   Do a memory dump, args = starting address.
        !           192: */
        !           193: void DebugUI_MemDump(char *arg, BOOL cont)
        !           194: { 
        !           195:   int i,j;
        !           196:   
        !           197:   if(cont != TRUE){    
        !           198:     if(!isHex(arg)) {
        !           199:       bMemDump = FALSE;
        !           200:       fprintf(stderr,"Invalid address!\n");
        !           201:       return;
        !           202:     }
        !           203:     i = sscanf(arg, "%lx", &memdump_addr);
        !           204:     
        !           205:     if(i == 0){
        !           206:       bMemDump = FALSE;
        !           207:       fprintf(stderr,"Invalid address!\n");
        !           208:       return;
        !           209:     }
        !           210:   }
        !           211: 
        !           212:   memdump_addr &= 0x00FFFFFF;
        !           213:   bMemDump = TRUE;
        !           214: 
        !           215:   fprintf(stderr, "%6.6X: ", memdump_addr);
        !           216:   for(j=0;j<MEMDUMP_ROWS-1;j++){
        !           217:     for(i=0;i<MEMDUMP_COLS;i++)
        !           218:       fprintf(stderr, "%2.2x ",STMemory_ReadByte(memdump_addr++));
        !           219:   fprintf(stderr, "\n%6.6X: ", memdump_addr);
        !           220:   }
        !           221:   for(i=0;i<MEMDUMP_COLS;i++)
        !           222:     fprintf(stderr, "%2.2x ",STMemory_ReadByte(memdump_addr++));
        !           223:   fprintf(stderr,"\n"); 
        !           224: }
        !           225: 
        !           226: /*-----------------------------------------------------------------------*/
        !           227: /*
        !           228:   Do a memory write, arg = starting address, followed by bytes.
        !           229: */
        !           230: void DebugUI_MemWrite(char *addr_str, char *arg)
        !           231: {
        !           232:   int i, j, numBytes;
        !           233:   long write_addr;
        !           234:   unsigned char bytes[300]; /* store bytes */
        !           235:   char temp[15];
        !           236:   int d;
        !           237: 
        !           238:   numBytes = 0;
        !           239:   i = 0;
        !           240: 
        !           241:   string_trunc(arg);
        !           242:   while(arg[i] == ' ')i++; /* skip spaces */
        !           243:   while(arg[i] != ' ')i++; /* skip command */
        !           244:   while(arg[i] == ' ')i++; /* skip spaces */
        !           245: 
        !           246:   j = 0;
        !           247:   while(isxdigit(arg[i]) && j < 14) /* get address */
        !           248:     temp[j++] = arg[i++];
        !           249:   temp[j] = '\0';
        !           250:   j = sscanf(temp, "%x", &write_addr);
        !           251:   
        !           252:   /* if next char is not valid, or it's not a valid address */
        !           253:   if((arg[i] != '\0' && arg[i] != ' ') || (j == 0)){
        !           254:     fprintf(stderr, "Bad address!\n");
        !           255:     return;
        !           256:   }
        !           257:       
        !           258:   write_addr &= 0x00FFFFFF;
        !           259:   
        !           260:   while(arg[i] == ' ')i++; /* skip spaces */
        !           261: 
        !           262:   /* get bytes data */  
        !           263:   while(arg[i] != '\0'){
        !           264:     j = 0;
        !           265:     while(isxdigit(arg[i]) && j < 14) /* get byte */
        !           266:       temp[j++] = arg[i++];
        !           267:     temp[j] = '\0';
        !           268: 
        !           269:     /* if next char is not a null or a space - it's not valid. */
        !           270:     if(arg[i] != '\0' && arg[i] != ' '){
        !           271:        fprintf(stderr, "Bad byte argument: %c\n", arg[i]);
        !           272:        return;
        !           273:     }
        !           274:       
        !           275:     if(temp[0] != '\0')
        !           276:       if(sscanf(temp,"%x", &d) != 1){
        !           277:        fprintf(stderr, "Bad byte argument!\n");
        !           278:        return;
        !           279:       }         
        !           280: 
        !           281:     bytes[numBytes] = (d&0x0FF);
        !           282:     numBytes++;
        !           283:     while(arg[i] == ' ')i++; /* skip any spaces */
        !           284:   }
        !           285: 
        !           286:   /* write the data */
        !           287:   for(i=0;i<numBytes;i++)
        !           288:     STMemory_WriteByte(write_addr + i, bytes[i]);
        !           289: }
        !           290: 
        !           291: /*-----------------------------------------------------------------------*/
        !           292: /*
        !           293:   Help!
        !           294: */
        !           295: void DebugUI_Help()
        !           296: {
        !           297:   fprintf(stderr,"---- debug mode commands ----\n");
        !           298:   fprintf(stderr," d [address]- disassemble from PC, or given address. \n");
        !           299:   fprintf(stderr," r - dump register values \n");
        !           300:   fprintf(stderr," m [address] - dump memory at address, \n\tm alone continues from previous address.\n");
        !           301:   fprintf(stderr," w address bytes - write bytes to a memory address, bytes are space separated. \n");
        !           302:   fprintf(stderr," l filename address - load a file into memory starting at address. \n");
        !           303:   fprintf(stderr," s filename address length - dump length bytes from memory to a file. \n");
        !           304:   fprintf(stderr," q - return to emulation\n");
        !           305:   fprintf(stderr,"-----------------------------\n");
        !           306:   fprintf(stderr,"\n");
        !           307: }
        !           308: 
        !           309: /*-----------------------------------------------------------------------*/
        !           310: /*
        !           311:   Get a UI command, return it.
        !           312: */
        !           313: int DebugUI_Getcommand()
        !           314: {  
        !           315:   char temp[255];
        !           316:   char command[255], arg[255];
        !           317:   int i;
        !           318:   fprintf(stderr,"> ");
        !           319:   temp[0] = '\0';
        !           320:   fgets(temp, 255, stdin);
        !           321: 
        !           322:   i = sscanf(temp, "%s%s", command, arg);
        !           323:   string_tolower(command);
        !           324: 
        !           325:   if(i == 0){
        !           326:     fprintf(stderr,"  Unknown command.\n");
        !           327:     return(DEBUG_CMD);
        !           328:   }
        !           329: 
        !           330:   switch(command[0]){
        !           331:   case 'q':
        !           332:     return(DEBUG_QUIT);
        !           333:     break;
        !           334: 
        !           335:   case 'h':
        !           336:   case '?':
        !           337:     DebugUI_Help(); /* get help */
        !           338:     return(DEBUG_CMD);
        !           339:     break;
        !           340: 
        !           341:   case 'd':
        !           342:     if(i < 2)  /* no arg? */
        !           343:       DebugUI_DisAsm(arg, TRUE);     /* No arg - disassemble at PC */
        !           344:     else DebugUI_DisAsm(arg, FALSE); /* disasm at address. */
        !           345:     break;
        !           346: 
        !           347:   case 'm':
        !           348:     if(i < 2){  /* no arg? */
        !           349:       if(bMemDump == FALSE){
        !           350:        fprintf(stderr,"  Usage: m address\n");
        !           351:        return(DEBUG_CMD);
        !           352:       }
        !           353:       DebugUI_MemDump(arg, TRUE);     /* No arg - continue memdump */
        !           354:     } else DebugUI_MemDump(arg, FALSE); /* new memdump */
        !           355:     break;
        !           356: 
        !           357:   case 'w':
        !           358:     if(i < 2){  /* no arg? */
        !           359:       fprintf(stderr,"  Usage: w address bytes\n");
        !           360:       return(DEBUG_CMD);
        !           361:     }
        !           362:     DebugUI_MemWrite(arg, temp);
        !           363:     break;
        !           364: 
        !           365:   case 'r':
        !           366:     DebugUI_RegDump();
        !           367:     break;
        !           368: 
        !           369:   case 'l':
        !           370:     if(i < 2){  /* no arg? */
        !           371:       fprintf(stderr,"  Usage: l filename address\n");
        !           372:       return(DEBUG_CMD);
        !           373:     }
        !           374:     DebugUI_LoadBin(temp);
        !           375:     break;
        !           376: 
        !           377:   case 's':
        !           378:     if(i < 2){  /* no arg? */
        !           379:       fprintf(stderr,"  Usage: s filename address bytes\n");
        !           380:       return(DEBUG_CMD);
        !           381:     }
        !           382:     DebugUI_SaveBin(temp);
        !           383:     break;
        !           384: 
        !           385:   default:
        !           386:     fprintf(stderr,"  Unknown command: '%s'\n", command);
        !           387:     break;
        !           388:   }
        !           389: 
        !           390:   return(DEBUG_CMD);
        !           391: }
        !           392: 
        !           393: 
        !           394: /*-----------------------------------------------------------------------*/
        !           395: /*
        !           396:   Debug UI
        !           397: */
        !           398: void DebugUI()
        !           399: {
        !           400:   bMemDump = FALSE;
        !           401:   disasm_addr = 0;
        !           402:   fprintf(stderr,"\nYou have entered debug mode. Type q to quit, h for help. \n------------------------------\n");
        !           403:   while(DebugUI_Getcommand() != DEBUG_QUIT);
        !           404:   fprintf(stderr,"Returning to emulation...\n------------------------------\n\n");
        !           405: }
        !           406: 
        !           407: 
        !           408: 
        !           409: 
        !           410: 
        !           411: 
        !           412: 
        !           413: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.