Annotation of nono/debugger/debugger_private.h, revision 1.1.1.8

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #pragma once
                      8: 
1.1.1.3   root        9: #include "branchhistory.h"
1.1       root       10: #include "bus.h"
                     11: #include "cvprompt.h"
1.1.1.7   root       12: #include "monitor.h"
1.1       root       13: #include "textscreen.h"
1.1.1.2   root       14: #include <array>
                     15: 
                     16: using ConstStringPair = std::pair<const std::string, const std::string>;
                     17: using HelpMessages = std::vector<ConstStringPair>;
1.1       root       18: 
                     19: // 諸情報付きのアドレス
1.1.1.5   root       20: class saddr_t
1.1       root       21: {
1.1.1.5   root       22:  public:
                     23:        // コンストラクタ
                     24:        saddr_t() { }
                     25: 
                     26:        saddr_t(uint32 addr_, bool super_)
                     27:                : saddr_t(addr_, super_, false) { }
                     28: 
                     29:        saddr_t(uint32 addr_, bool super_, bool data_) {
                     30:                Set(addr_, super_, data_);
                     31:        }
                     32:        // コピーコンストラクタ
                     33:        saddr_t(const saddr_t& rhs) {
                     34:                Set(rhs);
                     35:        }
                     36:        // 代入演算子
                     37:        saddr_t& operator=(const saddr_t& rhs) {
                     38:                Set(rhs);
                     39:                return *this;
                     40:        }
                     41: 
                     42:        // 代入演算子 (uint32 を代入するとアドレスだけ差し替える)
                     43:        saddr_t& operator=(uint32 rhs) {
                     44:                SetAddr(rhs);
                     45:                return *this;
                     46:        }
                     47: 
                     48:        // 代入
                     49:        void Set(uint32 addr_, bool super_, bool data_) {
                     50:                addr  = addr_;
                     51:                super = super_;
                     52:                data  = data_;
                     53:        }
                     54: 
                     55:        uint32 GetAddr() const          { return addr; }
                     56:        bool IsSuper() const            { return super; }
                     57:        bool IsData()  const            { return data; }
                     58:        void SetAddr(uint32 addr_)      { addr  = addr_; }
                     59:        void SetSuper(bool super_)      { super = super_; }
                     60:        void SetData(bool data_)        { data  = data_; }
                     61: 
                     62:        // (uint32)saddr でアドレスだけ取り出せると楽
                     63:        explicit operator uint32() const { return GetAddr(); }
                     64: 
                     65:        // saddr += n でアドレス進められると楽
                     66:        uint32 operator+=(uint32 val) {
                     67:                addr += val;
                     68:                return addr;
                     69:        }
                     70:        // saddr++ でアドレス進められると楽
                     71:        void operator++(int n) {
                     72:                addr++;
                     73:        }
1.1       root       74: 
1.1.1.5   root       75:  private:
                     76:        void Set(const saddr_t& rhs) {
                     77:                addr  = rhs.addr;
                     78:                super = rhs.super;
                     79:                data  = rhs.data;
1.1       root       80:        }
1.1.1.5   root       81: 
                     82:        uint32 addr {};         // アドレス (32bit)
                     83:        bool super {};          // スーパーバイザアクセスなら true
                     84:        bool data  {};          // データ空間アクセスなら true
1.1       root       85: };
                     86: 
1.1.1.5   root       87: enum class MemoryMode : bool
                     88: {
                     89:        Logical  = false,
                     90:        Physical = true,
1.1       root       91: };
                     92: 
1.1.1.5   root       93: enum class MMULookupMode : bool
                     94: {
                     95:        False = false,
                     96:        True  = true,
                     97:        // MemoryMode::Physical ならこの項は意味を持たないので、
                     98:        // True でも False でもないと言いたい。
                     99:        None  = false,
                    100: };
                    101: 
                    102: // saddr_t の後で Debugger の前...
                    103: #include "debugger_memory.h"
                    104: 
