LLVMのオプションのリッチ逆アセンブル出力

はじめに

LLVMのデフォルトの逆アセンブル出力は生のテキストです。命令のテキスト表現をより詳細に調べたり、よりユーザーフレンドリーな表示のために再フォーマットしたりするための機能を利用できるようにするために、オプションのリッチ逆アセンブル出力が用意されています。

このオプションの出力は、命令テキストの個々の部分を参照するのに十分です。これは、生の命令以上のものと、それらを表示する機能を必要とする、逆アセンブラ、リストファイルジェネレータ、およびプリティプリンタのようなクライアントを対象としています。

この機能を提供するために、アセンブリテキストはアノテーションでマークアップされます。マークアップは、消費者と生産者の間のバージョンミスマッチの場合でも堅牢になるように構文が十分に単純です。つまり、構文は一般的に「このテキストにはアノテーションがある」以上の意味を持たないため、消費者は理解できない、または気にしないアノテーションを単純に無視できます。

LLVMCreateDisasm()を呼び出して逆アセンブラコンテキストを作成した後、この呼び出しでオプションの出力を有効にします

LLVMSetDisasmOptions(DC, LLVMDisassembler_Option_UseMarkup);

その後、LLVMDisasmInstruction()を呼び出すと、マークアップされたアノテーションを含む出力文字列が返されます。

命令アノテーション

コンテキストマークアップ

アノテーション付きのアセンブリ表示は、クライアントがプリティプリンタのようなものをより効率的に実装するのに役立つコンテキストマークアップを提供します。ほとんどのマークアップはターゲットに依存しないため、クライアントはターゲット固有の知識がなくても効果的な表示を提供できます。

アノテーション付きのアセンブリは、通常の命令プリンタを通過しますが、オプションで命令文字列の部分にコンテキストタグを含みます。アノテーションは、テキストの「<」「>」で区切られたセクションです(1)。

annotation: '<' tag-name tag-modifier-list ':' annotated-text '>'
tag-name: identifier
tag-modifier-list: comma delimited identifier list

タグ名は、アノテーションのタイプを示す識別子です。最初のパスでは、これは非常に単純で、メモリアクセス、レジスタ、およびイミディエイトには、それぞれ「mem」、「reg」、および「imm」というタグ名が付けられます。

タグ修飾子リストは、通常、レジスタクラスなど、ターゲット固有の追加コンテキストです。

クライアントは、理解できないタグ名またはタグ修飾子を受け入れて無視する必要があり、古いクライアントを壊すことなくアノテーションを豊かにすることができます。

たとえば、スタック相対位置のARMロードの可能なアノテーションは、次のようにアノテーションを付けることができます

ldr <reg gpr:r0>, <mem regoffset:[<reg gpr:sp>, <imm:#4>]>

1: 「<」および/または「>」が有効なトークンであるアセンブリ方言では、リテラルトークンは、文字をすぐに繰り返すことでエスケープされます。たとえば、リテラルの「<」文字は、アノテーション付きのアセンブリ文字列で「<<」として出力されます。

C APIの詳細

この情報の対象となる消費者はC APIを使用するため、逆アセンブラ用の新しいC API関数が、アノテーション付きで逆アセンブルされた命令を生成するオプションを提供するために追加されます。LLVMSetDisasmOptions()LLVMDisassembler_Option_UseMarkupオプション(上記参照)です。