Annotation of previous/src/debug/debugInfo.c, revision 1.1.1.4

1.1       root        1: /*
                      2:   Hatari - debuginfo.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   debuginfo.c - functions needed to show info about the atari HW & OS
                      8:    components and "lock" that info to be shown on entering the debugger.
                      9: */
                     10: const char DebugInfo_fileid[] = "Hatari debuginfo.c : " __DATE__ " " __TIME__;
                     11: 
                     12: #include <stdio.h>
                     13: #include <assert.h>
1.1.1.3   root       14: #include <ctype.h>
1.1       root       15: #include "main.h"
                     16: #include "configuration.h"
                     17: #include "debugInfo.h"
                     18: #include "debugcpu.h"
                     19: #include "debugui.h"
                     20: #include "evaluate.h"
1.1.1.2   root       21: #include "file.h"
1.1       root       22: #include "ioMem.h"
                     23: #include "m68000.h"
                     24: #include "nextMemory.h"
1.1.1.2   root       25: #include "screen.h"
1.1       root       26: #include "video.h"
                     27: 
                     28: /* ------------------------------------------------------------------
                     29:  * Next HW information
                     30:  */
                     31: 
1.1.1.3   root       32: char* get_rtc_ram_info(void);
                     33: 
1.1       root       34: /**
                     35:  * DebugInfo_Rtc : display the Videl registers values.
                     36:  */
1.1.1.3   root       37: static void DebugInfo_Rtc(Uint32 dummy) {
                     38:     Update_StatusBar();
1.1       root       39:        fprintf(stdout,"%s",get_rtc_ram_info());
                     40: }
                     41: 
                     42: /* ------------------------------------------------------------------
                     43:  * CPU and DSP information wrappers
                     44:  */
                     45: 
                     46: /**
                     47:  * Helper to call debugcpu.c and debugdsp.c debugger commands
                     48:  */
                     49: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg)
                     50: {
                     51:        char cmdbuffer[16], argbuffer[12];
                     52:        char *argv[] = { cmdbuffer, NULL };
                     53:        int argc = 1;
                     54: 
                     55:        assert(strlen(command) < sizeof(cmdbuffer));
                     56:        strcpy(cmdbuffer, command);
                     57:        if (arg) {
                     58:                sprintf(argbuffer, "$%x", arg);
                     59:                argv[argc++] = argbuffer;
                     60:        }
                     61:        func(argc, argv);
                     62: }
                     63: 
                     64: static void DebugInfo_CpuRegister(Uint32 arg)
                     65: {
                     66:        DebugInfo_CallCommand(DebugCpu_Register, "register", arg);
                     67: }
                     68: static void DebugInfo_CpuDisAsm(Uint32 arg)
                     69: {
                     70:        DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg);
                     71: }
                     72: static void DebugInfo_CpuMemDump(Uint32 arg)
                     73: {
                     74:        DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg);
                     75: }
                     76: 
                     77: static void DebugInfo_DspRegister(Uint32 arg)
                     78: {
                     79: }
                     80: static void DebugInfo_DspDisAsm(Uint32 arg)
                     81: {
                     82: }
                     83: 
                     84: static void DebugInfo_DspMemDump(Uint32 arg)
                     85: {
                     86: }
                     87: 
                     88: /**
                     89:  * Convert arguments to Uint32 arg suitable for DSP memdump callback
                     90:  */
                     91: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[])
                     92: {
                     93:        Uint32 value;
                     94:        char space;
                     95:        if (argc != 2) {
                     96:                return 0;
                     97:        }
                     98:        space = toupper(argv[0][0]);
                     99:        if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) {
                    100:                fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]);
                    101:                return 0;
                    102:        }
                    103:        if (!Eval_Number(argv[1], &value) || value > 0xffff) {
                    104:                fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]);
                    105:                return 0;
                    106:        }
                    107:        return ((Uint32)space<<16) | value;
                    108: }
                    109: 
                    110: 
                    111: static void DebugInfo_RegAddr(Uint32 arg)
                    112: {
                    113: }
                    114: 
                    115: /**
                    116:  * Convert arguments to Uint32 arg suitable for RegAddr callback
                    117:  */
                    118: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[])
                    119: {
                    120:        Uint32 value, *regaddr;
                    121:        if (argc != 2) {
                    122:                return 0;
                    123:        }
                    124: 
                    125:        if (strcmp(argv[0], "disasm") == 0) {
                    126:                value = 'D';
                    127:        } else if (strcmp(argv[0], "memdump") == 0) {
                    128:                value = 'M';
                    129:        } else {
                    130:                fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]);
                    131:                return 0;
                    132:        }
                    133: 
                    134:        if (strlen(argv[1]) != 2 ||
                    135:            (!DebugCpu_GetRegisterAddress(argv[1], &regaddr) &&
                    136:             (toupper(argv[1][0]) != 'R' || !isdigit(argv[1][1]) || argv[1][2]))) {
                    137:                /* not CPU register or Rx DSP register */
                    138:                fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]);
                    139:                return 0;
                    140:        }
                    141:        
                    142:        value |= argv[1][0] << 24;
                    143:        value |= argv[1][1] << 16;
                    144:        value &= 0xffff00ff;
                    145:        return value;
                    146: }
                    147: 
                    148: 
                    149: /* ------------------------------------------------------------------
1.1.1.2   root      150:  * wrappers for command to parse debugger input file
                    151:  */
                    152: 
                    153: /* file name to be given before calling the Parse function,
                    154:  * needs to be set separately as it's a host pointer which
                    155:  * can be 64-bit i.e. may not fit into Uint32.
                    156:  */
                    157: static char *parse_filename;
                    158: 
                    159: /**
                    160:  * Parse and exec commands in the previously given debugger input file
                    161:  */
                    162: static void DebugInfo_FileParse(Uint32 dummy)
                    163: {
                    164:     if (parse_filename) {
                    165:         DebugUI_ParseFile(parse_filename);
                    166:     } else {
1.1.1.3   root      167:        // fputs("ERROR: debugger input file name to parse isn't set!\n", stderr);
1.1.1.2   root      168:     }
                    169: }
                    170: 
                    171: /**
                    172:  * Set which input file to parse.
                    173:  * Return true if file exists, false on error
                    174:  */
                    175: static Uint32 DebugInfo_FileArgs(int argc, char *argv[])
                    176: {
                    177:     if (argc != 1) {
                    178:         return false;
                    179:     }
                    180:     if (!File_Exists(argv[0])) {
                    181:         fprintf(stderr, "ERROR: given file '%s' doesn't exist!\n", argv[0]);
                    182:         return false;
                    183:     }
                    184:     if (parse_filename) {
                    185:         free(parse_filename);
                    186:     }
                    187:     parse_filename = strdup(argv[0]);
                    188:     return true;
                    189: }
                    190: 
                    191: /* ------------------------------------------------------------------
1.1       root      192:  * Debugger & readline TAB completion integration
                    193:  */
                    194: 
                    195: /**
                    196:  * Default information on entering the debugger
                    197:  */
                    198: static void DebugInfo_Default(Uint32 dummy)
                    199: {
1.1.1.3   root      200:        fprintf(stderr, "\nCPU=$%x, DSP=",
                    201:                M68000_GetPC());
1.1       root      202:                fprintf(stderr, "N/A\n");
                    203: }
                    204: 
                    205: static const struct {
1.1.1.2   root      206:        /* if overlaps with other functionality, list only for lock command */
1.1       root      207:        bool lock;
                    208:        const char *name;
                    209:        void (*func)(Uint32 arg);
                    210:        /* convert args in argv into single Uint32 for func */
                    211:        Uint32 (*args)(int argc, char *argv[]);
                    212:        const char *info;
                    213: } infotable[] = {
                    214:        { true, "default",   DebugInfo_Default,    NULL, "Show default debugger entry information" },
                    215:        { true, "disasm",    DebugInfo_CpuDisAsm,  NULL, "Disasm CPU from PC or given <address>" },
                    216:        { true, "dspdisasm", DebugInfo_DspDisAsm,  NULL, "Disasm DSP from given <address>" },
                    217:        { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" },
1.1.1.2   root      218:        { true, "dspregs",   DebugInfo_DspRegister,NULL, "Show DSP registers values" },
                    219:     { true, "file",      DebugInfo_FileParse, DebugInfo_FileArgs, "Parse commands from given debugger input <file>" },
1.1       root      220:        { true, "memdump",   DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" },
                    221:        { true, "regaddr",   DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" },
1.1.1.2   root      222:        { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU registers values" },
1.1       root      223:        { false,"rtc",     DebugInfo_Rtc,      NULL, "Show Next's RTC registers" }
                    224: };
                    225: 
1.1.1.2   root      226: static int LockedFunction = 4; /* index for the "default" function */
1.1       root      227: static Uint32 LockedArgument;
                    228: 
                    229: /**
                    230:  * Show selected debugger session information
                    231:  * (when debugger is (again) entered)
                    232:  */
                    233: void DebugInfo_ShowSessionInfo(void)
                    234: {
                    235:        infotable[LockedFunction].func(LockedArgument);
                    236: }
                    237: 
                    238: 
                    239: /**
                    240:  * Readline match callback for info subcommand name completion.
                    241:  * STATE = 0 -> different text from previous one.
                    242:  * Return next match or NULL if no matches.
                    243:  */
                    244: static char *DebugInfo_Match(const char *text, int state, bool lock)
                    245: {
                    246:        static int i, len;
                    247:        const char *name;
                    248:        
                    249:        if (!state) {
                    250:                /* first match */
                    251:                len = strlen(text);
                    252:                i = 0;
                    253:        }
                    254:        /* next match */
                    255:        while (i++ < ARRAYSIZE(infotable)) {
                    256:                if (!lock && infotable[i-1].lock) {
                    257:                        continue;
                    258:                }
                    259:                name = infotable[i-1].name;
                    260:                if (strncmp(name, text, len) == 0)
                    261:                        return (strdup(name));
                    262:        }
                    263:        return NULL;
                    264: }
                    265: char *DebugInfo_MatchLock(const char *text, int state)
                    266: {
                    267:        return DebugInfo_Match(text, state, true);
                    268: }
                    269: char *DebugInfo_MatchInfo(const char *text, int state)
                    270: {
                    271:        return DebugInfo_Match(text, state, false);
                    272: }
                    273: 
                    274: 
                    275: /**
                    276:  * Show requested command information.
                    277:  */
                    278: int DebugInfo_Command(int nArgc, char *psArgs[])
                    279: {
                    280:        Uint32 value;
                    281:        const char *cmd;
                    282:        bool ok, lock;
                    283:        int i, sub;
                    284: 
                    285:        sub = -1;
                    286:        if (nArgc > 1) {
                    287:                cmd = psArgs[1];                
                    288:                /* which subcommand? */
                    289:                for (i = 0; i < ARRAYSIZE(infotable); i++) {
                    290:                        if (strcmp(cmd, infotable[i].name) == 0) {
                    291:                                sub = i;
                    292:                                break;
                    293:                        }
                    294:                }
                    295:        }
                    296: 
                    297:        if (infotable[sub].args) {
                    298:                /* value needs callback specific conversion */
                    299:                value = infotable[sub].args(nArgc-2, psArgs+2);
                    300:                ok = !!value;
                    301:        } else {
                    302:                if (nArgc > 2) {
                    303:                        /* value is normal number */
                    304:                        ok = Eval_Number(psArgs[2], &value);
                    305:                } else {
                    306:                        value = 0;
                    307:                        ok = true;
                    308:                }
                    309:        }
                    310: 
                    311:        lock = (strcmp(psArgs[0], "lock") == 0);
                    312:        
                    313:        if (sub < 0 || !ok) {
                    314:                /* no subcommand or something wrong with value, show info */
                    315:                fprintf(stderr, "%s subcommands are:\n", psArgs[0]);
                    316:                for (i = 0; i < ARRAYSIZE(infotable); i++) {
                    317:                        if (!lock && infotable[i].lock) {
                    318:                                continue;
                    319:                        }
                    320:                        fprintf(stderr, "- %s: %s\n",
                    321:                                infotable[i].name, infotable[i].info);
                    322:                }
                    323:                return DEBUGGER_CMDDONE;
                    324:        }
                    325: 
                    326:        if (lock) {
                    327:                /* lock given subcommand and value */
                    328:                LockedFunction = sub;
                    329:                LockedArgument = value;
                    330:                fprintf(stderr, "Locked %s output.\n", psArgs[1]);
                    331:        } else {
                    332:                /* do actual work */
                    333:                infotable[sub].func(value);
                    334:        }
                    335:        return DEBUGGER_CMDDONE;
                    336: }

unix.superglobalmegacorp.com

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