2026/03/25

2BSDの誤動作をバイナリパッチで捕まえる方法 その2

 実行中にODTでメモリを書き換える方法は

  1. 操作が煩雑
  2. 問題の再現性が低い(気がする)、あるいは挙動が変化する

ため、 カーネルにバイナリパッチを当てて自力でトリガをかけられるようにしました。

ソースコードの変更ではなくバイナリパッチなのは、

インストールされるカーネルバイナリと一致するソースコードが見つからない

ためです。 

後述するFPGAの変更と組み合わせることで、誤動作の発生を高確率で捕まえられるようになりました。

カーネルのバイナリパッチ

オリジナルのカーネル(rpunix)とパッチを当てたカーネルを比較すると以下のようになります。

    41 324 202
   42   3   4
   49 324 202
   50   3   4
 1187 346 300
 1188  35  25
 1189 170 172
 1190 373 377
 1191  46 310
 1192  20  25
 1193 346   1
 1194  35   0
 1195 234 300
 1196 133  25
 1197 146 200
 1198  20 376
 1199 246 310
 1200  20  25
 1201 346   1
 1202  20   0
 1203 203   0
 1204  35   0

先頭の4か所はトラップベクタの書き換えです。"Illegal instruction trap"と"IOT trap"の発生時に関数dzdmaにジャンプします。残りの部分は、使用されていないドライバの関数(002202 T dzdma)を上書きして、以下の命令列を書き込んでいます。アドレス依存性はないのでソースコードのアドレス指定は気にしなくても大丈夫です。

        1                                .asect
       2 000400                         .=400
       3 000400 012700  177572          mov #177572,r0
       4 000404 012710  000001          mov #1,(r0)
       5 000410 012700  177200          mov #177200,r0
       6 000414 012710  000001          mov #1,(r0)
       7 000420 000000                  halt

177572はMemory Management Register #0のアドレスです。"1"を書き込むことでアドレス変換を有効にしています。

177200はHALT信号をアサートするためのI/Oポートで、今回のデバッグのために追加しました。FPGAの変更については後述します。

FPGAの変更

I/Oポート(177200)に書き込みを行うとHALT信号をアサートするように改変しました。変更内容は以下のとおりです。

 diff --git a/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v b/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
index 4133bd9..e4a4380 100644
--- a/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
+++ b/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
@@ -2219,6 +2219,13 @@ module top(
        default:;
       endcase

+  always @(posedge sys_clk or negedge INIT_n)
+    if( ~INIT_n )
+      dbg_trg <= 1'b0;
+    else if(negedge_SCTL_n & bus_write && address == 18'o777200)
+      dbg_trg <= 1'b1;
+
+/* -----\/----- EXCLUDED -----\/-----
   always @(posedge sys_clk or negedge RESET_n)
     if( ~RESET_n )
       {REG_DBG_CP, dbg_trg} <= 0;
@@ -2230,6 +2237,7 @@ module top(
       REG_DBG_CP <= 1'b1;
     else if( (address[15:0] == REG_DBG2) & aio_iread  & REG_DBG_CP)
       dbg_trg <= 1'b1;
+ -----/\----- EXCLUDED -----/\----- */
 //    else if( (address == 16'o001040) & aio_iread ) // trap at 'panic:'
 //      dbg_trg <= 1'b1;
 //  else if( (dpwa == (16'o25246 >> 1)) & (we0_lo | we0_hi |we1_lo | we1_hi))

オリジナルのデバッグ機能(ブレークポイント)と競合するので、該当部分をコメントアウトしています。

バッチの置き場所

パッチを当てたカーネルのバイナリと、FPGAのソースコードに対するパッチをここに置きました。ご利用ください。add-self-abort.patchとrpunix.patchedです。 

(3月27日追記) 2.11BSDでも同様の解析ができるように、カーネルパッチを置きました。2.11BSDのカーネルパッチ FPGAは2.11BSD用のアドレス拡張版が必要です。FPGAのパッチ

0 件のコメント:

コメントを投稿

TangConsoleDCJ11MEMにおける2BSDの誤動作の調査 その3

誤動作の原因の二つ目が判明しました。 符号なし2進数と符号付2進数の比較 後述するSOFUB_MAPの実装に符号なし2進数と符号付2進数を比較しているコードがありました。直接の比較ではありませんでしたが、符号なし整数の値を符号付整数の変数に代入し、その変数と定数を比較していたため...