Die Startadresse ist die Adresse von main()
, richtig?
Nicht wirklich: Der Start eines Programms ist nicht wirklich main()
. Standardmäßig erstellt GCC ausführbare Dateien, deren Startadresse dem _start
Symbol entspricht. Sie können das sehen, indem Sie a objdump --disassemble Q1
. Hier ist die Ausgabe eines einfachen Programms von mir, das nur return 0;
in main()
:
0000000000400e30 <_start>:
400e30: 31 ed xor %ebp,%ebp
400e32: 49 89 d1 mov %rdx,%r9
400e35: 5e pop %rsi
400e36: 48 89 e2 mov %rsp,%rdx
400e39: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
400e3d: 50 push %rax
400e3e: 54 push %rsp
400e3f: 49 c7 c0 a0 15 40 00 mov $0x4015a0,%r8
400e46: 48 c7 c1 10 15 40 00 mov $0x401510,%rcx
400e4d: 48 c7 c7 40 0f 40 00 mov $0x400f40,%rdi
400e54: e8 f7 00 00 00 callq 400f50 <__libc_start_main>
400e59: f4 hlt
400e5a: 66 90 xchg %ax,%ax
400e5c: 0f 1f 40 00 nopl 0x0(%rax)
Wie Sie an der Adresse sehen können 400e54
, wird _start()
wiederum aufgerufen __libc_start_main
, wodurch das erforderliche Material (pthreads, atexit, ...) initialisiert und schließlich main()
mit den entsprechenden Argumenten (argc, argv und env) aufgerufen wird .
Okay, aber was hat das mit der Änderung der Startadresse zu tun?
Wenn Sie gcc
nach einer statischen Verknüpfung fragen , bedeutet dies, dass die gesamte oben erwähnte Initialisierung mithilfe von Funktionen erfolgen muss, die in der ausführbaren Datei enthalten sind. Wenn Sie sich die Größe beider ausführbarer Dateien ansehen, werden Sie feststellen, dass die statische Version viel größer ist. In meinem Test beträgt die statische Version 800 KB, während die freigegebene Version nur 6 KB beträgt.
Die zusätzlichen Funktionen werden zufällig vor platziert _start()
, daher die Änderung der Startadresse. Hier ist das Layout der statischen ausführbaren Datei start()
:
000000000049e960 r translit_from_tbl
0000000000400a76 t _i18n_number_rewrite
0000000000400bc0 t fini
0000000000400bd0 t init_cacheinfo
0000000000400e30 T _start
0000000000400e60 t deregister_tm_clones
0000000000400e90 t register_tm_clones
0000000000400ed0 t __do_global_dtors_aux
Und hier ist das Layout der gemeinsam genutzten ausführbaren Datei:
00000000004003c0 T _start
00000000004003f0 t deregister_tm_clones
00000000004004b0 T main
00000000004004c0 T __libc_csu_init
00000000006008a0 B _end
0000000000400370 T _init
Als Ergebnis erhalte ich leicht unterschiedliche Startadressen: 0x400e30 im statischen Fall und 0x4003c0 im gemeinsam genutzten Fall.