⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debug.c

📁 A Zilog Z80 simulator, debugger and profiler tailored for ZX Spectrum development (but generic enoug
💻 C
字号:
#include "debug.h"#include "cpu.h"#include "tokens.h"#include "watch.h"#include "parser.h"#include "sizes.h"#include "symbols.h"#include <stdio.h>#include <string.h>#define CMD_INFO     1#define CMD_RUN      2#define CMD_STEP     3#define CMD_STEPI    4#define CMD_WATCH    5#define CMD_EVAL     6#define CMD_DISASM   7#define CMD_STACK    8#define CMD_IRQ      9#define CMD_NAME    10#define CMD_QUIT    11#define CMD_ENABLE  12#define CMD_DISABLE 13#define CMD_HELP    14#define CMD_INFO_WATCHPOINTS 100#define CMD_INFO_WARRANTY    101#define LEX_QUIT             "quit"#define LEX_HELP             "help"#define LEX_INFO             "info"#define LEX_RUN              "run"#define LEX_STEP             "step"#define LEX_STEPI            "stepi"#define LEX_WATCH            "watch"#define LEX_EVAL             "eval"#define LEX_DISASM           "disasm"#define LEX_STACK            "stack"#define LEX_IRQ              "irq"#define LEX_NAME             "name"#define LEX_ENABLE           "enable"#define LEX_DISABLE          "disable"#define LEX_INFO_WATCHPOINTS "watchpoints"#define LEX_INFO_WARRANTY    "warranty"static tokens* DebugTokens;static logic StopAtNextCLine=FALSE;void PrintValue(FILE* Handle, word Value) {	if(Value>9) fprintf(Handle, "0x%04x", Value);	else fprintf(Handle, "%d", Value);}void Input(const char* Prompt, char* UserString) {	fprintf(stdout, "%s", Prompt);	fflush(stdout);	fgets(UserString, MAX_STRING, stdin);	UserString[strlen(UserString)-1]='\0';}void InitDebugger() {	InitParser();	InitWatchpoints();	DebugTokens=CreateTokenTable();	CreateToken(DebugTokens, " ", 0);	// Debugger commands	CreateToken(DebugTokens, LEX_QUIT, CMD_QUIT);	CreateToken(DebugTokens, LEX_HELP, CMD_HELP);	CreateToken(DebugTokens, LEX_INFO, CMD_INFO);	CreateToken(DebugTokens, LEX_RUN, CMD_RUN);	CreateToken(DebugTokens, LEX_STEP, CMD_STEP);	CreateToken(DebugTokens, LEX_STEPI, CMD_STEPI);	CreateToken(DebugTokens, LEX_WATCH, CMD_WATCH);	CreateToken(DebugTokens, LEX_EVAL, CMD_EVAL);	CreateToken(DebugTokens, LEX_DISASM, CMD_DISASM);	CreateToken(DebugTokens, LEX_STACK, CMD_STACK);	CreateToken(DebugTokens, LEX_IRQ, CMD_IRQ);	CreateToken(DebugTokens, LEX_NAME, CMD_NAME);	CreateToken(DebugTokens, LEX_ENABLE, CMD_ENABLE);	CreateToken(DebugTokens, LEX_DISABLE, CMD_DISABLE);	// Command parameters	CreateToken(DebugTokens, LEX_INFO_WATCHPOINTS, CMD_INFO_WATCHPOINTS);	CreateToken(DebugTokens, LEX_INFO_WARRANTY, CMD_INFO_WARRANTY);}logic BreakRequest() {	static logic OldLineSkipped=FALSE;	if(StopAtNextCLine) {		if(OldLineSkipped && HasSource(GetRegister(REG_PC))) {			StopAtNextCLine=FALSE;			OldLineSkipped=FALSE;			return TRUE;		} else OldLineSkipped=TRUE;	}	if(CheckWatchpoints()!=NULL) return TRUE;	return FALSE;}void ExecuteInfoWarranty() {	fprintf(stdout, "                            NO WARRANTY\n\n");	fprintf(stdout, "  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");	fprintf(stdout, "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n");	fprintf(stdout, "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");	fprintf(stdout, "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");	fprintf(stdout, "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");	fprintf(stdout, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n");	fprintf(stdout, "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n");	fprintf(stdout, "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");	fprintf(stdout, "REPAIR OR CORRECTION.\n");	fprintf(stdout, "  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");	fprintf(stdout, "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");	fprintf(stdout, "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");	fprintf(stdout, "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");	fprintf(stdout, "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");	fprintf(stdout, "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");	fprintf(stdout, "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");	fprintf(stdout, "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");	fprintf(stdout, "POSSIBILITY OF SUCH DAMAGES.\n");}void ExecuteInfo(const char* Parameters) {	char Lexeme[MAX_STRING];	int Token;	const char* OtherSymbols=Parameters;	while((Token=ExtractToken(DebugTokens, &OtherSymbols, Lexeme, TRUE))==0) {		if(strlen(Lexeme)==0) {			fprintf(stdout, "Info on what?\n");			return;		}	}	switch(Token) {	case CMD_INFO_WATCHPOINTS:		ListWatchpoints(stdout);		break;	case CMD_INFO_WARRANTY:		ExecuteInfoWarranty();		break;	default:		fprintf(stdout, "No info about '%s'\n", Lexeme);	}}void ExecuteWatch(const char* Parameters) {	operation* Watchpoint;	Watchpoint=ParseExpression(Parameters);	if(Watchpoint==NULL) {		fprintf(stdout, "A parse error in expression.\n");	} else {		char Expression[MAX_STRING];		StringifyExpression(Watchpoint, Expression);		fprintf(stdout, "Watchpoint %d: %s (currently 0x%04x)\n", AddWatchpoint(Watchpoint, TRUE), Expression, EvaluateExpression(Watchpoint));	}}void ExecuteEval(const char* Parameters) {	operation* Representation;        Representation=ParseExpression(Parameters);        if(Representation==NULL) {                fprintf(stdout, "A parse error in expression.\n");        } else {                char Expression[MAX_STRING];                StringifyExpression(Representation, Expression);                fprintf(stdout, "%s evaluates to ", Expression);		PrintValue(stdout, EvaluateExpression(Representation)); fprintf(stdout, "\n");                FreeExpression(Representation);        }}void ExecuteDisasm(const char* Parameters) {	char StartStr[MAX_STRING], EndStr[MAX_STRING];	const char *OtherTokens=Parameters;	if(!ExtractFreeform(DebugTokens, &OtherTokens, StartStr) || !ExtractFreeform(DebugTokens, &OtherTokens, EndStr)) {                fprintf(stdout, "Syntax: disasm <start-addr> [<end-addr>]\n");		return;	} else {	        word Start=strtol(StartStr, NULL, 0);        	word End=strtol(EndStr, NULL, 0);        	word i;        	if(strlen(EndStr)==0) End=Start+1;        	i=Start; while(i<=End) {			char Mnemonic[MAX_STRING];        		fprintf(stdout, "%04x: ", i);                        Disassemble(&i, Mnemonic);                        fprintf(stdout, "%s\n", Mnemonic);                }	}}void ExecuteStack(const char* Parameters) {	char DepthStr[MAX_NAME];        word Start, End;        word i;        Start=GetRegister(REG_SP);        if(!ExtractFreeform(DebugTokens, &Parameters, DepthStr)) End=Start+3; else End=Start+strtol(DepthStr, NULL, 0);        fprintf(stdout, "%04x: %04x  <- SP\n", Start, GetMemoryWord(Start));        for(i=Start+1; i<End; i+=2) {                fprintf(stdout, "%04x: %04x\n", i, GetMemoryWord(i));        }}void ExecuteName(const char* Parameters) {	char AddrStr[MAX_STRING];        char Symbol[MAX_NAME];	if(!ExtractFreeform(DebugTokens, &Parameters, AddrStr)) {                fprintf(stdout, "Syntax: name <addr>\n");        } else {                word Addr=strtol(AddrStr, NULL, 0);                if(LookupSymbol(Addr, Symbol)) {                        fprintf(stdout, "Symbol: '%s'\n", Symbol);                } else if(SearchSymbol(Addr, Symbol)) {                        fprintf(stdout, "Nearest symbol: '%s'\n", Symbol);                } else fprintf(stdout, "No symbol found\n");        }}void ExecuteEnable(const char* Parameters) {	char NumberStr[MAX_STRING];	while(ExtractFreeform(DebugTokens, &Parameters, NumberStr)) {		short Number=strtol(NumberStr, NULL, 0);		if(ExistsWatchpoint(Number)) {			WatchpointActivation(Number, TRUE);		} else {			fprintf(stdout, "Watchpoing %d does not exist\n", Number);		}	}}void ExecuteDisable(const char* Parameters) {	char NumberStr[MAX_STRING];        while(ExtractFreeform(DebugTokens, &Parameters, NumberStr)) {                short Number=strtol(NumberStr, NULL, 0);                if(ExistsWatchpoint(Number)) {                        WatchpointActivation(Number, FALSE);                } else {                        fprintf(stdout, "Watchpoing %d does not exist\n", Number);                }        }}logic Debugger() {	watchpoint* Watch;	while(NULL!=(Watch=CheckWatchpoints())) {		char Expression[MAX_STRING];                StringifyExpression(Watch->Trigger, Expression);                fprintf(stdout, "\nBREAK: %s has changed value\n", Expression);                fprintf(stdout, "Old value: ");		PrintValue(stdout, Watch->StableValue); fprintf(stdout, "\n");                fprintf(stdout, "New value: ");		PrintValue(stdout, Watch->StableValue=EvaluateExpression(Watch->Trigger)); fprintf(stdout, "\n");	}	{                source SourceSpec=SearchSource(GetRegister(REG_PC));                if(SourceSpec.File!=NULL) {                        char SourceLine[MAX_STRING];                        ReadFileLine(SourceSpec.File, SourceSpec.Line, SourceLine);                        fprintf(stdout, "%d %s\n", SourceSpec.Line, SourceLine);                }	}	for(;;) {		char CommandLine[MAX_STRING];		char Token[MAX_STRING];		const char* OtherTokens=CommandLine;		Input("$ ", CommandLine);		switch(ExtractToken(DebugTokens, &OtherTokens, Token, TRUE)) {		case CMD_QUIT:			exit(0);		case CMD_HELP:			fprintf(stdout, "\t%s\n", LEX_QUIT);			fprintf(stdout, "\t%s\n", LEX_INFO);			fprintf(stdout, "\t%s\n", LEX_RUN);			fprintf(stdout, "\t%s\n", LEX_STEP);			fprintf(stdout, "\t%s\n", LEX_STEPI);			fprintf(stdout, "\t%s\n", LEX_WATCH);			fprintf(stdout, "\t%s\n", LEX_EVAL);			fprintf(stdout, "\t%s\n", LEX_DISASM);			fprintf(stdout, "\t%s\n", LEX_STACK);			fprintf(stdout, "\t%s\n", LEX_IRQ);			fprintf(stdout, "\t%s\n", LEX_NAME);			fprintf(stdout, "\t%s\n", LEX_ENABLE);			fprintf(stdout, "\t%s\n", LEX_DISABLE);			fprintf(stdout, "\tinfo %s\n", LEX_INFO_WATCHPOINTS);			fprintf(stdout, "\tinfo %s\n", LEX_INFO_WARRANTY);			break;		case CMD_RUN:			fprintf(stdout, "Resuming execution\n\n");			return FALSE;		case CMD_STEP:			return TRUE;		case CMD_STEPI:			StopAtNextCLine=TRUE;			return FALSE;		case CMD_INFO:			ExecuteInfo(OtherTokens);			break;		case CMD_WATCH:			ExecuteWatch(OtherTokens);              		break;		case CMD_EVAL:			ExecuteEval(OtherTokens);			break;		case CMD_DISASM:			ExecuteDisasm(OtherTokens);			break;		case CMD_STACK:			ExecuteStack(OtherTokens);			break;		case CMD_NAME:			ExecuteName(OtherTokens);			break;		case CMD_ENABLE:			ExecuteEnable(OtherTokens);			break;		case CMD_DISABLE:			ExecuteDisable(OtherTokens);			break;		default:			fprintf(stdout, "Unknown command.\n");		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -