rlibには何が入っている？


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

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

rlibには何が入っている？
-----------------------

まずは試しにライブラリを作ってみましょう。`rustc`だけでライブラリを作るサンプルが [Rust By Example](https://doc.rust-lang.org/rust-by-example/crates/lib.html) にあります：

```rust: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`で定義してある３つの関数と、`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](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/back/bytecode.rs)のコードにたどり着きます。
どうやらLLVMのバイトコードを埋め込むための形式のようですね。コメントによると以下のような構造になっているようです

```rust
//!     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](https://github.com/rust-lang/rust/tree/master/src/librustc_metadata)によって出力されたものと推察されます（名推理）。

目的だったLLVMのバイトコードが手に入ったし、必要なメタデータは`cargo-metadata`で別途取得できるため、これをこれ以上調べるのはやめました。

最後に
---
rlibを調べてるのは[Accel](https://qiita.com/termoshtt/items/41b4e23c4ce5e822319c)で使うためのPTXリンカを作るためだったんですが、これでLLVMのバイトコードが依存しているライブラリ毎に生成されることがわかったのでLLVMのコンパイラ`llc`を使って結合したPTX（というかcubin）を生成できそうです。