bear を使った compile_commands.json 生成

はじめに

clangd を使う際、JSON Compilation Database (compile_commands.json) が必要になります。CMake を使ってビルドするプロジェクトの場合は、CMAKE_EXPORT_COMPILE_COMMANDS=1 を指定すれば簡単に export できますが、そうでない場合は別のツールを使って生成する必要があります。

今回は、汎用的に compile_commands.json を生成するツール Bear の Mac への導入方法について紹介します。

Homebrew があれば以下のコマンドで入ります。

$ brew install bear

ただ、このままだと Bear が動いてくれません。この後、以下の二つの手順を踏む必要があります。

  • System Integirty Protection の無効化
  • 標準ライブラリのヘッダファイルの再インストール

System Integrity Protection の無効化

Bear のリポジトリにも注意点として挙げられていますが、library preload を無効化しているシステムでは Bear は使えません。Macだと (私は Majave を使っていますが、それ以降でもおそらく) デフォルトで library preload ができないようになっているため、Bear が出力する compile_commands.json が空ファイルになります。

この library preload を許可するためには、System Integrity Protection を無効化してやる必要があります。デフォルトではこれは有効になっています。

$ csrutil status | grep 'System Integrity Protection'
System Integrity Protection status: enabled.

System Integrity Protection の無効化ですが、以下の手順で行えます。

  1. OS の再起動
  2. Cmd-R を押しっぱなしにして、リカバリーモードに入る
  3. ユーティリティをクリック
  4. Terminal をし、Terminal を起動
  5. csrutil disable を打ち込む
  6. OS の再起動

再起動した後、再度 Terminal を開き、System Integrity Protection が無効になっていることを確認します。

$ csrutil status | grep 'System Integrity Protection'
System Integrity Protection status: disabled.

標準ライブラリのヘッダファイルの再インストール

次は標準ライブラリのヘッダファイルの再インストールです。これをやらないとこのイシューで挙げられている問題点に遭遇し、標準ライブラリのヘッダーが見つからずコンパイルできなくなります。

解決策としてはイシューのスレッドのこれにしたがって、ヘッダーの再インストールを行います。

JSON Compilation Database を生成してみる

これで compile_commands.json が生成できるようになりました。適当な C 言語のプロジェクトで compile_commands.json を早速作成してみましょう。

今回は高機能逆アセンブラである radare2 の compile_commands.json を生成してみます。

$ git clone https://github.com/radareorg/radare2.git
$ cd radare2
$ ./configure
$ bear make all
$ ls compile_commands.json
compile_commands.json

以下のような compile_commands.json ができていることが確認できます。

