オブジェクトファイルの奇妙なcall命令
http://lucille.atso-net.jp/blog/?p=603
これなんですが、たしか参照解決前の関数エントリのインデックスだったような・・・
ということで確認してみる。
まずはコンパイルの準備。
ヘッダファイル。
extern "C" void test_c_func(); void test_cpp_func(); extern "C" void test_inline_c_func() {} void test_inline_cpp_func() {}
test.hとして保存。
んで本体。
#include "test.h" int main() { test_c_func(); test_cpp_func(); test_inline_c_func(); test_inline_cpp_func(); return 0; }
test.cppとして保存
で、コンパイル。
$ g++ -g -c test.cpp
そして逆アセンブル
$ objdump -dS test.o | c++filt -t test.o: file format pe-i386 Disassembly of section .text: 00000000 <_test_inline_c_func>: void test_cpp_func(); extern "C" void test_inline_c_func() {} 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 5d pop %ebp 4: c3 ret 5: 90 nop 00000006 <test_inline_cpp_func()>: void test_inline_cpp_func() {} 6: 55 push %ebp 7: 89 e5 mov %esp,%ebp 9: 5d pop %ebp signed char: c3 ret bool: 90 nop 0000000c <_main>: char: 55 push %ebp double: 89 e5 mov %esp,%ebp float: 83 ec 08 sub $0x8,%esp 12: 83 e4 f0 and $0xfffffff0,%esp 15: b8 00 00 00 00 mov $0x0,%eax a: 83 c0 0f add $0xf,%eax d: 83 c0 0f add $0xf,%eax 20: c1 e8 04 shr $0x4,%eax 23: c1 e0 04 shl $0x4,%eax 26: 89 45 fc mov %eax,0xfffffffc(%ebp) 29: 8b 45 fc mov 0xfffffffc(%ebp),%eax 2c: e8 00 00 00 00 call 31 <_main+0x25> 31: e8 00 00 00 00 call 36 <_main+0x2a> 36: e8 00 00 00 00 call 3b <_main+0x2f> 3b: e8 00 00 00 00 call 40 <_main+0x34> 40: e8 bb ff ff ff call 0 <_test_inline_c_func> 45: e8 bc ff ff ff call 6 <test_inline_cpp_func()> 4a: b8 00 00 00 00 mov $0x0,%eax 4f: c9 leave 50: c3 ret 51: 90 nop 52: 90 nop 53: 90 nop 54: 90 nop 55: 90 nop 56: 90 nop 57: 90 nop 58: 90 nop 59: 90 nop 5a: 90 nop 5b: 90 nop 5c: 90 nop 5d: 90 nop 5e: 90 nop 5f: 90 nop
で、call部分の抜粋
2c: e8 00 00 00 00 call 31 <_main+0x25> 31: e8 00 00 00 00 call 36 <_main+0x2a> 36: e8 00 00 00 00 call 3b <_main+0x2f> 3b: e8 00 00 00 00 call 40 <_main+0x34> 40: e8 bb ff ff ff call 0 <_test_inline_c_func> 45: e8 bc ff ff ff call 6 <test_inline_cpp_func()>
inline化してるものはobjdumpでの逆アセンブル結果で関数名まで出てます。
問題はその上の4行分。
でobjdumpでいろいろみてたらそれっぽいのを見つけた。
$ objdump -r test.o test.o: file format pe-i386 RELOCATION RECORDS FOR [.text]: OFFSET TYPE VALUE 0000002d DISP32 __alloca 00000032 DISP32 ___main 00000037 DISP32 _test_c_func 0000003c DISP32 __Z13test_cpp_funcv RELOCATION RECORDS FOR [.stab]: OFFSET TYPE VALUE 00000014 dir32 .text 00000020 dir32 .text 00000158 dir32 .text 00000164 dir32 .text 00000194 dir32 .text 000001d0 dir32 .text 000001dc dir32 .text 00000254 dir32 .text
リロケーション情報にあった。なんでか1ずつオフセットずれてるみたいだけど・・・
確認のため、実行ファイルにして付き合わせてみる。
まずは外部関数の用意
extern "C" void test_c_func() {} void test_cpp_func() {}
test_link.cppとして保存。
で、コンパイルとリンク
$ g++ -g -c test_link.cpp $ g++ -g -o test test.o test_link.o
そして逆アセンブル
$ objdump -dS test.exe | c++filt -t (中略) 004012fc <_main>: 4012fc: 55 push %ebp 4012fd: 89 e5 mov %esp,%ebp 4012ff: 83 ec 08 sub $0x8,%esp 401302: 83 e4 f0 and $0xfffffff0,%esp 401305: b8 00 00 00 00 mov $0x0,%eax 40130a: 83 c0 0f add $0xf,%eax 40130d: 83 c0 0f add $0xf,%eax 401310: c1 e8 04 shr $0x4,%eax 401313: c1 e0 04 shl $0x4,%eax 401316: 89 45 fc mov %eax,0xfffffffc(%ebp) 401319: 8b 45 fc mov 0xfffffffc(%ebp),%eax 40131c: e8 4f 05 00 00 call 401870 <___chkstk> 401321: e8 ca 00 00 00 call 4013f0 <___main> 401326: e8 25 00 00 00 call 401350 <_test_c_func> 40132b: e8 26 00 00 00 call 401356 <test_cpp_func()> 401330: e8 bb ff ff ff call 4012f0 <_test_inline_c_func> 401335: e8 bc ff ff ff call 4012f6 <test_inline_cpp_func()> 40133a: b8 00 00 00 00 mov $0x0,%eax 40133f: c9 leave 401340: c3 ret 401341: 90 nop (後略)
スタック検査が挿入されてます。
あとcall 40が消えてる・・・