From: j8takagi Date: Thu, 28 Jun 2018 12:37:26 +0000 (+0900) Subject: ブレークポイント機能の修正 X-Git-Tag: v0.4p1~2 X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?p=YACASL2.git;a=commitdiff_plain;h=c2820a4ee2f34c794268b5a61d3223f1c270d39c ブレークポイント機能の修正 --- diff --git a/include/debugger.h b/include/debugger.h index d35615f..ccd6ca7 100644 --- a/include/debugger.h +++ b/include/debugger.h @@ -1,13 +1,20 @@ #ifndef DEBBUGER_INCLUDE #define DEBBUGER_INCLUDE +#include +#include +#include +#include "hash.h" +#include "cmem.h" +#include "cerr.h" +#include "exec.h" #include "word.h" /** * @brief デバッガー */ enum { - DBARGSIZE = 2, /**<デバッガー引数の最大数 */ + DBARGSIZE = 3, /**<デバッガー引数の最大数 */ }; /** @@ -22,17 +29,17 @@ typedef struct { * @brief デバッガー命令行を表すデータ型 */ typedef struct { - char *dbcmd; /**<コマンド */ - DBARGS *dbargs; /**<引数 */ + char *cmd; /**<コマンド */ + DBARGS *args; /**<引数 */ } DBCMDLINE; /** * @brief ブレークポイント表を表すデータ型 */ -typedef struct _BPSTAB { - struct _BPSTAB *next; /**<リスト次項目へのポインタ */ +typedef struct _BPSLIST { + struct _BPSLIST *next; /**<リスト次項目へのポインタ */ WORD adr; /**<アドレス */ -} BPSTAB; +} BPSLIST; /** * ブレークポイント表のサイズ @@ -42,9 +49,18 @@ enum { }; enum { - DBINSIZE = 8 /**<デバッガーの、入力領域 */ + DBINSIZE = 40 /**<デバッガーの、入力領域 */ }; +/** + * @brief アドレスのハッシュ値を返す + * + * @return ハッシュ値 + * + * @param adr アドレス + */ +unsigned adrhash(WORD adr); + /** * @brief 文字列から、デバッガーの引数を取得する * @@ -91,4 +107,22 @@ bool addbps(WORD adr); */ bool delbps(WORD adr); +/** + * @brief ブレークポイント表からすべてのアドレスを削除する + * + * @return なし + * + * @param なし + */ +void resetbps(); + +/** + * @brief ブレークポイント表を開放する + * + * @return なし + * + * @param なし + */ +void freebps(); + #endif /* end of DEBBUGER_INCLUDE */ diff --git a/include/exec.h b/include/exec.h index e73db1c..f081089 100644 --- a/include/exec.h +++ b/include/exec.h @@ -18,11 +18,11 @@ typedef struct { bool trace; /**<レジストリの内容をステップごとに表示する場合はtrue */ bool logical; /**<レジストリの内容を論理値(0から65535)で表示する場合はtrue */ bool dump; /**<メモリの内容をステップごとに表示する場合はtrue */ - bool debugger; /**<デバッガーモードの場合はtrue */ + bool step; /**<ステップ実行の場合はtrue */ } EXECMODE; /** - * @brief 実行モード: trace, logical, dump, debugger + * @brief 実行モード: trace, logical, dump, step */ extern EXECMODE execmode; diff --git a/src/casl2.c b/src/casl2.c index 89333d5..216496e 100644 --- a/src/casl2.c +++ b/src/casl2.c @@ -166,7 +166,7 @@ int main(int argc, char *argv[]) execmode.dump = true; break; case 'b': - execmode.debugger = true; + execmode.step = true; break; case 'M': memsize = atoi(optarg); diff --git a/src/comet2.c b/src/comet2.c index 1309df9..2422c00 100644 --- a/src/comet2.c +++ b/src/comet2.c @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) execmode.dump = true; break; case 'b': - execmode.debugger = true; + execmode.step = true; break; case 'M': memsize = atoi(optarg); diff --git a/src/debugger.c b/src/debugger.c index d86cc66..b84a013 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -1,30 +1,9 @@ -#include -#include -#include #include "debugger.h" -#include "hash.h" -#include "cmem.h" -#include "cerr.h" -#include "exec.h" - -/** - * アドレスに対応するハッシュ値を返す - * - * @return ハッシュ値 - * - * @param adr アドレス - */ -unsigned adrhash(WORD adr); - -/** - * @brief ブレークポイント数 - */ -static int bpscnt = 0; /** * @brief ブレークポイント表 */ -static BPSTAB *bps[BPSTABSIZE]; +static BPSLIST *bps[BPSTABSIZE]; /** * @brief ブレークポイントのエラー @@ -33,17 +12,10 @@ static CERR cerr_bps[] = { { 101, "break point already defined" }, { 102, "break point table is full" }, { 103, "break point not found" }, + { 104, "break point address not set" }, + { 105, "illegal break point address" }, }; -/** - * @brief アドレスのハッシュ値を返す - * - * @return ハッシュ値 - * - * @param adr アドレス - */ -unsigned adrhash(WORD adr); - /** * @brief ブレークポイントのエラーをエラーリストに追加する * @@ -71,7 +43,7 @@ void addcerrlist_bps() bool getbps(WORD adr) { - BPSTAB *p; + BPSLIST *p; for(p = bps[adrhash(adr)]; p != NULL; p = p->next) { if(p->adr == adr) { @@ -83,20 +55,18 @@ bool getbps(WORD adr) bool addbps(WORD adr) { - BPSTAB *p; + BPSLIST *p; unsigned h; - /* 登録されたラベルを検索。すでに登録されている場合はエラー発生 */ + /* 登録されたラベルを検索。すでに登録されている場合は終了 */ if(getbps(adr) == true) { - setcerr(101, ""); /* breakpoint already defined */ + fprintf(stderr, "%04X: Breakpoint is already defined.\n", adr); return false; } /* メモリを確保 */ - p = malloc_chk(sizeof(BPSTAB), "bps.next"); + p = malloc_chk(sizeof(BPSLIST), "bps.next"); /* アドレスを設定 */ p->adr = adr; - /* ブレークポイント数を設定 */ - bpscnt++; /* ハッシュ表へ追加 */ p->next = bps[h = adrhash(adr)]; bps[h] = p; @@ -105,50 +75,67 @@ bool addbps(WORD adr) bool delbps(WORD adr) { - BPSTAB *p, *q; + BPSLIST *p, *q; unsigned h; + bool res = false; p = bps[h = adrhash(adr)]; - if(p->adr == adr && p->next != NULL) { - bps[h] = p->next; - FREE(p); - return true; - } else { - for(; p != NULL; p = p->next) { - if(p->adr == adr) { - q = p->next; - p->next = q->next; + if(p != NULL) { + if(p->adr == adr) { + if(p->next == NULL) { + FREE(bps[h]); + } else { + bps[h] = p->next; FREE(p); - return true; + } + res = true; + } else { + for(; p->next != NULL; p = p->next) { + q = p->next; + if(q->adr == adr) { + p->next = q->next; + FREE(q); + res = true; + break; + } } } } - return false; + return res; } -void printbps() +void listbps() { - int i; - BPSTAB *p; + int i, cnt = 0; + BPSLIST *p; - fprintf(stdout, "breakpoints list\n"); + fprintf(stdout, "List of breakpoints\n"); for(i = 0; i < BPSTABSIZE; i++) { for(p = bps[i]; p != NULL; p = p->next) { fprintf(stdout, "#%04X\n", p->adr); + cnt++; } } + if(cnt == 0) { + fprintf(stdout, "(No breakpoints.)\n"); + } +} + +void freebpslist(BPSLIST *head) +{ + BPSLIST *p, *q; + for(p = head; p != NULL; p = q) { + q = p->next; + FREE(p); + } } void freebps() { int i; - BPSTAB *p, *q; - for(i = 0; i < BPSTABSIZE; i++) { - for(p = bps[i]; p != NULL; p = q) { - q = p->next; - FREE(p); - } + freebpslist(bps[i]); + bps[i] = NULL; } } @@ -170,7 +157,7 @@ DBARGS *dbargstok(const char *str) sepp = r + strcspn(r, " "); sepc = *sepp; *sepp = '\0'; - args->argv[(++args->argc)-1] = strdup_chk(q, "args.argv[]"); + args->argv[++(args->argc)-1] = strdup_chk(q, "args.argv[]"); q = r = sepp + 1; } while(sepc == ' '); FREE(p); @@ -179,36 +166,29 @@ DBARGS *dbargstok(const char *str) DBCMDLINE *dblinetok(const char *line) { - char *tokens, *p, *sepp; + char *tokens, *p; + long l; DBCMDLINE *dbcmdl = NULL; - if(*line == '\0') { + if(*line == '\n' || *line == '\0') { return NULL; } - tokens = strdup_chk(line, "tokens"); - p = tokens; + p = tokens = strdup_chk(line, "tokens"); dbcmdl = malloc_chk(sizeof(DBCMDLINE), "dbcmdl"); - /* コマンドと引数の取得 */ - if(*p == '\n' || *p == '\0') { /* コマンドがない場合は、終了 */ - dbcmdl->dbcmd = '\0'; + /* コマンドの取得 */ + dbcmdl->cmd = malloc_chk((l = strcspn(p, " \t\n")) + 1, "dbcmdl.cmd"); + strncpy(dbcmdl->cmd, p, l); + /* コマンドと引数の間の空白をスキップ */ + p += l; + while(*p == ' ' || *p == '\t') { + p++; + } + /* 引数として、改行までの文字列を取得 */ + if((l = strcspn(p, "\n")) > 0) { + dbcmdl->args = dbargstok(p); } else { - /* コマンドの取得 */ - sepp = p + strcspn(p, " \t\n"); - *sepp = '\0'; - dbcmdl->dbcmd = strdup_chk(p, "dbcmdl.dbcmd"); - p = sepp + 1; - /* コマンドと引数の間の空白をスキップ */ - while(*p == ' ' || *p == '\t') { - p++; - } - /* 改行までの文字列を取得 */ - if((sepp = p + strcspn(p, "\n")) > p) { - *sepp = '\0'; - dbcmdl->dbargs = dbargstok(p); - } else { - dbcmdl->dbargs = malloc_chk(sizeof(DBARGS), "dbcmdl.dbargs"); - dbcmdl->dbargs->argc = 0; - } + dbcmdl->args = malloc_chk(sizeof(DBARGS), "dbcmdl.args"); + dbcmdl->args->argc = 0; } FREE(tokens); return dbcmdl; @@ -217,6 +197,9 @@ DBCMDLINE *dblinetok(const char *line) bool stracmp(char *str1, int str2c, char *str2v[]) { int i; + if(str1 == NULL) { + return false; + } for(i = 0; i < str2c; i++) { if(strcmp(str1, str2v[i]) == 0) { return true; @@ -225,56 +208,128 @@ bool stracmp(char *str1, int str2c, char *str2v[]) return false; } -void debugger() +void db_break(int argc, char *argv[]) { - char *buf = malloc_chk(DBINSIZE + 1, "debugger.buf"), *cmd; - DBCMDLINE *dbcmdl = malloc_chk(sizeof(DBCMDLINE), "dbcmdl"); - DBARGS *arg; - for( ; ;) { - fprintf(stdout, "COMET II (Type ? for help) > "); - fgets(buf, DBINSIZE, stdin); - dbcmdl = dblinetok(buf); - cmd = dbcmdl->dbcmd; - arg = dbcmdl->dbargs; - if(*buf == '\n' || stracmp(cmd, 2, (char* []){"s", "step"})) { - break; - } else if(stracmp(cmd, 2, (char* []){"c", "continue"})) { - execmode.debugger = false; - break; - } else if(stracmp(cmd, 2, (char* []){"t", "trace"})) { - if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"a", "auto"})) { - execmode.logical = false; - execmode.trace = true; - } else if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"no", "noauto"})) { - execmode.trace = false; - } else { - fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr); - dspregister(); + WORD w; + if(stracmp(argv[0], 2, (char* []){"l", "list"})) { + listbps(); + } else if(stracmp(argv[0], 2, (char* []){"r", "reset"})) { + freebps(); + fprintf(stdout, "All breakpoints are deleted.\n"); + } else { + if(argc > 1) { + if((w = nh2word(argv[1])) == 0x0) { + fprintf(stderr, "%s: address error\n", argv[1]); } - } else if(stracmp(cmd, 2, (char* []){"T", "tracelogical"})) { - if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"a", "auto"})) { - execmode.logical = true; - execmode.trace = true; - } else if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"no", "noauto"})) { - execmode.trace = false; + } + if(stracmp(argv[0], 2, (char* []){"a", "add"})) { + if(addbps(w) == true) { + fprintf(stdout, "#%04X: breakpoint added\n", w); } else { - fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr); - dspregister(); + fprintf(stdout, "No breakpoint added\n"); } - } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) { - if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"a", "auto"})) { - execmode.dump = true; - } else if(arg->argc > 0 && stracmp(arg->argv[0], 2, (char* []){"no", "noauto"})) { - execmode.dump = false; + } else if(stracmp(argv[0], 2, (char* []){"d", "del"})) { + if(delbps(w) == true) { + fprintf(stdout, "#%04X: breakpoint deleted\n", w); } else { - dumpmemory(); + fprintf(stdout, "No breakpoint deleted\n"); } - } else if(*buf == '?') { - fprintf(stdout, "s (default) -- Step by step running your program until next interaction.\n"); - fprintf(stdout, "c -- Continue running your program.\n"); - fprintf(stdout, "t -- Display CPU register.\n"); - fprintf(stdout, "d -- Display memory dump.\n"); - break; + } else if(stracmp(argv[0], 3, (char* []){"?", "h", "help"})) { + fprintf(stdout, "breakpoint manipulate:\n"); + fprintf(stdout, " b[reak] a[dd]
\n"); + fprintf(stdout, " b[reak] d[el]
\n"); + fprintf(stdout, " b[reak] l[ist]\n"); + fprintf(stdout, " b[reak] r[eset]\n"); + } else { + fprintf(stderr, "%s: Not breakpoint manipulate command. see `b ?'.\n", argv[0]); + } + } +} + +bool debuggercmd(char *cmd, DBARGS *args) +{ + bool next = false; + if(stracmp(cmd, 2, (char* []){"s", "step"})) { + execmode.step = true; + next = true; + } else if(stracmp(cmd, 2, (char* []){"b", "break"})) { + db_break(args->argc, args->argv); + } else if(stracmp(cmd, 2, (char* []){"c", "continue"})) { + execmode.step = false; + next = true; + } else if(stracmp(cmd, 2, (char* []){"t", "trace"})) { + if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) { + execmode.logical = false; + execmode.trace = true; + } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) { + execmode.trace = false; + } else { + fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr); + dspregister(); + } + } else if(stracmp(cmd, 2, (char* []){"T", "tracelogical"})) { + if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) { + execmode.logical = true; + execmode.trace = true; + } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) { + execmode.trace = false; + } else { + fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr); + dspregister(); + } + } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) { + if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) { + execmode.dump = true; + } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) { + execmode.dump = false; + } else { + dumpmemory(); } + } else if(stracmp(cmd, 3, (char* []){"?", "h", "help"})) { + fprintf(stdout, "b[reak] -- Manipulate Breakpoints. Details in `b ?'.\n"); + fprintf(stdout, "s[tep] -- Step by step running your program until next interaction.\n"); + fprintf(stdout, "c[ontinue] -- Continue running your program.\n"); + fprintf(stdout, "t[race] -- Display CPU register. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n"); + fprintf(stdout, "d[ump] -- Display memory dump. `d[ump] a[uto]/n[oauto]' set auto/noauto display.\n"); + fprintf(stdout, "?/h[elp] -- Display this help.\n"); + } + return next; +} + +void free_dbcmdline(DBCMDLINE *dbcmdl) +{ + int i; + assert(dbcmdl != NULL); + if(dbcmdl->args != NULL) { + for(i = 0; i < dbcmdl->args->argc; i++) { + FREE(dbcmdl->args->argv[i]); + } + FREE(dbcmdl->args); + } + if(dbcmdl->cmd != NULL) { + FREE(dbcmdl->cmd); + } + if(dbcmdl != NULL) { + FREE(dbcmdl); } } + +void debugger() +{ + char *buf, *p; + DBCMDLINE *dbcmdl; + bool next = false; + do { + fprintf(stdout, "COMET II (Type ? for help) > "); + buf = malloc_chk(DBINSIZE + 1, "debugger.buf"); + fgets(buf, DBINSIZE, stdin); + if((p = strchr(buf, '\n')) != NULL) { + *p = '\0'; + } + if((dbcmdl = dblinetok(buf)) != NULL) { + next = debuggercmd(dbcmdl->cmd, dbcmdl->args); + free_dbcmdline(dbcmdl); + } + FREE(buf); + } while(next == false); +} diff --git a/src/exec.c b/src/exec.c index 2a71610..b920fb1 100644 --- a/src/exec.c +++ b/src/exec.c @@ -110,7 +110,7 @@ static CERR cerr_load[] = { }; /** - * @brief 実行モード: trace, logical, dump, debugger + * @brief 実行モード: trace, logical, dump, step */ EXECMODE execmode = {false, false, false, false}; @@ -812,7 +812,7 @@ void exec() fprintf(stdout, "\n"); } /* デバッガーモードの場合、デバッガーを起動 */ - if(execmode.debugger == true || getbps(sys->cpu->pr) == true) { + if(execmode.step == true || getbps(sys->cpu->pr) == true) { debugger(); } /* プログラムレジスタをチェック */ @@ -850,6 +850,7 @@ void exec() } while(clock_end - clock_begin < CLOCKS_PER_SEC / sys->clocks); } execfin: + freebps(); free_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を解放 */ if(cerr->num > 0) { fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg);