📄 pdebug.c
字号:
/***************************************************************************** XCopilotThis code is part of XCopilot, a port of copilot Copyright (C) 1997 Ivan A. Curtis icurtis@radlogic.com.auThe original MS-Windows95 copilot emulator was written by Greg Hewgill.The following copyright notice appeared on the original copilot sources: Copyright (c) 1996 Greg Hewgill MC68000 Emulation code is from Bernd Schmidt's Unix Amiga Emulator. The following copyright notice appeared in those files: Original UAE code Copyright (c) 1995 Bernd SchmidtThis code must not be distributed without these copyright notices intact.**************************************************************************************************************************************************************Filename: pdebug.cDescription: debugging routines for xcopilot emulatorUpdate History: (most recent first) Ian Goldberg 26-Jun-98 12:42 -- added support for PalmOS 3.x Ian Goldberg 25-Sep-97 16:18 -- fixed loading of filenames with spaces Ian Goldberg 10-Apr-97 16:53 -- added logging of flow traces I. Curtis 9-Apr-97 11:54 -- added debug via socket I. Curtis 5-Mar-97 21:03 -- added load command I. Curtis 27-Feb-97 22:16 -- created - start/stop/quit commands******************************************************************************/#include <config.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/stat.h>#include <stdio.h>#include <string.h>#include "config.h"#include "sysdeps.h"#include "shared.h"#include "memory.h"#include "custom.h"#include "newcpu.h"#include "dragonball.h"#include "pilotcpu.h"#include "fakecall.h"#include "pdebug.h"#define DEBUG_OK 0#define DEBUG_ERR 1#define MaxLineLen 200 /* input buffer */static char *Delim = " \t\r\n"; /* command token delimeters *//***************************************************************************** * * * Command Handlers * * * *****************************************************************************//* * Each command handler is a function with the * prototype : * int fn(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr) * out and in are the files currently being used for output and input * cmd is the comand word, line is the rest of the command line * and shptr is a pointer to the shared memroy image */#ifndef HAVE_STRSEP/* Copyright (C) 1992, 1993, 1996 Free Software Foundation, Inc.This file is part of the GNU C Library.The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General Public License aspublished by the Free Software Foundation; either version 2 of theLicense, or (at your option) any later version.The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with the GNU C Library; see the file COPYING.LIB. Ifnot, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */char *strsep (char **stringp, const char *delim){ char *begin, *end; begin = *stringp; if (! begin || *begin == '\0') return NULL; /* Find the end of the token. */ end = strpbrk (begin, delim); if (end) { /* Terminate the token and set *STRINGP past NUL character. */ *end++ = '\0'; *stringp = end; } else /* No more delimiters; this is the last token. */ *stringp = NULL; return begin;}#endif/* This variable stores the MEMORY_VERSION corresponding to the ROM we're using. We need to know this so that we can construct a valid chunk header. A value of 1 is for ROMs <= 2.x; A value of 2 is for 3.0. It's unclear what is the best way to set this. Autodetection would be great, if we could do it correctly. - Ian */int pdebug_memversion = 1;/*********************** * Load an application * ***********************/int dbg_loadapp(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ char *fname; FILE *prcfile; int err; struct stat prcstats; if (out == NULL) { out = stderr; } /* * get the file name */ if (cmd) { /* If invoked from the right-button menu, skip these checks */ if (!(fname = strsep(&line, Delim))) { if (out) { fprintf(out, "error - you must specify a file to load\n"); } return DEBUG_ERR; } } else { fname = line; } err = stat(fname, &prcstats); if (err != 0) { if (out) { fprintf(out, "error - cannot stat \"%s\"\n", fname); } return DEBUG_ERR; } prcfile = fopen(fname, "r"); if (prcfile == NULL) { if (out) { fprintf(out, "error - cannot open \"%s\" for read\n", fname); } return DEBUG_ERR; } if (pdebug_memversion == 1) { int size; unsigned int csize; size = prcstats.st_size; csize = (size + 7) & ~1; /* * Check that size is not larger than scratchmemory */ if (size + 8 > SCRATCH_SIZE || csize > 0xFFFF) { if (out) { fprintf(out, "error - \"%s\" too large\n", fname); } fclose(prcfile); return DEBUG_ERR; } /* * set up fake chunk header */ scratchmemory[0] = 0xFF; scratchmemory[1] = 0xFF; scratchmemory[2] = (UBYTE)((csize >> 8) & 0xff); scratchmemory[3] = (UBYTE)(csize & 0xff); scratchmemory[4] = 0xF0; scratchmemory[5] = (UBYTE)((csize - 6 - size) & 0x0f); scratchmemory[6] = 0; scratchmemory[7] = 0; } else if (pdebug_memversion == 2) { int size; unsigned int csize; size = prcstats.st_size; csize = (size + 9) & ~1; /* * Check that size is not larger than scratchmemory */ if (size + 8 > SCRATCH_SIZE || csize > 0xFFFFFF) { if (out) { fprintf(out, "error - \"%s\" too large\n", fname); } fclose(prcfile); return DEBUG_ERR; } /* * set up fake chunk header (version 2) */ scratchmemory[0] = (UBYTE)((csize - 8 - size) & 0x0f); scratchmemory[1] = (UBYTE)((csize >> 16) & 0xff); scratchmemory[2] = (UBYTE)((csize >> 8) & 0xff); scratchmemory[3] = (UBYTE)(csize & 0xff); scratchmemory[4] = 0xF0; scratchmemory[5] = 0; scratchmemory[6] = 0; scratchmemory[7] = 0; } else { if (out) { fprintf(out, "error - unknown memversion\n"); } fclose(prcfile); return DEBUG_ERR; } fread(&scratchmemory[8], 1, prcstats.st_size, prcfile); fclose(prcfile); /* * fprintf(stderr, "D - setting exception flag\n"); * fflush(stderr); */ CPU_setexceptionflag(shptr, 32 + 0xF, 1); CPU_wait(shptr); /* * fprintf(stderr, "D - clearing exception flag\n"); * fflush(stderr); */ CPU_setexceptionflag(shptr, 32 + 0xF, 0); /* * fprintf(stderr, "D - Requesting cpuLoadApp..\n"); * fflush(stderr); */ shptr->CpuReq = cpuLoadApp; while (shptr->CpuState != cpuLoaded) { usleep(1000); } /* * fprintf(stderr, "D - cpuLoadApp done\n"); * fflush(stderr); */ { int ret_code; if (shptr->ErrNo == 0) { ret_code = DEBUG_OK; } else { ret_code = DEBUG_ERR; } shptr->CpuReq = cpuStart; return ret_code; }}/***************** * Start the cpu * *****************/int dbg_start(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ shptr->CpuReq = cpuStart; return DEBUG_OK;}/**************** * Stop the cpu * ****************/int dbg_stop(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ shptr->CpuReq = cpuStop; return DEBUG_OK;}/*************** * Show the PC * ***************/int dbg_pc(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ fprintf(out, "%08lx\n", (shptr->regs).pc + ((char *)(shptr->regs).pc_p - (char *)(shptr->regs).pc_oldp)); return DEBUG_OK;}/************************** * Turn logging on or off * **************************/int dbg_log(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ char *arg = strsep(&line, Delim); if (!strcmp(arg, "on")) { /* Turn logging on */ shptr->dolog = 1; return DEBUG_OK; } else if (!strcmp(arg, "off")) { /* Turn logging off */ shptr->dolog = 0; return DEBUG_OK; } else { fprintf(out, "Usage: %s on|off\n", cmd); return DEBUG_OK; }}/********************** * Quit the emulation * **********************/int dbg_quit(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ shptr->CpuReq = cpuExit; return DEBUG_OK;}int dbg_help(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr);/************************** * Command dispatch table * **************************/struct { char *name; int (*fun)(FILE *, FILE *, char *, char *, shared_img *shptr); char *help;} cmd_table[] = { {"help", dbg_help, ": Give brief help on commands"}, {"start", dbg_start, ": Start Cpu running"}, {"stop", dbg_stop, ": Stop Cpu running"}, {"pc", dbg_pc, ": Show current PC"}, {"log", dbg_log, "on|off : turn logging on or off"}, {"load", dbg_loadapp, " <prcfile>: load application"}, {"quit", dbg_quit, ": Quit XCopilot"}, {NULL, NULL, NULL}};int dbg_help(FILE *out, FILE *in, char *cmd, char *line, shared_img *shptr){ int i; fprintf(out, "Command Summary\n"); for (i = 0; cmd_table[i].name; i++) { fprintf(out, "%s\t %s\n", cmd_table[i].name, cmd_table[i].help); } return DEBUG_OK;}#include <netinet/in.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#define MaxHostNameLen 20/* * Establish a socket and listen for connections * Accept a connection on the socket * s and return the file descriptor * or -1 if failed */int dbg_connect(unsigned short portnum){ char host_name[MaxHostNameLen]; struct sockaddr_in saddr; struct hostent *host_ptr; int sid; int one = 1; /* * Clear out socket structure */ memset(&saddr, 0, sizeof(struct sockaddr_in));#if 0 /* * Get host name */ gethostname(host_name, MaxHostNameLen - 1); host_ptr = gethostbyname(host_name); if (host_ptr == NULL) { return -1; }#endif /* * Set socket address: host and port * and create socket */ saddr.sin_family = AF_INET; // host_ptr->h_addrtype; saddr.sin_port = htons(portnum); sid = socket(AF_INET, SOCK_STREAM, 0); if (sid < 0) { return -1; } /* * Bind socket to address */ setsockopt(sid, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)); if (bind(sid, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) < 0) { close(sid); return -1; } /* * Listen for at most 1 connection */ listen(sid, 1); return accept(sid, NULL, NULL);}/***************************************************************************** * * * Main debugger loop * * * *****************************************************************************/void pdebug_loop(char *args, int portnum, shared_img *shptr){ char buff[MaxLineLen], *line, *word; int i, status; int fid; FILE *in, *out;#ifdef DISABLE_AUTORUN shptr->CpuReq = cpuStop;#endif /* * Establish a socket */ fid = dbg_connect(portnum); if (fid < 0) { perror("dbg_connect"); return; } in = fdopen(fid, "r"); if (in == NULL) { perror("fdopen in"); return; } out = fdopen(fid, "w"); if (out == NULL) { perror("fdopen out"); return; } do { fprintf(out, "command > "); fflush(out); if (!(line = fgets(buff, MaxLineLen, in))) { break; } if (!(word = strsep(&line, Delim))) { continue; } i = 0; while (cmd_table[i].name && strcmp(word, cmd_table[i].name) != 0) { i++; } if (cmd_table[i].name) { status = (cmd_table[i].fun)(out, in, word, line, shptr); } else if (*word != '\0' && *word != ';') { fprintf(out, "E - debug - unrecognized command \"%s\"\n", word); } } while (shptr->CpuReq != cpuExit);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -