rust
LLVM

rlibには何が入っている?

以下の内容はLinux上で確認しており、ほかのプラットフォームでは異なることが予想されます(規格ベースで調べたかったけど見つからなくて実装ベースで調べてます)

断片的な知識しかないので、以下では作業記録の形で記述します

rlibには何が入っている?

まずは試しにライブラリを作ってみましょう。rustcだけでライブラリを作るサンプルがrust-lang-jaにあります:

rary.rs
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で生成された静的ライブラリであることがわかります。

https://ja.wikipedia.org/wiki/Ar_(UNIX)

中身を見てみましょう:

%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)を生成できそうです。