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

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       root      200:        void cmd_brhist();
                    201:        void cmd_bx();
                    202:        void cmd_c();
                    203:        void cmd_d();
                    204:        void cmd_dt();
                    205:        void cmd_D();
1.1.1.4   root      206:        void cmd_disp();
1.1.1.3   root      207:        void cmd_exhist();
1.1       root      208:        void cmd_h();
1.1.1.4   root      209:        void cmd_hb();
                    210:        void cmd_hr();
1.1       root      211:        void cmd_L();
                    212:        void cmd_m();
                    213:        void cmd_mt();
                    214:        void cmd_M();
                    215:        void cmd_minus();
                    216:        void cmd_n();
1.1.1.4   root      217:        void cmd_nt();
1.1       root      218:        void cmd_q();
1.1.1.4   root      219:        void cmd_reset();
1.1       root      220:        void cmd_s();
1.1.1.4   root      221:        void cmd_st();
1.1       root      222:        void cmd_so();
1.1.1.4   root      223:        void cmd_sot();
1.1       root      224:        void cmd_show();
                    225:        void cmd_t();
                    226: 
1.1.1.3   root      227:        int AddBreakpoint(const breakpoint_t&);
                    228:        void RecalcInstMask();
1.1.1.5   root      229:        bool GetAddr(saddr_t *addr, bool);
                    230:        void cmd_d_common(MemoryMode access_mode, MMULookupMode lookup_mode);
1.1.1.7 ! root      231:        void cmd_hist_common(BranchHistory& hist);
1.1.1.5   root      232:        void cmd_m_common(MemoryMode access_mode, MMULookupMode lookup_mode);
1.1.1.4   root      233:        void cmd_n_common(bool);
                    234:        void cmd_s_common(bool);
                    235:        void cmd_so_common(bool);
1.1.1.3   root      236:        bool ParseVerbHex(const char *arg, uint32 *valp);
1.1       root      237:        bool ParseAddr(const char *arg, uint32_t *addrp);
1.1.1.4   root      238:        void SetNBreakpoint();
1.1       root      239: 
1.1.1.5   root      240:        static const HelpMessages HelpListMain;
                    241:        static const HelpMessages HelpListBreakpoints;
1.1.1.4   root      242:        static const HelpMessages HelpDetails;
1.1.1.5   root      243:        void ShowHelpList(const HelpMessages& msgs);
1.1.1.4   root      244: 
                    245:        // 個別ヘルプメッセージを出力用に置換
                    246:        std::string HelpConvert(const std::string& msg);
1.1.1.2   root      247: 
                    248:        // モニターを更新して表示
1.1.1.7 ! root      249:        void ShowMonitor(Monitor& monitor);
1.1.1.2   root      250:        // テキストスクリーンを表示
                    251:        void ShowTextScreen(TextScreen& screen);
1.1       root      252: 
1.1.1.4   root      253:        DebuggerMD *md {};                      // 機種依存部分
1.1       root      254: 
1.1.1.4   root      255:        Console *cons {};                       // 入出力
                    256:        const char *prompt {};          // プロンプト文字列
1.1       root      257:        std::string cmdbuf {};          // 現在のコマンドライン
                    258:        std::string last_cmdbuf {};     // 直前のコマンドライン
1.1.1.2   root      259:        std::vector<std::string> args {};
1.1       root      260: 
1.1.1.4   root      261:        uint32 pc {};
1.1       root      262:        std::vector<uint8> ir {};       // この後実行する命令のバイナリ列
1.1.1.2   root      263:        std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
1.1.1.4   root      264:        bool bc_enable {};
                    265:        uint32 bc_addr {};
                    266:        uint32 bi_inst {};
                    267:        int bi_inst_bytes {};
                    268:        int bi_need_bytes {};
1.1.1.3   root      269:        int bv_vector = -1;
1.1.1.5   root      270:        saddr_t d_last_addr {};
                    271:        saddr_t m_last_addr {};
1.1.1.4   root      272:        bool n_enable {};
                    273:        uint32 n_breakaddr {};
                    274:        uint32 n_count {};
                    275:        bool s_enable {};
                    276:        uint32 s_count {};
                    277:        bool so_enable {};
                    278:        bool t_enable {};
                    279:        uint32 t_count {};
1.1       root      280: 
                    281:        // 一度VMを実行して再びプロンプトに来たら true
1.1.1.4   root      282:        bool is_continued {};
                    283: 
                    284:        // プロンプトで表示するレジスタ群
                    285:        std::vector<std::string> disp_regs {};
1.1       root      286: 
1.1.1.6   root      287:        // ブレークポイント到達メッセージ
                    288:        // (コンソールが獲得できるまで保留しておくため)
                    289:        std::string bpointmsg {};
                    290: 
1.1.1.7 ! root      291:        // ブレークポイントモニタ
        !           292:        DECLARE_MONITOR_CALLBACK(MonitorUpdateBpoint);
        !           293:        Monitor bpoint_monitor { this };
        !           294: 
        !           295:        // メモリダンプモニタ
        !           296:        DECLARE_MONITOR_CALLBACK(MonitorUpdateMemdump);
        !           297: 
