以下の内容はLinux上で確認しており、ほかのプラットフォームでは異なることが予想されます(規格ベースで調べたかったけど見つからなくて実装ベースで調べてます)
断片的な知識しかないので、以下では作業記録の形で記述します
rlibには何が入っている?
まずは試しにライブラリを作ってみましょう。rustc
だけでライブラリを作るサンプルが Rust By Example にあります:
pub fn public_function() {
println!("called rary's `public_function()`");
}
fn private_function() {
println!("called rary's `private_function()`");
}
pub fn indirect_access() {
print!("called rary's `indirect_access()`, that\n> ");
private_function();
}
rustc --crate-type=lib rary.rs
これでlibrary.rlib
が出来上がります(lib{filename}.rlib
ができる)。これの中身を見てみましょう。これはバイナリファイルなのでxxd
で先頭を見てみます
%xxd library.rlib| head -1
00000000: 213c 6172 6368 3e0a 2f20 2020 2020 2020 !<arch>./
この先頭のアスキー文字!<arch>
からどうやらこれはar
で生成された静的ライブラリであることがわかります。
中身を見てみましょう:
%ar t library.rlib
rary.rary0.rust-cgu.o
rary.rary1.rust-cgu.o
rust.metadata.bin
rary.rary0.rust-cgu.bytecode.encoded
rary.rary1.rust-cgu.bytecode.encoded
アーカイブ自体はar x library.rlib
で展開できます。*.o
は通常のオブジェクトファイルでnm
で中身が見れます
%nm rary.rary0.rust-cgu.o
0000000000000000 d ref.1
0000000000000000 r ref.2
0000000000000000 d ref.4
0000000000000000 d ref.6
0000000000000000 r str.0
0000000000000000 r str.3
0000000000000000 r str.5
U _ZN3std2io5stdio6_print17hd8ec97fc8b4f6250E
U _ZN4core3fmt9Arguments6new_v117h7bac9064a6920f0fE
0000000000000000 T _ZN4rary15indirect_access17hdfd7893373562372E
0000000000000000 T _ZN4rary15public_function17hf68b81680a0dec22E
0000000000000000 t _ZN4rary16private_function17h70b7e600c8033b10E
名前がマングルされていてわかりにくいですが、rary.rs
で定義してある3つの関数と、println!
に由来するだろう関数が見えます。
bytecode.*
これもまずxxd
で見てみましょう
%xxd rary.rary0.rust-cgu.bytecode.encoded | head -1
00000000: 5255 5354 5f4f 424a 4543 5402 0000 0029 RUST_OBJECT....)
RUST_OBJECT
という文字が見えますね。これをもとにググってみるとlibrustc_transのコードにたどり着きます。
どうやらLLVMのバイトコードを埋め込むための形式のようですね。コメントによると以下のような構造になっているようです
//! RLIB LLVM-BYTECODE OBJECT LAYOUT
//! Version 2
//! Bytes Data
//! 0..10 "RUST_OBJECT" encoded in ASCII
//! 11..14 format version as little-endian u32
//! 15..19 the length of the module identifier string
//! 20..n the module identifier string
//! n..n+8 size in bytes of deflate compressed LLVM bitcode as
//! little-endian u64
//! n+9.. compressed LLVM bitcode
//! ? maybe a byte to make this whole thing even length
このファイルを読み書きするための関数が同じくlibrustc_trans
で提供されていますが、これはrustc内部のcrateのため、使用するには#[feature(rustc_private)]
が必要になります(なのでnightlyでしか使えません)。
rust.metadata.bin
何でしょうねこれ(´・ω・`)
これはxxd
で先頭見てもそれっぽい識別用のアスキー文字がないので分からないのですが、内部にGlobalMetaData
のような文字列が見られる事とファイル名から恐らくlibrustc_metadataによって出力されたものと推察されます(名推理)。
目的だったLLVMのバイトコードが手に入ったし、必要なメタデータはcargo-metadata
で別途取得できるため、これをこれ以上調べるのはやめました。
最後に
rlibを調べてるのはAccelで使うためのPTXリンカを作るためだったんですが、これでLLVMのバイトコードが依存しているライブラリ毎に生成されることがわかったのでLLVMのコンパイラllc
を使って結合したPTX(というかcubin)を生成できそうです。