|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.7 root 7: //
8: // デバッガ (外部用)
9: //
10:
1.1 root 11: #pragma once
12:
1.1.1.9 root 13: #include "debugger_defs.h"
1.1.1.10 root 14: #include "bus.h"
1.1.1.6 root 15: #include "monitor.h"
1.1.1.9 root 16: #include "textscreen.h"
17: #include "thread.h"
18: #include <array>
19: #include <condition_variable>
20: #include <mutex>
1.1.1.4 root 21:
1.1.1.9 root 22: class BranchHistory;
23: class HostCOMDevice;
24: class MemdumpMonitor;
25: class Syncer;
26: class VectorTable;
1.1.1.6 root 27:
1.1.1.9 root 28: class Debugger : public ThreadDevice
29: {
30: using inherited = ThreadDevice;
31: friend class DebuggerMD_m680x0;
32: friend class DebuggerMD_m88xx0;
33:
34: private:
35: // リクエストフラグ
36: static const uint32 REQUEST_EXIT = 0x0001; // 終了
37: static const uint32 REQUEST_RXCHAR = 0x0002; // 1文字受信
38: static const uint32 REQUEST_ACCEPT = 0x0004; // 着信通知
39: static const uint32 REQUEST_PROMPT = 0x0008; // プロンプト要求
40:
41: // コマンド
42: enum CmdAct {
43: Stay, // デバッガプロンプトに留まる
44: Leave, // デバッガプロンプトを抜けて VM を実行する
45: Quit, // デバッガとの接続を終了する
46: };
47: struct cmddef_t {
48: const char *name;
49: CmdAct (Debugger::*func)();
50: };
51:
52: // ブレークポイント種別
53: enum BreakpointType {
54: Unused = 0,
55: Address, // このアドレスに来る直前
56: Memory, // このアドレスをアクセスした直後
57: Exception, // この例外を検出した直後
58: Instruction, // この命令を実行する直前
59: };
60:
61: // ブレークポイント
62: struct breakpoint_t {
63: DebuggerMD *md {}; // CPU
64: BreakpointType type {}; // 種別
65: // 種別ごとのパラメータ
66: union {
67: uint32 addr {}; // ターゲットアドレス (Address/Memory)
68: struct {
69: int vec1; // ベクタ番号 (開始)
70: int vec2; // ベクタ番号 (終了)
71: };
72: struct {
73: uint32 inst; // 命令ワード
74: uint32 mask; // マスク
1.1.1.14! root 75: int instbytes; // 命令バイト数
1.1.1.9 root 76: };
77: };
78:
79: uint32 matched {}; // 成立回数 (積算)
80:
81: // skip はユーザ指定値。ただし
82: // -1 なら常にスキップ、つまりブレークせずカウントのみ行う、
83: // 0 ならスキップなし、つまり成立ごとにブレーク(これがデフォルト)、
84: // n(>0) なら n 回の成立をスキップし、(n+1) 回目でブレークの意。
85: int32 skip {}; // スキップ回数 (ユーザ指定値)
86: int32 skipremain {}; // 残りスキップ回数 (0 で成立)
87: };
88: static const int MAX_BREAKPOINTS = 8;
89:
90: // ステップ実行種別
91: enum StepType {
92: None, // なし
93: Count, // 命令数指定
94: CountSkipSub, // 命令数指定 (サブルーチンをスキップ)
95: StepOut, // ステップアウト
96: Addr, // アドレス指定
97: Time, // 時間指定
98: };
99:
100: public:
101: Debugger();
102: ~Debugger() override;
103:
104: bool Create() override;
105: void SetLogLevel(int) override;
106: bool Init() override;
107: void ThreadRun() override;
108: void Terminate() override;
109:
110: void ExecMain() { Exec(md_mpu.get()); }
111: void ExecXP() { Exec(md_xp.get()); }
112:
113: // MPU トレースが必要なら true を返す
114: bool IsTrace() const;
115:
116: // FILE コールバック
117: int ReadFunc(char *, int);
118: int WriteFunc(const char *, int);
119:
120: private:
121: void Close();
1.1.1.12 root 122: void RxCallback(uint32);
123: void AcceptCallback(uint32);
1.1.1.9 root 124: void Input(int);
125: void EnterPrompt();
1.1.1.14! root 126: void QuitPrompt();
1.1.1.9 root 127: void LeavePrompt(bool trace);
128: void PrintPrompt();
129:
130: void Exec(DebuggerMD *);
131: CmdAct Command();
132: bool CheckAllBreakpoints(DebuggerMD *);
1.1.1.14! root 133: uint64 ReadBreakpointInst(breakpoint_t&);
1.1.1.9 root 134: void ParseCmdbuf();
135: // コマンド名は大文字小文字を区別する関係でスネークスタイル。
136: CmdAct cmd_b();
137: CmdAct cmd_bi();
138: CmdAct cmd_bm();
139: CmdAct cmd_bv();
140: CmdAct cmd_b_list();
141: CmdAct cmd_b_set(BreakpointType);
142: CmdAct cmd_b_delete();
143: CmdAct cmd_brhist();
144: CmdAct cmd_bx();
145: CmdAct cmd_c();
146: CmdAct cmd_ct();
147: CmdAct cmd_d();
148: CmdAct cmd_D();
149: CmdAct cmd_disp();
150: CmdAct cmd_exhist();
151: CmdAct cmd_h();
152: CmdAct cmd_hb();
153: CmdAct cmd_hr();
154: CmdAct cmd_L();
155: CmdAct cmd_m();
156: CmdAct cmd_mpu();
157: CmdAct cmd_M();
158: CmdAct cmd_minus();
159: CmdAct cmd_n();
160: CmdAct cmd_nt();
1.1.1.14! root 161: CmdAct cmd_pe();
! 162: CmdAct cmd_pf();
1.1.1.9 root 163: CmdAct cmd_q();
164: CmdAct cmd_reset();
165: CmdAct cmd_s();
166: CmdAct cmd_st();
167: CmdAct cmd_so();
168: CmdAct cmd_sot();
169: CmdAct cmd_show();
170: CmdAct cmd_t();
171: CmdAct cmd_xp();
172: CmdAct cmd_z();
173:
174: bool Check(DebuggerMD *);
1.1.1.13 root 175: bool ParseOptBreakAddr(const std::string&);
176: bool ParseOptBreakInst(const std::string&);
177: bool ParseOptBreakVector(const std::string&);
178: bool IsCPUStr(const std::string&) const;
1.1.1.9 root 179: DebuggerMD *ParseCPU(const std::string&) const;
1.1.1.13 root 180: int AddBreakInst(const std::string& cpustr, const std::string& inststr,
181: const std::string& skipstr, std::string *errstr);
182: int AddBreakVector(const std::string& cpustr, const std::string& vecstr,
183: const std::string& skipstr, std::string *errstr);
184: int AddBreakpoint(const breakpoint_t&);
1.1.1.10 root 185: bool GetAddr(busaddr *addr, bool);
186: CmdAct cmd_d_common(busaddr access_mode);
1.1.1.9 root 187: CmdAct cmd_hist_common(BranchHistory& hist);
1.1.1.10 root 188: CmdAct cmd_m_common(busaddr access_mode);
1.1.1.9 root 189: CmdAct cmd_n_common(bool);
190: CmdAct cmd_s_common(bool);
191: CmdAct cmd_so_common(bool);
192: bool ParseVector(DebuggerMD *, const char *arg, uint32 *valp);
193: bool ParseVerbHex(const char *arg, uint32 *valp);
194: bool ParseAddr(const char *arg, uint32_t *addrp);
195: bool ParseTime(const char *arg, uint64 *timep);
196: void SetNBreakpoint();
197: void ChangeMD(DebuggerMD *);
198: void ResetStickyAddr();
199:
200: static const HelpMessages HelpListMain;
201: static const HelpMessages HelpListBreakpoints;
202: static const HelpMessages HelpDetails;
203: CmdAct ShowHelpList(const HelpMessages& msgs);
204:
205: // 個別ヘルプメッセージを出力用に置換
206: std::string HelpConvert(const std::string& msg);
207:
208: // モニタを更新して表示
1.1.1.11 root 209: void ShowMonitor(Monitor *monitor);
1.1.1.9 root 210: // テキストスクリーンを表示
211: void ShowTextScreen(TextScreen& screen);
212:
213: // 機種依存部分
214: std::unique_ptr<DebuggerMD> md_mpu /*{}*/; // メイン
215: std::unique_ptr<DebuggerMD> md_xp /*{}*/; // XP
216: // 現行
217: DebuggerMD *curmd {};
218:
219: std::mutex mtx {};
220: // このスレッドへのリクエスト
221: std::condition_variable cv_request {};
222: uint32 request {};
223: // コマンドモード(プロンプト)なら true
224: std::condition_variable cv_prompt {};
225: bool prompt_released {};
226:
227: bool is_prompt {};
228:
229: // コンソール
230: std::unique_ptr<HostCOMDevice> hostcom /*{}*/;
231: FILE *cons {};
232:
233: const char *prompt {}; // プロンプト文字列
234: std::string cmdbuf {}; // 現在のコマンドライン
235: std::string last_cmdbuf {}; // 直前のコマンドライン
1.1.1.13 root 236: std::vector<std::string> cmdargs {};
1.1.1.9 root 237:
238: uint32 pc {};
239: std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
240: uint64 ct_timespan {};
1.1.1.10 root 241: busaddr d_last_addr {};
242: busaddr m_last_addr {};
1.1.1.9 root 243: StepType step_type {}; // ステップ実行種別
244: DebuggerMD *step_md {}; // ステップ実行中の CPU
245: uint32 step_count {};
246: uint64 step_addr {};
247: uint64 step_time {};
248: DebuggerMD *t_enable {};
249: uint32 t_count {};
250:
251: // 一度VMを実行して再びプロンプトに来たら true
252: bool is_continued {};
253:
254: // MPU を一時停止するとき true (ワンショット)
255: bool is_pause {};
256:
257: // プロンプトで表示するレジスタ群
258: std::vector<std::string> disp_regs {};
259:
260: // ブレークポイント到達メッセージ
261: // (コンソールが獲得できるまで保留しておくため)
262: std::string bpointmsg {};
263:
264: // ブレークポイントモニタ
1.1.1.14! root 265: DECLARE_MONITOR_SCREEN(MonitorScreenBpoint);
1.1.1.11 root 266: Monitor *bpoint_monitor {};
1.1.1.9 root 267:
268: // 逆アセンブルとメモリダンプモニタ
269: std::array<std::unique_ptr<MemdumpMonitor>, MAX_MEMDUMP_MONITOR>
270: memdump_monitor /*{}*/;
271: std::array<std::unique_ptr<MemdumpMonitor>, MAX_XPMEMDUMP_MONITOR>
272: xpmemdump_monitor /*{}*/;
273:
274: // ベクタテーブル
275: std::unique_ptr<VectorTable> pVectorTable /*{}*/;
276:
277: Syncer *syncer {};
278:
279: static std::vector<cmddef_t> cmdtable;
280: };
281:
1.1.1.14! root 282: inline Debugger *GetDebugger() {
1.1.1.9 root 283: return Object::GetObject<Debugger>(OBJ_DEBUGGER);
284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.