[
    {
        "arguments": [
            "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang",
            "-c",
            "-fno-common",
            "-fPIC",
            "-g",
            "-Wall",
            "-D__UNIX__=1",
            "-DR2_PLUGIN_INCORE",
            "-I/Users/utsuneko/Documents/radare2/libr/..//shlr",
            "-I/Users/utsuneko/Documents/radare2/libr/../shlr/zip/include",
            "-I/Users/utsuneko/Documents/radare2/libr",
            "-I/Users/utsuneko/Documents/radare2/libr/include",
            "-fvisibility=hidden",
            "-I../../shlr/sdb/src//src",
            "-DHAVE_FORK=1",
            "-o",
            "chmod.o",
            "chmod.c"
        ],
        "directory": "/Users/utsuneko/Documents/radare2/libr/util",
        "file": "chmod.c"
    },
...

まとめ

Bear の Mac への導入方法についてまとめました。

compile_commands.json があると、VSCode の補完がいい感じで効くようになったりします。他にも最近リリースされた Sourcetrail を C 言語のプロジェクトで使う場合も compile_commands.json が必要になります。   この compile_commands.json の作成、地味に苦労したので、誰かの役に立てればと思い、ブログに記事としてまとめました。

AArch64 アセンブリ UBFM UBFIZ UBFX

はじめに

最近はArmv8アセンブリを読むことが多いのが、ビット演算系の命令を頻繁に忘れて何回もググっているので、一回まとめておく。 公式ドキュメント、擬似コード (or 具体例) を載っけて欲しい。

ubfm

Unsigned Bit Field Move の頭文字をとって ubfm と呼ぶらしい。 他のビット演算系の命令を見る上で基本となる。

ubfm Xd, Xn, #imm6r, #imm6s
  • imm6s には source register から移動させる一番左のビット番号を指定
  • imm6r には destination register に挿入させる位置の一番右のビット番号を指定

右とか左とか言っているが、LSB first の場合になる。

擬似コードで書けば以下のような感じ。

Xd[:] = 0;
Xd[(64 - imm6r + imm6s + 1):(64 - imm6r)] = Xn[imm6s + 1:0];

Pythonで同じ操作に当たるコードを書くとこんな感じ。

Xd = (Xn & ((1 << (imm6s + 1)) - 1)) << (64 - imm6r)

まず Xn の下位 imm6s + 1 bitを取り出す。その取り出したbitを 64 - imm6r bit 分だけ左シフトしたものをXdに代入する。

例がこのサイトに上がっていたので載っけておく。

 x2    : 823456789ABCDEF0
 x5    : 5555555555555555
 UBFM X5, X2, #60, #23 --> 000000000BCDEF00
# x2 のうち下位24bitsを取り出す (今回だとBCDEF0) 
# そのあと、64 - 60 = 4 bits だけ左シフトしてx5に代入すれば完成

ubfiz

Unsigned Bit Field Insert in Zero の頭文字をとって ubfiz。

ubfiz Xd, Xn, #lsb, #width

これは以下と同じになる。

ubfm Xd, Xn, #(-lsb MOD 64), #(width-1)

source register の内容のうち、下位 width bit を取り出す。これを lsb 分左シフトしたものを作成し、destination register に格納する。

擬似コードで書くとこんな感じ。

Xd[:] = 0;
Xd[width + lsb:lsb] = Xn[width:0]

これも具体例で考えてみる。

 x2    : 823456789ABCDEF0
 x5    : 5555555555555555
 UBFIZ X5, X2, #4, #24 --> 000000000BCDEF00

ubfm の具体例を ubfiz で書き直した例を作ってみた。lsb = 4, width = 24 としたら、さっきの ubfm の具体例と一致することがわかると思う。

ubfx

Unsigned Bit Field eXtract を省略して ubfx

これは以下と同じになる。

ubfm Xd, Xn, #lsb, #(lsb+width-1)

擬似コードでかくとこんな感じ。

Xd[:] = 0;
Xd[width:0] = Xn[lsb + width:lsb];

具体例を一個載っけておく。

x2    : 823456789ABCDEF0
x5    : 5555555555555555
UBFX X5, X2, #4, #24 --> 00000000000BCDEF

おわりに

UBFM UBFIZ UBFX について擬似コード付きで説明した。 新しく命令勉強したら更新していくことにする。

RISC-V Day Tokyo 2019 に参加してきた

日立製作所立馬場記念ホール にて行われたRISC-V Day Tokyo 2019に参加してきた。聞いて思ったことを忘れないうちに書き残しておこうと思い、記事にした。

個人的に気になったこと

まずは、将来的にRISC-Vが機能をスイスに移すことを計画しているとの話。Calista Redmondさんの発表において出てきた(正確には、発表あとの質疑応答のところ)。

ISAを非営利財団であるRISC-V Foundationが管理しているが、機能がアメリカにある以上、Huaweiへ行われたような措置が今後起きないとも限らない。スイスに拠点が移ることにより、こうした危険性はなくなり中国メーカーにとって追い風になりそう。

次にヘネペタの翻訳の苦労話。原著は結構な分量である上、殴り書きに近いところがあったため翻訳に際しては相当の苦労があったとのこと。編集者とのトラブルもあったそうで、その苦労の末生まれたのがヘネパタの日本語訳本だったという話。

私は大学の選考がComputer Scienceでも電気電子工学でもないので、パタヘネすらまだ読めていないが、コンピューターアーキテクチャの定番の教科書・バイブル的存在とのことで是非とも読破しておきたい。

その他、パネルディスカッション。

印象に残っているのは「セキュリティモジュールをオープンソースで作ることのメリットは?」という質問。ソフトウェアと同じでリーナスの法則 (「十分な目ん玉があれば、全てのバグは洗い出される」) が働くこと、問題がおきた場合に自力での検証ができること (これがArmやIntelのものだとできない) というのがメリットとの話が出ていた。

ただ、リーナスの法則が働くのは十分にアクティブなプロジェクトにおいてのみなので、オープンであることが必ずしもプラスに働くわけではないことは注意が必要。

例えば、オープンにして逆にサプライチェーン攻撃の標的になるケースもある。例えば、npmパッケージのevent-streamでは、悪意のある人がOSSのメンテナーとなり、悪意のあるモジュールをパッケージ内に埋め込んだという事件がおきている。

また、「RISC-Vを採用してよかった点。悪かった点。」という質問もあった。

よかった点として

  • シンプルなISAで本質的でない部分に煩わされることがない
  • 一通りソフトウェアスタックが整っている
  • ツールセットがよくできている
  • 新しいアイデアがすぐに試されて、実装が公開される

悪かった点として

  • デバッグ環境が整っておらず苦労する
  • libcとかにまだバグがあったりする
  • Tile Linkの仕様が一気に変わったりして、アップデートしたら突然動かなくなったりする
  • Chiselできる人があまりいない

とかが挙げられていた。

libcとかのバグはこれまで踏んだことがないけど、最近のものはだいぶ修正されたということなんかな。

Chisel ひとまず最低限かけるようになってきたが、まだまだな気がするな(依然としてRocket Chipのコードリーディングに苦しんでいるレベルなので。)。

所感

本日の発表を聞いていて、初めに思ったことが「日本でも商用利用がそろそろ始まる気配があるな」というところかなと。他のアジア諸国に比べて2--3年ほど遅れとの話があったが、今年が商用利用の元年になるかもしれない。

ただ、あくまで気配でしかないかな。日本企業の発表で具体的な採用事例を紹介しているところは少なくとも現時点ではなく、まだ検討段階を脱していない。カスタマイズ可能・低消費電力を実現しやすい・ライセンスフリーであることに目をつけてようやく検討しだしたと感じ。

あと、既存の製品からの移行よりは新規参入者をターゲットとしているサービスがRISC-Vは多めと今日聞いていて感じた。すでに市場に入り込み広く使われているプロセッサの置き換えをすることがどれだけ大変なのか、それは歴史が証明しているわけで、そこに狙いを定めるのはなんか正しい気がする。(ただ、DTSインサイト SiFiveと日本市場の正規代理店となったというプレスリリースが先週あったけど、これにより既存の製品からの移行の支援の体制が整ってきてはいる。)

あと、スポンサーセッションが多めなのは気になった。もう少しテクニカルな話を聞きたかったというところはある。アカデミック・産業半々ぐらいの構成にしてほしい。(ちなみに、海外のRISC-V Workshopとかをみていると発表の内容がアカデミック・産業半々ぐらいになっている。)日本でRISC-Vに関係する研究を行なっている研究者は0ではないはずで、そういった研究者を招いて最先端の研究内容を発表するセッションを設けても良いのではと感じた。

総じて勉強になることが多かった。来年も都合が合えば参加したい。

分子動力学シミュレーションコードをGoで書いてみる

はじめに

仕事でGoを時々使う。静的型付け言語で比較的動作も高速・書きやすいというのがあり重宝している。

高速と書いたが、あるアプリケーションを別々の言語で実装して速度を比較した場合、ざっくりと

C/C++, Fortran, Rust > Go > Java > Python, Ruby

みたいになるイメージを持っていたんだけども、これって本当なのかなとふと思った。

そこで、大学にいた頃にやっていた短距離古典分子動力学法のシミュレーションコードをGoで書いてみて、C++の実装と比較してみることにした。

ソースコードは以下にあげた。

github.com

比較対象としたC++の実装はkaityo256さんの以下のリポジトリのコード。

github.com

計測の条件は以下の通り

時間がなかったので、ひとまずstep1のBrute Forceで相互作用の計算を行う場合の性能の比較だけ行なった。

結果

Go C++
実行時間 18.43s 19.99s

あれ? Goの実装の方が速かった。なんかミスっている気がするな。。。 後日、真面目にプロファイリングしてみることにする。

Malware Data Science Chapter 8 のデータセットで少し遊んでみる

Malware Data Science の Chapter 8 では実際に機械学習を使ってマルウェア検知器を作る手順が書かれている。 このChapterの内容を再現できるように、マルウェアと良性ファイルを入手できるようになっており、Supportページからダウンロードできる。 データ数は良性ファイルが991でマルウェアが428でそこまで多くはないが、これを使って少し遊んでみる。

実施した内容

Malware Data Science では Feature Hashing Trick を使って、バイナリに含まれる文字列情報から特徴ベクトルを作り、それを使ったマルウェア検知器の作成方法が書かれている。これとは別の特徴量を使った場合と比較して性能がどの程度変化するのかを調べてみることにした。

特徴量としては、Endgameが出しているEmberデータセットで使われている機械学習モデルで使われているものを採用した。

github.com

このモデルでは以下が特徴ベクトルとして採用されている。

  • バイナリに含まれるバイトヒストグラム
  • バイトエントロピーヒストグラム
  • バイナリに含まれる文字列
  • ファイルサイズやメモリに読み込まれた際のサイズ
  • PEヘッダーの情報
  • セクションの情報
  • インポートAPIの情報
  • エクスポートAPIの情報

ちなみに、APIの情報や文字列の情報を特徴ベクトルにする際は、Malware Data Scienceでも使われているFeature Hashing Trickが使われている。

実験結果

実験の結果はgistにまとめた。

gist.github.com

AUCを比較すると、Emberのほうが優れていた (Malware Data Scienceのモデルだと AUC が0.9951、Emberだと AUC が0.9972) が、そこまで大きく差はない。

次に、どの特徴量が最も検知に効いているのか、調べてみると (ちなみに、先程のgistの一番最後のところに特徴量の重要度の比較をまとめている) 、圧倒的に Byte Histogram が大きい。二番目に文字列の情報が重要な特徴量として使われているようだ。

結局のところ、Ember では文字列情報以外にも色々特徴量が使われているけども、今回に限れば文字列とバイトヒストグラム・バイトエントロピーヒストグラムぐらいしか推論結果に寄与していないみたいである。

これだったら、バイトヒストグラムだけでも良い精度が出せるのではと思い、こちらも試してみる。

gist.github.com

もとのEmberのモデルから特徴ベクトルのサイズが1/10ぐらいになっているが、AUCが0.9975と上がった。バイトヒストグラム強い。

Embenchを試そうとしたが動かせなかった

Dhrystone に変わるフリーのCPUを性能を測るベンチマークとして Embench が David Patterson によって提案されているのを、RISC-V Workshop Zurich で知った。発表スライドとビデオはこのリンクの"Embench TM: A Free Benchmark Suite for Embedded Computing from an Academic-Industry Cooperative (Towards the Long Overdue and Deserved Demise of Dhrystone)" を参照。

GitHubソースコードがすでに公開されているので早速試そうとしたのだが、結論から言うと実行することができず orz。

riscv64 向けに一応ビルドするところまではできたのだが、ベンチマークを実行しその結果を出力するところまではできなかった。

リポジトリにあるISSUEを見る限り同じ問題に困っている人がいるらしく、ビルドスクリプトからして書き直しを検討しているらしいので、修正されるのを待つことにするか。 github.com

riscv64 向けにビルドできるようにしたものを置いた。 github.com

Malware Data Science: Attack Detection and Attributionを読んだ

Malware Data Scienceを読んだ。

マルウェア解析のBasicから入り、機械学習の入門・マルウェア検知器への応用事例・深層学習のイントロダクションとその適用事例などが紹介されている。

機械学習のプロフェッショナルには正直物足りない内容だと思う。ある程度マルウェア解析の経験がある人で、機械学習の手法を取り入れた検知器を作りたいと考えている人向けかなと思った。

(ただ、マルウェア解析の経験がある人向けの本にしては最初の二章は正直余分な気がして、少しターゲットとしている読者層がよく見えない感じの本かなと思った。)

この本むけに筆者が作成したデータセットが公開されている。そこそこのデータ量があって結構遊べた。その遊んだ結果はまた後日投稿しようと思う。