web-dev-qa-db-ja.com

バイナリ形式をどのようにデバッグしますか?

バイナリビルダーのビルドをデバッグできるようにしたいと思います。現在、私は基本的にバイナリパーサーに入力データを出力してから、コードの奥深くまで行き、入力から出力へのマッピングを出力し、出力マッピング(整数)を取得し、それを使用して対応する整数を見つけています。バイナリで。かなり不格好で、入力と出力の間のマッピングを取得するためにソースコードを深く変更する必要があります。

バイナリをさまざまなバリアントで表示できるようです(私の場合、8ビットのチャンクで10進数として表示したいと思います。これは入力にかなり近いためです)。実際、いくつかの数値は16ビット、いくつかは8、いくつかは32などです。そのため、これらの異なる数値のそれぞれを何らかの方法でメモリ内で強調表示して、バイナリを表示する方法があるかもしれません。

私が可能であると私が見ることができる唯一の方法は、実際のバイナリ形式/レイアウトに固有のビジュアライザーを実際に構築する場合です。そのため、シーケンスの32ビットの数値がどこにあるべきか、8ビットの数値がどこにあるべきかなどがわかります。これは多くの作業であり、状況によっては扱いにくいものです。だからそれを行う一般的な方法があるかどうか疑問に思います。

また、このタイプのものをデバッグする一般的な方法は現在どのようなものなのかと思っているので、そこから何を試すべきかについていくつかのアイデアを得ることができます。

11
Lance Pollard

アドホックチェックの場合は、標準の16進ダンプを使用して、目視する方法を学んでください。

適切な調査のためにツールアップしたい場合は、通常Python-理想的には、これはメッセージ仕様ドキュメントまたはIDLから直接駆動され、次のように自動化されます。可能です(したがって、両方のデコーダーに同じバグを手動で導入する可能性はありません)。

最後に、既知の正しい定型入力を使用して、デコーダーの単体テストを作成する必要があることを忘れないでください。

76
Useless

これを行う最初のステップは、データの構造、つまりスキーマを記述する文法を検索または定義する方法が必要であることです。

この例は、非公式にコピーブックとして知られているCOBOLの言語機能です。 COBOLプログラムでは、メモリ内のデータの構造を定義します。この構造は、バイトの格納方法に直接マップされました。これは、メモリの物理レイアウトが開発者から抽象化された実装の問題である一般的な現代の言語とは対照的に、その時代の言語に共通です。

バイナリデータスキーマ言語 をGoogle検索すると、いくつかのツールが表示されます。例は Apache DFDL です。このためのUIもすでにあるかもしれません。

10
JimmyJames

ASN.1 、抽象構文記法1、はバイナリ形式を指定する方法を提供します。

  • DDT-サンプルデータと単体テストを使用して開発します。
  • テキストダンプが役立つ場合があります。 XMLの場合、サブ階層を縮小/展開できます。
  • ASN.1は実際には必要ありませんが、文法ベースの宣言的なファイル仕様の方が簡単です。
6
Joop Eggen

他の回答では、16進ダンプの表示、またはオブジェクト構造(JSONなど)の書き込みについて説明しています。これらの両方を組み合わせると非常に役立ちます。

16進ダンプの上にJSONをレンダリングできるツールを使用すると、非常に便利です。 dotNetBytes と呼ばれる.NETバイナリを解析するオープンソースツールを作成しました。これが サンプルDLLのビュー です。

dotNetBytes Example

3
Carl Walsh

完全に理解しているとは思いませんが、このバイナリ形式のパーサーがあり、コードを制御しているようです。したがって、この答えはその仮定に基づいています。

パーサーは、何らかの方法で、構造体、クラス、または言語のデータ構造を満たします。解析するすべてのものにToStringを実装すると、バイナリデータを人間が読める形式で表示する、非常に使いやすく維持しやすい方法になります。

基本的には次のようになります。

byte[] arrayOfBytes; // initialized somehow
Object obj = Parser.parse(arrayOfBytes);
Logger.log(obj.ToString());

そして、それを使うという観点からはそれだけです。もちろん、これにはyour ToString class/struct/whateverに対してObject関数を実装/オーバーライドする必要があり、ネストされたクラス/構造体/ whateverに対してもそうする必要があります。

さらに、条件ステートメントを使用して、リリースコードでToString関数が呼び出されないようにして、デバッグモード以外でログに記録されないものに時間を浪費しないようにすることができます。

ToStringは次のようになります。

return String.Format("%d,%d,%d,%d", int32var, int16var, int8var, int32var2);

// OR

return String.Format("%s:%d,%s:%d,%s:%d,%s:%d", varName1, int32var, varName2, int16var, varName3, int8var, varName4, int32var2);

元の質問では、これをある程度試みたように聞こえ、この方法は負担が大きいと思われますが、ある時点でバイナリ形式の解析を実装し、そのデータを格納する変数を作成しました。したがって、必要なのは、これらの既存の変数を適切な抽象化レベルで出力することです(変数が含まれるクラス/構造体)。

これは一度だけ実行する必要があることであり、パーサーの構築中に実行できます。また、バイナリ形式が変更された場合にのみ変更されます(これにより、パーサーへの変更が既に要求されます)。

同様に、一部の言語には、クラスをXMLまたはJSONに変換するための堅牢な機能があります。これにはC#が特に適しています。バイナリ形式をあきらめる必要はありません。デバッグログステートメントでXMLまたはJSONを実行し、リリースコードをそのままにします。

エラーが発生しやすいので、16進ダンプルートを使用しないことをお勧めします(正しいバイトから開始した場合、左から右に読んでいるときに、正しいエンディアンを「確認」していることを確認していますか?) 。

例:ToStrings吐き出し変数a,b,c,d,e,f,g,hと言います。プログラムを実行してgのバグに気づきましたが、問題は実際にはcで始まりました(ただし、デバッグ中であるため、まだそれを理解していません)。入力値がわかっていれば(知っているはずです)、cが問題の発生源であることがすぐにわかります。

単に[338E 8455 0000 FF76 0000 E444 ....]と表示される16進ダンプと比較してください。フィールドがさまざまなサイズの場合、どこでcが始まり、どのような値になるか-16進エディターが教えてくれますが、これはエラーが発生しやすく、時間がかかることです。それだけでなく、16進ビューアを介してテストを簡単に/迅速に自動化することはできません。データを解析した後に文字列を出力することで、プログラムが「考えている」ことを正確に知ることができ、自動テストのパスに沿った1つのステップになります。

1
Shaz