私はこのコードをgcc hello.c -o hello -O3
でコンパイルしています:
#include <stdio.h>
int main(void) {
printf("Hello world\n");
return 0;
}
そして、私が得る再配置をリストするとき:
test@southpark$ readelf -r hello | grep gmon
080495a4 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
080495b4 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
このファイルにシンボルをリストすると、次のようになります。
test@southpark$ readelf -s hello | grep gmon
1: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
48: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
gmon_start
はgprofと関係がありますか? -pg
または-g
でコンパイル/リンクしなかったのに、なぜそのシンボルの再配置があるのですか?どのライブラリがこのシンボルを解決しますか?
少しグーグルして、これを ここ から見つけました:
関数call_gmon_startは、gmonプロファイリングシステムを初期化します。このシステムは、バイナリが-pgフラグを使用してコンパイルされると有効になり、gprof(1)で使用するための出力を作成します。シナリオの場合、バイナリcall_gmon_startは、その_start関数の直前に配置されます。 call_gmon_start関数は、グローバルオフセットテーブル(__gmon_start__とも呼ばれます)の最後のエントリを検索し、NULLでない場合は、指定されたアドレスに制御を渡します。 __gmon_start__要素は、プロファイリング情報の記録を開始し、クリーンアップ関数をatexit()に登録するgmon初期化関数を指します。ただし、この場合、gmonは使用されていないため、__ gmon_start__はNULLです。
だから...
更新:
さて、私はあなたのコードを-pg
の有無にかかわらずコンパイルしました。 __gmon_start__
がコンパイルされたプログラム内のアドレスにマップされているようです。そうは言っても、そのシンボルを解決するライブラリはないと思いますが、プログラム自体はあります。
with -pg
:
akyserr@orion:~$ readelf -r hello
Relocation section '.rel.dyn' at offset 0x32c contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049fec 00000806 R_386_GLOB_DAT 08048460 __gmon_start__
Relocation section '.rel.plt' at offset 0x334 contains 6 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000607 R_386_JUMP_SLOT 080483b0 _mcleanup
0804a004 00000107 R_386_JUMP_SLOT 00000000 __monstartup
0804a008 00000207 R_386_JUMP_SLOT 00000000 mcount
0804a00c 00000307 R_386_JUMP_SLOT 00000000 __cxa_atexit
0804a010 00000407 R_386_JUMP_SLOT 00000000 puts
0804a014 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main
__ gmon_start__コードのobjdump:
akyserr@orion:~$ objdump -S hello | grep "460 <__gmon_start__>:" -A 20
08048460 <__gmon_start__>:
8048460: 83 ec 1c sub $0x1c,%esp
8048463: a1 20 a0 04 08 mov 0x804a020,%eax
8048468: 85 c0 test %eax,%eax
804846a: 75 2a jne 8048496 <__gmon_start__+0x36>
804846c: c7 05 20 a0 04 08 01 movl $0x1,0x804a020
8048473: 00 00 00
8048476: c7 44 24 04 36 86 04 movl $0x8048636,0x4(%esp)
804847d: 08
804847e: c7 04 24 30 84 04 08 movl $0x8048430,(%esp)
8048485: e8 36 ff ff ff call 80483c0 <__monstartup@plt>
804848a: c7 04 24 b0 83 04 08 movl $0x80483b0,(%esp)
8048491: e8 1a 01 00 00 call 80485b0 <atexit>
8048496: 83 c4 1c add $0x1c,%esp
8048499: c3 ret
804849a: 90 nop
804849b: 90 nop
804849c: 90 nop
804849d: 90 nop
コンパイルされたhello
プログラムに__gmon_start__
が存在すると、その__monstartup
が呼び出されていることがわかります。 ( monstartupのマニュアルページ )
-pg
なし:
akyserr@orion:~$ readelf -r hello
Relocation section '.rel.dyn' at offset 0x290 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x298 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000107 R_386_JUMP_SLOT 00000000 puts
0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__
0804a008 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main
ここで、__gmon_start__
のシンボル値が00000000
に設定されていることがわかります。