|
|
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; // マスク
75: };
76: };
77:
78: uint32 matched {}; // 成立回数 (積算)
79:
80: // skip はユーザ指定値。ただし
81: // -1 なら常にスキップ、つまりブレークせずカウントのみ行う、
82: // 0 ならスキップなし、つまり成立ごとにブレーク(これがデフォルト)、
83: // n(>0) なら n 回の成立をスキップし、(n+1) 回目でブレークの意。
84: int32 skip {}; // スキップ回数 (ユーザ指定値)
85: int32 skipremain {}; // 残りスキップ回数 (0 で成立)
86: };
87: static const int MAX_BREAKPOINTS = 8;
88:
89: // ステップ実行種別
90: enum StepType {
91: None, // なし
92: Count, // 命令数指定
93: CountSkipSub, // 命令数指定 (サブルーチンをスキップ)
94: StepOut, // ステップアウト
95: Addr, // アドレス指定
96: Time, // 時間指定
97: };
98:
99: public:
100: Debugger();
101: ~Debugger() override;
102:
103: bool Create() override;
104: void SetLogLevel(int) override;
105: bool Init() override;
106: void ThreadRun() override;
107: void Terminate() override;
108:
109: void ExecMain() { Exec(md_mpu.get()); }
110: void ExecXP() { Exec(md_xp.get()); }
111: void NotifyExceptionMain(int vector);
112: void NotifyExceptionXP(int vector);
113:
114: // MPU トレースが必要なら true を返す
115: bool IsTrace() const;
116:
117: // FILE コールバック
118: int ReadFunc(char *, int);
119: int WriteFunc(const char *, int);
120:
121: private:
122: void Close();
123: void RxCallback();
124: void AcceptCallback();
125: void Input(int);
126: void EnterPrompt();
127: void LeavePrompt(bool trace);
128: void PrintPrompt();
129:
130: void Exec(DebuggerMD *);
131: CmdAct Command();
132: bool CheckAllBreakpoints(DebuggerMD *);
133: bool CheckBreakpointInst(breakpoint_t&);
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();
161: CmdAct cmd_q();
162: CmdAct cmd_reset();
163: CmdAct cmd_s();
164: CmdAct cmd_st();
165: CmdAct cmd_so();
166: CmdAct cmd_sot();
167: CmdAct cmd_show();
168: CmdAct cmd_t();
169: CmdAct cmd_xp();
170: CmdAct cmd_z();
171:
172: bool Check(DebuggerMD *);
173: DebuggerMD *ParseCPU(const std::string&) const;
174: int AddBreakpoint(const breakpoint_t&, const std::string&);
175: void RecalcInstMask();
1.1.1.10! root 176: bool GetAddr(busaddr *addr, bool);
! 177: CmdAct cmd_d_common(busaddr access_mode);
1.1.1.9 root 178: CmdAct cmd_hist_common(BranchHistory& hist);
1.1.1.10! root 179: CmdAct cmd_m_common(busaddr access_mode);
1.1.1.9 root 180: CmdAct cmd_n_common(bool);
181: CmdAct cmd_s_common(bool);
182: CmdAct cmd_so_common(bool);
183: bool ParseVector(DebuggerMD *, const char *arg, uint32 *valp);
184: bool ParseVerbHex(const char *arg, uint32 *valp);
185: bool ParseAddr(const char *arg, uint32_t *addrp);
186: bool ParseTime(const char *arg, uint64 *timep);
187: void SetNBreakpoint();
188: void ChangeMD(DebuggerMD *);
189: void ResetStickyAddr();
190:
191: static const HelpMessages HelpListMain;
192: static const HelpMessages HelpListBreakpoints;
193: static const HelpMessages HelpDetails;
194: CmdAct ShowHelpList(const HelpMessages& msgs);
195:
196: // 個別ヘルプメッセージを出力用に置換
197: std::string HelpConvert(const std::string& msg);
198:
199: // モニタを更新して表示
200: void ShowMonitor(Monitor& monitor);
201: // テキストスクリーンを表示
202: void ShowTextScreen(TextScreen& screen);
203:
204: // 機種依存部分
205: std::unique_ptr<DebuggerMD> md_mpu /*{}*/; // メイン
206: std::unique_ptr<DebuggerMD> md_xp /*{}*/; // XP
207: // 現行
208: DebuggerMD *curmd {};
209:
210: std::mutex mtx {};
211: // このスレッドへのリクエスト
212: std::condition_variable cv_request {};
213: uint32 request {};
214: // コマンドモード(プロンプト)なら true
215: std::condition_variable cv_prompt {};
216: bool prompt_released {};
217:
218: bool is_prompt {};
219:
220: // コンソール
221: std::unique_ptr<HostCOMDevice> hostcom /*{}*/;
222: FILE *cons {};
223:
224: const char *prompt {}; // プロンプト文字列
225: std::string cmdbuf {}; // 現在のコマンドライン
226: std::string last_cmdbuf {}; // 直前のコマンドライン
227: std::vector<std::string> args {};
228:
229: uint32 pc {};
230: std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
231: uint32 bi_inst {};
232: int bi_inst_bytes {};
233: int bi_need_bytes {};
234: uint64 ct_timespan {};
1.1.1.10! root 235: busaddr d_last_addr {};
! 236: busaddr m_last_addr {};
1.1.1.9 root 237: StepType step_type {}; // ステップ実行種別
238: DebuggerMD *step_md {}; // ステップ実行中の CPU
239: uint32 step_count {};
240: uint64 step_addr {};
241: uint64 step_time {};
242: DebuggerMD *t_enable {};
243: uint32 t_count {};
244:
245: // 一度VMを実行して再びプロンプトに来たら true
246: bool is_continued {};
247:
248: // MPU を一時停止するとき true (ワンショット)
249: bool is_pause {};
250:
251: // プロンプトで表示するレジスタ群
252: std::vector<std::string> disp_regs {};
253:
254: // ブレークポイント到達メッセージ
255: // (コンソールが獲得できるまで保留しておくため)
256: std::string bpointmsg {};
257:
258: // ブレークポイントモニタ
259: DECLARE_MONITOR_CALLBACK(MonitorUpdateBpoint);
260: Monitor bpoint_monitor { this };
261:
262: // 逆アセンブルとメモリダンプモニタ
263: std::array<std::unique_ptr<MemdumpMonitor>, MAX_MEMDUMP_MONITOR>
264: memdump_monitor /*{}*/;
265: std::array<std::unique_ptr<MemdumpMonitor>, MAX_XPMEMDUMP_MONITOR>
266: xpmemdump_monitor /*{}*/;
267:
268: // ベクタテーブル
269: std::unique_ptr<VectorTable> pVectorTable /*{}*/;
270:
271: Syncer *syncer {};
272:
273: static std::vector<cmddef_t> cmdtable;
274: };
275:
276: static inline Debugger *GetDebugger() {
277: return Object::GetObject<Debugger>(OBJ_DEBUGGER);
278: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.