1.1       root      105: class Console;
                    106: class DebuggerMD;
                    107: class Disasm;
                    108: 
1.1.1.7   root      109: class Debugger final : public Object
1.1       root      110: {
1.1.1.7   root      111:        using inherited = Object;
1.1       root      112:        friend class DebuggerMD_m680x0;
                    113:        friend class DebuggerMD_m88xx0;
1.1.1.5   root      114:  public:
                    115:        enum class Arch {
                    116:                M680x0,
                    117:                M88xx0,
                    118:        };
                    119: 
1.1       root      120:  private:
                    121:        // 型
1.1.1.2   root      122:        enum CommandAction {
                    123:                Stay,           // デバッガプロンプトに留まる
                    124:                Leave,          // デバッガプロンプトを抜けて VM を実行する
                    125:                Quit,           // デバッガとの接続を終了する
                    126:        };
                    127:        using cmdfunc_t = void (Debugger::*)();
1.1       root      128:        typedef struct {
                    129:                const char *name;
                    130:                cmdfunc_t func;
1.1.1.2   root      131:                CommandAction action;
1.1       root      132:        } cmddef_t;
                    133: 
1.1.1.3   root      134:        // ブレークポイント種別
                    135:        enum BreakpointType {
                    136:                Unused = 0,
                    137:                Address,                // このアドレスに来る直前
                    138:                Memory,                 // このアドレスをアクセスした直後
                    139:                Exception,              // この例外を検出した直後
                    140:                Instruction,    // この命令を実行する直前
                    141:        };
                    142: 
1.1       root      143:        // ブレークポイント
                    144:        typedef struct {
1.1.1.3   root      145:                BreakpointType type {}; // 種別
                    146:                // 種別ごとのパラメータ
                    147:                union {
                    148:                        uint32 addr {};         // ターゲットアドレス (Address/Memory)
                    149:                        struct {
                    150:                                int vec1;               // ベクタ番号 (開始)
                    151:                                int vec2;               // ベクタ番号 (終了)
                    152:                        };
                    153:                        struct {
                    154:                                uint32 inst;    // 命令ワード
                    155:                                uint32 mask;    // マスク
                    156:                        };
                    157:                };
                    158: 
                    159:                uint32 matched {};              // 成立回数 (積算)
                    160: 
                    161:                // skip はユーザ指定値。ただし
                    162:                // -1 なら常にスキップ、つまりブレークせずカウントのみ行う、
                    163:                // 0 ならスキップなし、つまり成立ごとにブレーク(これがデフォルト)、
                    164:                // n(>0) なら n 回の成立をスキップし、(n+1) 回目でブレークの意。
                    165:                int32 skip {};                  // スキップ回数 (ユーザ指定値)
                    166:                int32 skipremain {};    // 残りスキップ回数 (0 で成立)
1.1       root      167:        } breakpoint_t;
                    168:        static const int MAX_BREAKPOINTS = 8;
                    169: 
                    170:  public:
                    171:        Debugger();
1.1.1.2   root      172:        ~Debugger() { }
1.1       root      173: 
                    174:        void Init();
                    175:        void ThreadRun();
                    176:        bool Check();
1.1.1.3   root      177:        void NotifyException(int vector);
                    178: 
1.1.1.7   root      179:        // メモリダンプモニタ
                    180:        // GUI 用 (show コマンドでも見れるけど)
                    181:        std::array<Monitor, MAX_MEMDUMP_MONITOR> memdump_monitor;
                    182: 
                    183:        // m/M コマンド用のメモリダンプモニタ
                    184:        Monitor m_monitor { this };
1.1       root      185: 
                    186:  private:
1.1.1.2   root      187:        bool Accept();
                    188:        bool AcquirePrompt();
                    189:        CommandAction MainLoop();
1.1.1.3   root      190:        bool CheckAllBreakpoints();
                    191:        bool CheckBreakpointInst(breakpoint_t&);
1.1.1.2   root      192:        void ParseCmdbuf();
1.1       root      193:        // コマンド名は大文字小文字を区別する関係でスネークスタイル。
                    194:        void cmd_b();
1.1.1.3   root      195:        void cmd_bi();
                    196:        void cmd_bm();
                    197:        void cmd_bv();
1.1       root      198:        void cmd_b_list();
1.1.1.3   root      199:        void cmd_b_set(BreakpointType);
1.1.1.8 ! root      200:        void cmd_b_delete();
1.1       root      201:        void cmd_brhist();
                    202:        void cmd_bx();
                    203:        void cmd_c();
                    204:        void cmd_d();
                    205:        void cmd_dt();
                    206:        void cmd_D();
1.1.1.4   root      207:        void cmd_disp();
1.1.1.3   root      208:        void cmd_exhist();
1.1       root      209:        void cmd_h();
1.1.1.4   root      210:        void cmd_hb();
                    211:        void cmd_hr();
1.1       root      212:        void cmd_L();
                    213:        void cmd_m();
                    214:        void cmd_mt();
                    215:        void cmd_M();
                    216:        void cmd_minus();
                    217:        void cmd_n();
1.1.1.4   root      218:        void cmd_nt();
1.1       root      219:        void cmd_q();
1.1.1.4   root      220:        void cmd_reset();
1.1       root      221:        void cmd_s();
1.1.1.4   root      222:        void cmd_st();
1.1       root      223:        void cmd_so();
1.1.1.4   root      224:        void cmd_sot();
1.1       root      225:        void cmd_show();
                    226:        void cmd_t();
                    227: 
1.1.1.3   root      228:        int AddBreakpoint(const breakpoint_t&);
                    229:        void RecalcInstMask();
1.1.1.5   root      230:        bool GetAddr(saddr_t *addr, bool);
                    231:        void cmd_d_common(MemoryMode access_mode, MMULookupMode lookup_mode);
1.1.1.7   root      232:        void cmd_hist_common(BranchHistory& hist);
1.1.1.5   root      233:        void cmd_m_common(MemoryMode access_mode, MMULookupMode lookup_mode);
1.1.1.4   root      234:        void cmd_n_common(bool);
                    235:        void cmd_s_common(bool);
                    236:        void cmd_so_common(bool);
1.1.1.3   root      237:        bool ParseVerbHex(const char *arg, uint32 *valp);
1.1       root      238:        bool ParseAddr(const char *arg, uint32_t *addrp);
1.1.1.4   root      239:        void SetNBreakpoint();
1.1       root      240: 
1.1.1.5   root      241:        static const HelpMessages HelpListMain;
                    242:        static const HelpMessages HelpListBreakpoints;
1.1.1.4   root      243:        static const HelpMessages HelpDetails;
1.1.1.5   root      244:        void ShowHelpList(const HelpMessages& msgs);
1.1.1.4   root      245: 
                    246:        // 個別ヘルプメッセージを出力用に置換
                    247:        std::string HelpConvert(const std::string& msg);
1.1.1.2   root      248: 
                    249:        // モニターを更新して表示
1.1.1.7   root      250:        void ShowMonitor(Monitor& monitor);
1.1.1.2   root      251:        // テキストスクリーンを表示
                    252:        void ShowTextScreen(TextScreen& screen);
1.1       root      253: 
1.1.1.4   root      254:        DebuggerMD *md {};                      // 機種依存部分
1.1       root      255: 
1.1.1.4   root      256:        Console *cons {};                       // 入出力
                    257:        const char *prompt {};          // プロンプト文字列
1.1       root      258:        std::string cmdbuf {};          // 現在のコマンドライン
                    259:        std::string last_cmdbuf {};     // 直前のコマンドライン
1.1.1.2   root      260:        std::vector<std::string> args {};
1.1       root      261: 
1.1.1.4   root      262:        uint32 pc {};
1.1       root      263:        std::vector<uint8> ir {};       // この後実行する命令のバイナリ列
1.1.1.2   root      264:        std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
1.1.1.4   root      265:        bool bc_enable {};
                    266:        uint32 bc_addr {};
                    267:        uint32 bi_inst {};
                    268:        int bi_inst_bytes {};
                    269:        int bi_need_bytes {};
1.1.1.3   root      270:        int bv_vector = -1;
1.1.1.5   root      271:        saddr_t d_last_addr {};
                    272:        saddr_t m_last_addr {};
1.1.1.4   root      273:        bool n_enable {};
                    274:        uint32 n_breakaddr {};
                    275:        uint32 n_count {};
                    276:        bool s_enable {};
                    277:        uint32 s_count {};
                    278:        bool so_enable {};
                    279:        bool t_enable {};
                    280:        uint32 t_count {};
1.1       root      281: 
                    282:        // 一度VMを実行して再びプロンプトに来たら true
1.1.1.4   root      283:        bool is_continued {};
                    284: 
                    285:        // プロンプトで表示するレジスタ群
                    286:        std::vector<std::string> disp_regs {};
1.1       root      287: 
1.1.1.6   root      288:        // ブレークポイント到達メッセージ
                    289:        // (コンソールが獲得できるまで保留しておくため)
                    290:        std::string bpointmsg {};
                    291: 
1.1.1.7   root      292:        // ブレークポイントモニタ
                    293:        DECLARE_MONITOR_CALLBACK(MonitorUpdateBpoint);
                    294:        Monitor bpoint_monitor { this };
                    295: 
                    296:        // メモリダンプモニタ
                    297:        DECLARE_MONITOR_CALLBACK(MonitorUpdateMemdump);
                    298: 
1.1.1.2   root      299:        static std::vector<cmddef_t> cmdtable;
1.1       root      300: };
                    301: 
                    302: // デバッガの CPU 依存部分
                    303: class DebuggerMD
                    304: {
                    305:  public:
1.1.1.5   root      306:        DebuggerMD(Debugger *parent_, Debugger::Arch arch_) {
1.1.1.4   root      307:                parent = parent_;
1.1.1.5   root      308:                arch = arch_;
1.1       root      309:        }
1.1.1.5   root      310:        virtual ~DebuggerMD();
1.1       root      311: 
                    312:        // CPU のリクエストフラグに flag を立てる
                    313:        virtual void ReqSet(uint32 flag) = 0;
                    314:        // CPU のリクエストフラグから flag を落とす
                    315:        virtual void ReqClr(uint32 flag) = 0;
                    316: 
                    317:        // 特権モードなら true を返す
                    318:        virtual bool IsSuper() const = 0;
                    319:        // MMU が有効なら true を返す
                    320:        virtual bool MMUEnabled() const = 0;
                    321: 
                    322:        // アドレス変換をする。
                    323:        // MMUEnabled() が true であることは呼び出し側が確認すること。
1.1.1.5   root      324:        // lookup が true ならテーブルサーチまで行う。
1.1       root      325:        // 変換できなければ (uint64)-1 を返す。
1.1.1.5   root      326:        virtual uint64 TranslateAddr(saddr_t laddr, bool lookup) const = 0;
1.1       root      327: 
                    328:        // 現在の命令先頭アドレスを返す
                    329:        virtual uint32 GetPC() const = 0;
                    330: 
                    331:        // ステップアウトを設定する
                    332:        virtual void SetStepOut() = 0;
                    333:        // ステップアウトなら true を返す
                    334:        virtual bool IsStepOut() const = 0;
                    335: 
1.1.1.4   root      336:        // この命令がステップイン出来るなら true を返す (cmd_n 用)
1.1.1.5   root      337:        virtual bool IsOpStepIn(DebuggerMemoryStream& mem) = 0;
1.1.1.4   root      338: 
1.1       root      339:        // name で示されるのレジスタの値を返す。
                    340:        // メモリダンプで指定するケースを想定しているので、明らかにアドレスでは
                    341:        // ないレジスタは含まなくてよい (m680x0 の SR など)。ただし Dn は含めて
                    342:        // よい。また m680x0 の SRP/CRP は下位32ビットでよい。
                    343:        // name が正しくない場合は (uint64)-1 を返す。
                    344:        virtual uint64 GetRegAddr(const char *name) const = 0;
                    345: 
                    346:        // 現在のレジスタセットを内部にバックアップする
                    347:        virtual void BackupRegs() = 0;
                    348: 
1.1.1.2   root      349:        // レジスタ表示系のコマンドを実行。処理すれば true を返す。
                    350:        virtual bool ShowRegister(Console *cons,
                    351:                const std::vector<std::string>& args) = 0;
1.1.1.5   root      352:        // レジスタ表示系コマンドのヘルプ一覧を取得
                    353:        virtual const HelpMessages& GetHelpListReg() const = 0;
1.1.1.2   root      354:        // レジスタ表示系コマンドのヘルプメッセージを取得
1.1.1.5   root      355:        virtual const HelpMessages& GetHelpReg() const = 0;
1.1.1.2   root      356: 
1.1.1.3   root      357:        // ブランチ履歴・例外履歴(オブジェクト)を取得
                    358:        virtual BranchHistory& GetBrHist() const = 0;
                    359:        virtual BranchHistory& GetExHist() const = 0;
1.1       root      360: 
                    361:        // 直近の命令でアクセスした laddr が一致したら true を返す
                    362:        // 1 命令で複数にアクセスする場合を考慮して、md 側で判断する
                    363:        virtual bool CheckLEA(uint32 laddr) = 0;
                    364: 
                    365:        // 逆アセンブル。
1.1.1.5   root      366:        // mem.laddr の位置の命令を一つ逆アセンブルする。
1.1       root      367:        // 成功すれば true を返し、失敗すれば(?) false を返す。
                    368:        // 成功した場合 mnemonic に逆アセンブルした文字列が、
                    369:        // bin にこの命令のバイナリ列が格納されている。
                    370:        // mnemonic は単純に命令部分のみ、16進ダンプや付随情報は含まない。
                    371:        // bin はメモリイメージのバイト順で格納すること。
1.1.1.5   root      372:        virtual bool Disassemble(DebuggerMemoryStream& mem,
1.1       root      373:                std::string& mnemonic, std::vector<uint8>& bin) = 0;
                    374: 
                    375:        // 逆アセンブルをフォーマット。
                    376:        // オフライン版は逆アセンブルウィンドウなど、
                    377:        // オンライン版(Live) はデバッガプロンプトで表示するやつ。
                    378:        virtual std::string FormatDisasm(const std::string& mnemonic,
                    379:                const std::vector<uint8>& bin) = 0;
                    380:        virtual std::string FormatDisasmLive(const std::string& mnemonic,
                    381:                const std::vector<uint8>& bin) = 0;
                    382: 
1.1.1.4   root      383:        // 例外のベクタ番号から名前を取得。
                    384:        virtual const char *GetExceptionName(int vector) const = 0;
                    385: 
1.1.1.5   root      386:        // 機種
                    387:        Debugger::Arch arch {};
                    388: 
1.1.1.3   root      389:        // ベクタ番号の最大値 (+1)
1.1.1.4   root      390:        int vector_max {};
                    391:        // 最短の1命令のバイト数
                    392:        uint inst_bytes {};
                    393:        // 命令が固定長ならそのバイト数、可変長なら 0
                    394:        uint inst_bytes_fixed {};
1.1.1.3   root      395: 
1.1       root      396:  protected:
1.1.1.4   root      397:        Debugger *parent {};    // 親クラス
1.1       root      398: };
                    399: 
                    400: #define NORM           "\x1b[0m"
                    401: #define BOLD           "\x1b[1m"
                    402: #define BOLDIF(n)      ((n) ? BOLD : "")

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.