Nyxstoneは、LLVMに基づいた強力なアセンブリおよび分解ライブラリです。 LLVMソースツリーへのパッチや、ほとんどのLinux分布で利用可能な標準のLLVMライブラリに対するリンクは必要ありません。 C ++ライブラリとして実装されたNyxstoneは、RustとPythonのバインディングも提供しています。公式のすべてのLLVMアーキテクチャをサポートし、アーキテクチャ固有のターゲット設定を構成できます。
X86、ARM、MIPS、RISC-Vなどを含む、リンクされたLLVMによってサポートされているすべてのアーキテクチャのコードを組み立てて分解します。
錆とPythonのバインディングを備えたLLVMに基づくC ++ライブラリ。
LinuxとMacOSのネイティブプラットフォームサポート。
ラベルからアドレスのマッピングの仕様を含む、アセンブラーのラベルをサポートします
生のバイトとテキストに組み立てて分解しますが、アドレス、生のバイト、およびアセンブリ表現を含む詳細な指示オブジェクトも提供します。
分解は、バイトシーケンスからのユーザー指定の数の命令に限定できます。
ISA拡張機能やハードウェア機能など、アーキテクチャ固有のターゲット機能を構成できます。
サポートされているアーキテクチャの包括的なリストには、 clang -print-targets使用できます。各アーキテクチャの機能の包括的なリストについては、 llc -march=ARCH -mattr=helpを参照してください。
注記
免責事項:Nyxstoneは主に開発され、X86_64、AARCH64、およびARM32アーキテクチャについてテストされています。これらのプラットフォームのアセンブリを正確に生成し、エラーを特定する能力に高い自信があります。他のアーキテクチャの場合、Nyxstoneの有効性は、それぞれのLLVMバックエンドの信頼性とパフォーマンスに依存します。
このセクションでは、Nyxstoneを開始する方法、必要な前提条件、CLIツールの使用方法、C ++、Rust、Pythonでライブラリを使用するための段階的なガイドラインをカバーする方法について説明します。
Nyxstoneを構築する前に、ClangとLLVMがシステムに存在することを確認してください。 Nyxstoneは、LLVMの主要バージョン15-18をサポートしています。構築するときは、システムの$PATHまたは指定された環境変数$NYXSTONE_LLVM_PREFIX/binでllvm-configを探します。
LLVMバージョン15-18のインストールオプション:
sudo apt install llvm- ${version} llvm- ${version} -devDebian LLVMバージョン15および16は、Debianリポジトリを通じて利用できます。インストールはubuntuと同じです。バージョン17または18については、インストール手順についてはhttps://apt.llvm.org/を参照してください。
アーチ
sudo pacman -S llvm llvm-libsbrew install llvm@18
export NYXSTONE_LLVM_PREFIX=/opt/homebrew/opt/llvm@18注:Windowsでは、Visual Studio 2022 X64コマンドプロンプトからこれらのコマンドを実行する必要があります。さらに~lib/my-llvm-18別のパスに置き換えます。
# checkout llvm
git clone -b release/18.x --single-branch https://github.com/llvm/llvm-project.git
cd llvm-project
# build LLVM with custom installation directory
cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_PARALLEL_LINK_JOBS=1
cmake --build build
cmake --install build --prefix ~ /lib/my-llvm-18
# export path
export NYXSTONE_LLVM_PREFIX= ~ /lib/my-llvm-18また、LLVMバージョンが静的リンクに必要なシステムに従ったライブラリをインストールしてください。それらは、コマンドllvm-config --system-libsで表示できます。リストは空になる可能性があります。 ubuntu/debianでは、パッケージzlib1g-devとzlibstd-devが必要になります。
Nyxstoneには、迅速なアセンブリと分解タスクのための便利なCLIツールが付属しています。 Nyxstoneリポジトリをチェックアウトし、cmakeでツールを構築します。
# clone directory
git clone https://github.com/emproof-com/nyxstone
cd nyxstone
# build nyxstone
mkdir build && cd build && cmake .. && make 次に、 nyxstoneコマンドラインから使用できます。ヘルプメニューの出力は次のとおりです。
$ ./nyxstone -h
Usage: nyxstone [-t=<triple>] [-p=<pc>] [-d] <input>
Examples:
# Assemble an instruction with the default architecture ('x86_64').
nyxstone 'push eax'
# Disassemble the bytes 'ffc300d1' as AArch64 code.
nyxstone -t aarch64 -d ffc300d1
Options:
-t, --triple=<triple> LLVM target triple or alias, e.g. 'aarch64'
-c, --cpu=<cpu> LLVM CPU specifier, e.g. 'cortex-a53'
-f, --features=<list> LLVM architecture/CPU feature list, e.g. '+mte,-neon'
-p, --address=<pc> Initial address to assemble/disassemble relative to
-l, --labels=<list> Label-to-address mappings (used when assembling only)
-d, --disassemble Treat <input> as bytes to disassemble instead of assembly
-h, --help Show this help and usage message
Notes:
The '--triple' parameter also supports aliases for common target triples:
'x86_32' -> 'i686-linux-gnu'
'x86_64' -> 'x86_64-linux-gnu'
'armv6m' -> 'armv6m-none-eabi'
'armv7m' -> 'armv7m-none-eabi'
'armv8m' -> 'armv8m.main-none-eabi'
'aarch64' -> 'aarch64-linux-gnueabihf'
The CPUs for a target can be found with 'llc -mtriple=<triple> -mcpu=help'.
The features for a target can be found with 'llc -mtriple=<triple> -mattr=help'.
これで、x86_64アーキテクチャの指示を組み立てることができます。
$ ./nyxstone -t x86_64 "mov rax, rbx"
0x00000000: mov rax, rbx ; 48 89 d8
一連の指示を組み立てることもできます。以下では、ラベルベースのアドレス指定を利用し、最初の命令が0xdeadbeefにアドレス指定するようにマッピングされていると仮定します。
$ ./nyxstone -t x86_64 -p 0xdeadbeef "cmp rax, rbx; jz .exit; inc rax; .exit: ret"
0xdeadbeef: cmp rax, rbx ; 48 39 d8
0xdeadbef2: je .exit ; 74 03
0xdeadbef4: inc rax ; 48 ff c0
0xdeadbef7: ret ; c3
さらに、さまざまな命令セットの命令を分解できます。ここでは、ARM32親指命令セットがあります。
$ ./nyxstone -t thumbv8 -d "13 37"
0x00000000: adds r7, #19 ; 13 37
ユーザー定義のラベルのサポートを使用して、メモリの位置を自分で指定してラベル.label含まないこのスニペットを組み立てることができます。
$ ./nyxstone -p "0x1000" -l ".label=0x1238" "jmp .label"
0x00001000: jmp .label ; e9 33 02 00 00
NyxstoneをC ++ライブラリとして使用するには、C ++コードをNyxstoneおよびLLVMに対してリンクする必要があります。
次のcmakeの例は、あなたのプロジェクトのサブディレクトリnyxstoneのNyxstoneを想定しています。
add_subdirectory (nyxstone)
add_executable (my_executable main.cpp)
target_link_libraries (my_executable nyxstone::nyxstone)対応するC ++使用例:
# include < cassert >
# include < iostream >
# include " nyxstone.h "
int main ( int , char **) {
// Create the nyxstone instance:
auto nyxstone {
NyxstoneBuilder ( " x86_64 " )
. build ()
. value ()
};
// Assemble to bytes
std::vector< uint8_t > bytes =
nyxstone-> assemble ( /* assembly= */ " mov rax, rbx " , /* address= */ 0x1000 , /* labels= */ {}). value ();
std::vector< uint8_t > expected { 0x48 , 0x89 , 0xd8 };
assert (bytes == expected);
return 0 ;
}包括的なC ++例については、example.cppをご覧ください。
NyxstoneをRustライブラリとして使用するには、 Cargo.tomlに追加して、次の例に示すように使用します。
use anyhow :: Result ;
use nyxstone :: { Nyxstone , NyxstoneConfig } ;
use std :: collections :: HashMap ;
fn main ( ) -> Result < ( ) > {
let nyxstone = Nyxstone :: new ( "x86_64" , NyxstoneConfig :: default ( ) ) ? ;
let bytes = nyxstone . assemble_with (
"mov rax, rbx; cmp rax, rdx; jne .label" ,
0x1000 ,
& HashMap :: from ( [ ( ".label" , 0x1200 ) ] ) ,
) ? ;
println ! ( "Bytes: {:x?}" , bytes ) ;
Ok ( ( ) )
}錆の結合に関する詳細については、対応するReadmeをご覧ください。
PythonのNyxstoneを使用するには、PIPを使用してインストールします。
pip install nyxstone次に、Pythonから使用できます。
$ python -q
>>> from nyxstone import Nyxstone
>>> nyxstone = Nyxstone("x86_64")
>>> nyxstone.assemble("jne .loop", 0x1100, {".loop": 0x1000})
詳細な指示は、対応するREADMEで利用できます。
NyxstoneはTarget::createMCAsmParserやTarget::createMCDisassemblerなどのLLVMからのパブリックC ++ API関数をレバレッジして、アセンブリと分解タスクを実行します。 Nyxstoneは、 MCELFStreamerとMCObjectWriter 2つのLLVMクラスを拡張して、カスタムロジックを注入し、追加情報を抽出します。具体的には、Nyxstoneは次の手順でアセンブリプロセスを増強します。
ELFStreamerWrapper::emitInstruction :ユーザーが詳細な命令オブジェクトが要求されている場合、アセンブリ表現と命令の初期生のバイトをキャプチャします。
ObjectWriterWrapper::writeObject :詳細な命令オブジェクトに命令の最終的な生のバイト(再配置調整を伴う)を書き込みます。さらに、完全なELFファイルから.textセクションのみに生のバイト出力を切り替えます。
ObjectWriterWrapper::validate_fixups :再配置の範囲の確認など、追加のチェックを実施します。
ObjectWriterWrapper::recordRelocation :追加の再配置を適用します。 MCObjectWriter 、リンク中にのみ適用されるいくつかの再配置をスキップします。現在、これはfixup_aarch64_pcrel_adrp_imm21 AARCH64命令adrpの再配置にのみ関連しています。
LLVMクラスを拡張すると、特定のLLVMバージョンへの強い依存関係など、いくつかの欠点が導入されますが、LLVMソースツリーにパッチを維持するのが難しい代替案よりも、このアプローチは依然として好ましいと考えています。
私たちは、プロジェクトの複雑さをさらに削減し、改善のための提案を受け入れることを約束しています。将来を見据えて、既存のLLVMインフラストラクチャをよりスマートな方法で活用するか、後処理ステップに追加のロジックを組み込むことにより、LLVMクラスを拡張する必要性を排除する可能性があります。
以下は、Nyxstoneを大幅に前進させると思われるいくつかのアイデアと改善です。アイテムは特定の順序でリストされていません。
スレッドの安全性を確認してください
より多くのLLVMバージョンのサポートを追加します(発見されたLLVMライブラリバージョンに応じて自動選択)
MCObjectWriter異なる方法で構成するか、別のライターを使用して、LLVMにすべての移転( adrpを含む)を適用するためのオプションを探索する
LLVMクラスの拡張に依存するのではなく、アセンブリプロセスの生のバイト出力を分解して、詳細な命令オブジェクトを生成するオプションを探索する
LLVMクラスの拡張に依存するのではなく、ポスト処理ステップで追加の範囲と再配置のアラインメントを実装するオプションを探索する
NyxstoneはMITライセンスの下で利用できます。
コミュニティからの貢献を歓迎します! Nyxstoneで問題が発生した場合は、GitHubの問題を自由に開いてください。
プロジェクトに直接貢献することに興味がある場合は、たとえば:
準備ができたら、変更を受けてプルリクエストを送信してください。私たちはあなたの貢献を楽しみにしています!
現在の貢献者は次のとおりです。
コア:
マイナー:
LLVMを錆の適切なバージョンに正しくリンクするようにするために、LLVM-SYSのbuild.rsを適応させました。