DarwinはデフォルトでPosition Independentらしい
まだまだMac初心者やなぁと思わされたコト
今までLeopardの共有ライブラリをビルドするには,
$ cc -c -fPIC -fno-common -Wall -o hoge.o hoge.c $ cc -dynamiclib -o hoge.dylib hoge.o
とかやって,-fPICを指定してコンパイルしていたのですが,なんとDarwinは標準でPosition Independentでしたw
そもそも気づいたきっかけは,Libtool
そろそろ更新も安定してきたのでAutotools対応にしようとしたところ・・・Libtoolの吐くコードに-fPICがない・・・?
Libtoolを使うと,.loファイルにPICと非PICオブジェクトの場所が書いてあります
場所をチェックして,両方のMD5チェックサムを調べたところ・・・なんと同じ!?
不思議なので逆アセンブルしてみたところ,たしかにPICっポイ
でも,オプション指定してないのになんで???
っと思ってたらFinkのサイトにこんな記述が・・・
位置独立コード (PIC: Position Independent Code) の生成は Darwin ではデフォルトです.実際, PowerPC コードは設計上 position-independent となり,パフォーマンスや空間上の損失はありません.このため,共有ライブラリやモジュールへコードをコンパイルする際も,PIC を指定する必要はありません.
ABIによってPICと非PICの区別がないシステムもあるけど,Darwinもそうなのか?
それとも,デフォルトがPICなだけで区別はあるのか?
デフォルトでPICということは,実行可能コードはPIE?
ということで,おなじみHello, Worldで試したみた
使ったコードは以下の通り
#include <stdio.h>
int main(int argc, const char* argv[])
{
printf("hoge\n");
return 0;
}
いろいろビルドオプションを変えてみた
$ cc -Wall -o hoge hoge.c $ md5 hoge MD5 (hoge) = e440d2da97997f3d6242426c7af2697d $ cc -Wall -fPIE -o hoge hoge.c $ md5 hoge MD5 (hoge) = e440d2da97997f3d6242426c7af2697d $ cc -Wall -fno-pie -o hoge hoge.c $ md5 hoge MD5 (hoge) = e440d2da97997f3d6242426c7af2697d $ cc -Wall -fno-pic -o hoge hoge.c $ md5 hoge MD5 (hoge) = 3a8543d19ef046c85ada6bc71c144ef2
どうやら非PICなコードも吐ける模様なので,両方とも逆アセンブルして比較してみる
まず,PICなコードのtextセクション後半
1fd9の1fde(=次の命令)にジャンプするcall命令は一見無意味そうだが,次の1fdeでスタックからeipの値を取得するためにある
1fdfと1fe5でスタックの先頭に0x1a+ebx(=0x1fde) = 0x1ffd(=main関数の終端アドレス)が入る
その結果,次の1fe8のcall命令は,0x1ffdをリターンアドレスとしてスタックにプッシュしてprintfを呼び戻ってくるのでPIC
・・・
1fd9: e8 00 00 00 00 call 1fde <LC_SEGMENT.__TEXT+0xfde>
1fde: 5b pop %ebx
1fdf: 8d 83 1a 00 00 00 lea 0x1a(%ebx),%eax
1fe5: 89 04 24 mov %eax,(%esp)
1fe8: e8 18 10 00 00 call 3005 <dyld__mach_header+0xff5>
1fed: b8 00 00 00 00 mov $0x0,%eax
1ff2: 83 c4 14 add $0x14,%esp
1ff5: 5b pop %ebx
1ff6: c9 leave
1ff7: c3 ret
1ff8: 68 6f 67 65 00 push $0x65676f
1ffd: 00 00 add %al,(%eax)
次は,非PICなコードのtextセクション後半
こちらは,1fe8でスタックの先頭に,main関数の終端アドレスである1ffbを直接指定しているのでPICではない
・・・
1fd4: e8 00 00 00 00 call 1fd9 <LC_SEGMENT.__TEXT+0xfd9>
1fd9: 58 pop %eax
1fda: 8b 80 3f 00 00 00 mov 0x3f(%eax),%eax
1fe0: ff e0 jmp *%eax
1fe2: 55 push %ebp
1fe3: 89 e5 mov %esp,%ebp
1fe5: 83 ec 18 sub $0x18,%esp
1fe8: c7 04 24 fb 1f 00 00 movl $0x1ffb,(%esp)
1fef: e8 11 10 00 00 call 3005 <dyld__mach_header+0xff5>
1ff4: b8 00 00 00 00 mov $0x0,%eax
1ff9: c9 leave
1ffa: c3 ret
1ffb: 68 6f 67 65 00 push $0x65676f
ということで,DarwinではやっぱりPICでないコードも吐けるが,標準はPICなコードを吐くようになっている
セキュリティ的にもPIEは大歓迎!!
Macやるなぁ・・・