1.1.1.2   root      298:        static std::vector<cmddef_t> cmdtable;
1.1       root      299: };
                    300: 
                    301: // デバッガの CPU 依存部分
                    302: class DebuggerMD
                    303: {
                    304:  public:
1.1.1.5   root      305:        DebuggerMD(Debugger *parent_, Debugger::Arch arch_) {
1.1.1.4   root      306:                parent = parent_;
1.1.1.5   root      307:                arch = arch_;
1.1       root      308:        }
1.1.1.5   root      309:        virtual ~DebuggerMD();
1.1       root      310: 
                    311:        // CPU のリクエストフラグに flag を立てる
                    312:        virtual void ReqSet(uint32 flag) = 0;
                    313:        // CPU のリクエストフラグから flag を落とす
                    314:        virtual void ReqClr(uint32 flag) = 0;
                    315: 
                    316:        // 特権モードなら true を返す
                    317:        virtual bool IsSuper() const = 0;
                    318:        // MMU が有効なら true を返す
                    319:        virtual bool MMUEnabled() const = 0;
                    320: 
                    321:        // アドレス変換をする。
                    322:        // MMUEnabled() が true であることは呼び出し側が確認すること。
1.1.1.5   root      323:        // lookup が true ならテーブルサーチまで行う。
1.1       root      324:        // 変換できなければ (uint64)-1 を返す。
1.1.1.5   root      325:        virtual uint64 TranslateAddr(saddr_t laddr, bool lookup) const = 0;
1.1       root      326: 
                    327:        // 現在の命令先頭アドレスを返す
                    328:        virtual uint32 GetPC() const = 0;
                    329: 
                    330:        // ステップアウトを設定する
                    331:        virtual void SetStepOut() = 0;
                    332:        // ステップアウトなら true を返す
                    333:        virtual bool IsStepOut() const = 0;
                    334: 
1.1.1.4   root      335:        // この命令がステップイン出来るなら true を返す (cmd_n 用)
1.1.1.5   root      336:        virtual bool IsOpStepIn(DebuggerMemoryStream& mem) = 0;
1.1.1.4   root      337: 
1.1       root      338:        // name で示されるのレジスタの値を返す。
                    339:        // メモリダンプで指定するケースを想定しているので、明らかにアドレスでは
                    340:        // ないレジスタは含まなくてよい (m680x0 の SR など)。ただし Dn は含めて
                    341:        // よい。また m680x0 の SRP/CRP は下位32ビットでよい。
                    342:        // name が正しくない場合は (uint64)-1 を返す。
                    343:        virtual uint64 GetRegAddr(const char *name) const = 0;
                    344: 
                    345:        // 現在のレジスタセットを内部にバックアップする
                    346:        virtual void BackupRegs() = 0;
                    347: 
1.1.1.2   root      348:        // レジスタ表示系のコマンドを実行。処理すれば true を返す。
                    349:        virtual bool ShowRegister(Console *cons,
                    350:                const std::vector<std::string>& args) = 0;
1.1.1.5   root      351:        // レジスタ表示系コマンドのヘルプ一覧を取得
                    352:        virtual const HelpMessages& GetHelpListReg() const = 0;
1.1.1.2   root      353:        // レジスタ表示系コマンドのヘルプメッセージを取得
1.1.1.5   root      354:        virtual const HelpMessages& GetHelpReg() const = 0;
1.1.1.2   root      355: 
1.1.1.3   root      356:        // ブランチ履歴・例外履歴(オブジェクト)を取得
                    357:        virtual BranchHistory& GetBrHist() const = 0;
                    358:        virtual BranchHistory& GetExHist() const = 0;
1.1       root      359: 
                    360:        // 直近の命令でアクセスした laddr が一致したら true を返す
                    361:        // 1 命令で複数にアクセスする場合を考慮して、md 側で判断する
                    362:        virtual bool CheckLEA(uint32 laddr) = 0;
                    363: 
                    364:        // 逆アセンブル。
1.1.1.5   root      365:        // mem.laddr の位置の命令を一つ逆アセンブルする。
1.1       root      366:        // 成功すれば true を返し、失敗すれば(?) false を返す。
                    367:        // 成功した場合 mnemonic に逆アセンブルした文字列が、
                    368:        // bin にこの命令のバイナリ列が格納されている。
                    369:        // mnemonic は単純に命令部分のみ、16進ダンプや付随情報は含まない。
                    370:        // bin はメモリイメージのバイト順で格納すること。
1.1.1.5   root      371:        virtual bool Disassemble(DebuggerMemoryStream& mem,
1.1       root      372:                std::string& mnemonic, std::vector<uint8>& bin) = 0;
                    373: 
                    374:        // 逆アセンブルをフォーマット。
                    375:        // オフライン版は逆アセンブルウィンドウなど、
                    376:        // オンライン版(Live) はデバッガプロンプトで表示するやつ。
                    377:        virtual std::string FormatDisasm(const std::string& mnemonic,
                    378:                const std::vector<uint8>& bin) = 0;
                    379:        virtual std::string FormatDisasmLive(const std::string& mnemonic,
                    380:                const std::vector<uint8>& bin) = 0;
                    381: 
1.1.1.4   root      382:        // 例外のベクタ番号から名前を取得。
                    383:        virtual const char *GetExceptionName(int vector) const = 0;
                    384: 
1.1.1.5   root      385:        // 機種
                    386:        Debugger::Arch arch {};
                    387: 
1.1.1.3   root      388:        // ベクタ番号の最大値 (+1)
1.1.1.4   root      389:        int vector_max {};
                    390:        // 最短の1命令のバイト数
                    391:        uint inst_bytes {};
                    392:        // 命令が固定長ならそのバイト数、可変長なら 0
                    393:        uint inst_bytes_fixed {};
1.1.1.3   root      394: 
1.1       root      395:  protected:
1.1.1.4   root      396:        Debugger *parent {};    // 親クラス
1.1       root      397: };
                    398: 
                    399: #define NORM           "\x1b[0m"
                    400: #define BOLD           "\x1b[1m"
                    401: #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.