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

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