|
|
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();
1.1.1.12 root 123: void RxCallback(uint32);
124: void AcceptCallback(uint32);
1.1.1.9 root 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 *);
1.1.1.13! root 173: bool ParseOptBreakAddr(const std::string&);
! 174: bool ParseOptBreakInst(const std::string&);
! 175: bool ParseOptBreakVector(const std::string&);
! 176: bool IsCPUStr(const std::string&) const;
1.1.1.9 root 177: DebuggerMD *ParseCPU(const std::string&) const;
1.1.1.13! root 178: int AddBreakInst(const std::string& cpustr, const std::string& inststr,
! 179: const std::string& skipstr, std::string *errstr);
! 180: int AddBreakVector(const std::string& cpustr, const std::string& vecstr,
! 181: const std::string& skipstr, std::string *errstr);
! 182: int AddBreakpoint(const breakpoint_t&);
1.1.1.9 root 183: void RecalcInstMask();
1.1.1.10 root 184: bool GetAddr(busaddr *addr, bool);
185: CmdAct cmd_d_common(busaddr access_mode);
1.1.1.9 root 186: CmdAct cmd_hist_common(BranchHistory& hist);
1.1.1.10 root 187: CmdAct cmd_m_common(busaddr access_mode);
1.1.1.9 root 188: CmdAct cmd_n_common(bool);
189: CmdAct cmd_s_common(bool);
190: CmdAct cmd_so_common(bool);
191: bool ParseVector(DebuggerMD *, const char *arg, uint32 *valp);
192: bool ParseVerbHex(const char *arg, uint32 *valp);
193: bool ParseAddr(const char *arg, uint32_t *addrp);
194: bool ParseTime(const char *arg, uint64 *timep);
195: void SetNBreakpoint();
196: void ChangeMD(DebuggerMD *);
197: void ResetStickyAddr();
198:
199: static const HelpMessages HelpListMain;
200: static const HelpMessages HelpListBreakpoints;
201: static const HelpMessages HelpDetails;
202: CmdAct ShowHelpList(const HelpMessages& msgs);
203:
204: // 個別ヘルプメッセージを出力用に置換
205: std::string HelpConvert(const std::string& msg);
206:
207: // モニタを更新して表示
1.1.1.11 root 208: void ShowMonitor(Monitor *monitor);
1.1.1.9 root 209: // テキストスクリーンを表示
210: void ShowTextScreen(TextScreen& screen);
211:
212: // 機種依存部分
213: std::unique_ptr<DebuggerMD> md_mpu /*{}*/; // メイン
214: std::unique_ptr<DebuggerMD> md_xp /*{}*/; // XP
215: // 現行
216: DebuggerMD *curmd {};
217:
218: std::mutex mtx {};
219: // このスレッドへのリクエスト
220: std::condition_variable cv_request {};
221: uint32 request {};
222: // コマンドモード(プロンプト)なら true
223: std::condition_variable cv_prompt {};
224: bool prompt_released {};
225:
226: bool is_prompt {};
227:
228: // コンソール
229: std::unique_ptr<HostCOMDevice> hostcom /*{}*/;
230: FILE *cons {};
231:
232: const char *prompt {}; // プロンプト文字列
233: std::string cmdbuf {}; // 現在のコマンドライン
234: std::string last_cmdbuf {}; // 直前のコマンドライン
1.1.1.13! root 235: std::vector<std::string> cmdargs {};
1.1.1.9 root 236:
237: uint32 pc {};
238: std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
239: uint32 bi_inst {};
240: int bi_inst_bytes {};
241: int bi_need_bytes {};
242: uint64 ct_timespan {};
1.1.1.10 root 243: busaddr d_last_addr {};
244: busaddr m_last_addr {};
1.1.1.9 root 245: StepType step_type {}; // ステップ実行種別
246: DebuggerMD *step_md {}; // ステップ実行中の CPU
247: uint32 step_count {};
248: uint64 step_addr {};
249: uint64 step_time {};
250: DebuggerMD *t_enable {};
251: uint32 t_count {};
252:
253: // 一度VMを実行して再びプロンプトに来たら true
254: bool is_continued {};
255:
256: // MPU を一時停止するとき true (ワンショット)
257: bool is_pause {};
258:
259: // プロンプトで表示するレジスタ群
260: std::vector<std::string> disp_regs {};
261:
262: // ブレークポイント到達メッセージ
263: // (コンソールが獲得できるまで保留しておくため)
264: std::string bpointmsg {};
265:
266: // ブレークポイントモニタ
267: DECLARE_MONITOR_CALLBACK(MonitorUpdateBpoint);
1.1.1.11 root 268: Monitor *bpoint_monitor {};
1.1.1.9 root 269:
270: // 逆アセンブルとメモリダンプモニタ
271: std::array<std::unique_ptr<MemdumpMonitor>, MAX_MEMDUMP_MONITOR>
272: memdump_monitor /*{}*/;
273: std::array<std::unique_ptr<MemdumpMonitor>, MAX_XPMEMDUMP_MONITOR>
274: xpmemdump_monitor /*{}*/;
275:
276: // ベクタテーブル
277: std::unique_ptr<VectorTable> pVectorTable /*{}*/;
278:
279: Syncer *syncer {};
280:
281: static std::vector<cmddef_t> cmdtable;
282: };
283:
284: static inline Debugger *GetDebugger() {
285: return Object::GetObject<Debugger>(OBJ_DEBUGGER);
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.