ToDo:
の話を聞いて、 GCC でコンパイルしたコンパイラは大丈夫で、そのコンパイラでコンパイルしたやつはまだ大丈夫だけど、次でクラッシュするバグがあった、みたいな話をしていた。
で、 TCC であそんでたとき似たようなのがふたつあったなーと思ってたんだけど、片方しか思い出せない。そっちの片方はまだ2世代目が3世代目をビルドする時のやつで、こんな感じだったと思う。
INT_MIN 以下の値のリテラルの扱いがバグってて、なんかデカい値になっちゃう。 GCC はそんなバグ持ってないから1世代目は大丈夫。2世代目はそのバグを持った1世代目コンパイラでコンパイルされているので、コード中に一箇所だけある INT_MIN 以下の値が出てくるぶぶんがおかしくなってる。そのデカい数字が何でできてるかっていうと、 32bit 相対 call で届くかをチェックする部分で、届かないから trampoline 作らんといかんのに作らないから届かなくて SEGV する、っていうような感じだった。
このクラッシュは記憶がたしかなら3世代目を tcc -run で実行してる時、つまり
tcc -run tcc.c -run tcc.c -c hello.c
的なことしてる時しか当時は再現しなくて、小さいプログラムだと件のチェックに漏れるような種類の長距離 call が出てこなかった、とかなんとか。このへん記憶あやしくて最後に走らせるコードは tcctest.c でも再現してたかもしれない。
このバグ再現させるには JIT 生成されたプログラムから負方向の 32bit を越える距離の関数 call をする必要があって、これが小さいプログラムだと起きない。なんでかっていうと、プログラムは malloc された空間に置かれてて、 glibc の malloc は小さい malloc に対して最初のうちは 32bit におさまるアドレスを返すから。でも、デカいプログラムだとデカい malloc をする必要があって、となると 64bit なアドレスがかえってきてやっと問題が再現する…とかいう感じだったと思う。
うーんでも詳細イマイチ覚えてない…
それをゴマかした時の変更はこれだったんだと思うんだけど、ただこれは上記の話をきちんと説明しきれてない気がするんだよな…
http://repo.or.cz/w/tinycc.git/commitdiff/51a7f163ad4a363953ae744afbc12cd7bd381097
あともう一個はよくある 32bit 命令を 64bit アドレスに対して使っちゃってた、っていう系だと思う。この手のバグは頻繁に起こりすぎてて、世代を経ると発生するみたいなヘンなヤツでもイマイチ詳細を覚えてないんだよな…
(00:04)
http://shinh.skr.jp/m/?date=20090416
微妙な記録を見つけた。
tcc -run tcc.c -run tcc.c は tcc -run tcc.c -run tcctest.c より先に動いたらしい。で、前者の方動かすのに最後に必要だった変更はそのデカい int literal だった、っていうのは、時期的にも正しい記憶だったようだ。
(00:11)
前 | 2012年 7月 |
次 | ||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。