オブジェクトファイルの奇妙な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が消えてる・・・