valgrind (1)

valgrind コマンドを叩くと普通に main が動きます。 main は coregrind/launcher-linux.c にあります。ごちゃごちゃと環境を調べたり tool を調べたりした後、情報を残すために環境変数をいじったりした後、即 tool を execve して終了します。

で、 tool なんですが… tool の実体は memcheck--linux とかいうバイナリです。うちだと memcheck-amd64-linux とかです。これはちゃんとした ELF バイナリなんですけど、なかなかどうして普通のバイナリではありません。

> ldd rmemcheck-amd64-linux
        not a dynamic executable

static link されてます。

> nm rmemcheck-amd64-linux | grep -r ' printf$'
>

僕らの printf がありません。ていうか実のところ、 glibc をリンクしてません。さらに、

> nm rmemcheck-amd64-linux | grep -r ' main$'
>

main もどこにもありません。 gcc にヘンなオプションを渡すことによって crt1.o をリンクしないようにしてあります。事情があって、全ては guest のためです…

ただ、 memcpy と memset は定義されてたりします。

> nm rmemcheck-amd64-linux | grep -r ' memcpy$'
0000000038023180 T memcpy
> nm rmemcheck-amd64-linux | grep -r ' memset$'
000000003801f7b0 T memset

これは gcc が構造体をほげほげする時にこの二つの関数を呼ぶコードを埋めちゃうことがあるからだそうです。てか GCC そんなことするのかよ。ちなみに、これらの関数は自力で実装してます。

まぁとにかく、こんなバイナリですので、 _start から定義されてます。ソースコードで言うと coregrind/m_main.c です。 _start はアセンブリですけど、特にヘンなことはせずに _start_in_C_linux を呼びます。その先でも argc とか argv を作ったら、割とすぐに valgrind_main を呼びます。これで普通の世界です。 libc は無いですが!

でまぁ libc がどうなってるかってういと、まぁ実のところ、必要なものは自前で実装してます。 coregrind/pub_core_libc*.h や coregrind/m_libc*.c を参照。ミニマル実装な libc の一つとしてこれ使えるんじゃないかなぁとかいう程度にはそろってます。ただ呼ぶ時に VG_(printf)("Hello, world!") などと、 VG_() でシンボル名をかこう必要があることに注意です。

valgrind_main に続く(気がする)

LLVM勉強会

行ってきました。大変楽しかった。適当にベンチ取って結果発表したのでそのスライド置いときます。現地で作ったけどやはり mkp.rb は性にあうなぁ。

http://shinh.skr.jp/llvmbench/000.html

何が言いたいかよくわからんけど、言いたかったことは

  • SSA 大変だけど、メモリ使うコード書いて opt に喰わせればちゃんと SSA で書いたコードと同じような速度になった。 (BrainF vs llc+opt)
  • Brainfuck の +++ とかを incincinc とかにしても add $3 とかになってた。つまりある程度コード生成適当にやってもそれなりの速度になるというのは良い。
  • しかし現状では LLVM のパフォーマンスは長年の蓄積がある GCC に対して速くなるとか期待できるレベルじゃないと思う。
  • 個人的には LLVM のコード出力するより x86 のコード出力する方がラクなので開発の手軽さってのもあるとは思えないかなぁ。
  • あとこのベンチは関数呼び出しとか全くしないし、あまりベンチとして良くないと思うのでご注意を。

て感じか。

http://shinh.skr.jp/llvmbench/023.html

は適当に思いついた言語とかで足していっています。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h