Auswirkung statischer und dynamischer Verlinkung auf die Startadresse

Auswirkung statischer und dynamischer Verlinkung auf die Startadresse

Ich habe ein einfaches C-Programm. Ich führe aus:

$ gcc Q1.c -Wall -save-temps -o Q1

Dann prüfe ich die generierte ausführbare Datei:

$  objdump -f Q1
Q1:     file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080483b0

Dann kompiliere ich es mit statischer Verknüpfung:

$ gcc Q1.c -Wall -save-temps -static -o Q1

und überprüfen Sie die Datei erneut:

$ objdump -f Q1
Q1:     file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048e08

Welchen Einfluss hat das statische und dynamische Linken auf die Startadresse des Programms? Die Startadresse ist doch die Adresse von main(), oder?

Antwort1

Die Startadresse ist die Adresse von main(), richtig?

Nicht wirklich: Der Start eines Programms ist nicht wirklich main(). Standardmäßig erzeugt GCC ausführbare Dateien, deren Startadresse dem _startSymbol entspricht. Sie können dies sehen, indem Sie ein ausführen objdump --disassemble Q1. Hier ist die Ausgabe eines einfachen Programms von mir, das nur return 0;in ausgeführt wird 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, _start()ruft wiederum auf __libc_start_main, das die notwendigen Dinge (pthreads, atexit, ...) initialisiert und schließlich main()mit den entsprechenden Argumenten (argc, argv und env) aufruft.

Okay, aber was hat das mit der Änderung der Startadresse zu tun?

Wenn Sie gcceine statische Verknüpfung anfordern, bedeutet dies, dass die gesamte Initialisierung, die ich oben erwähnt habe, mithilfe von Funktionen durchgeführt werden muss, die sich in der ausführbaren Datei befinden. Und tatsächlich, wenn Sie sich die Größe beider ausführbaren Dateien ansehen, werden Sie feststellen, dass die statische Version viel größer ist. Bei meinem Test ist die statische Version 800 KB groß, während die gemeinsam genutzte Version nur 6 KB groß ist.

Die zusätzlichen Funktionen wurden zufällig vor platziert _start(), daher die Änderung der Startadresse. Hier ist das Layout der statischen ausführbaren Datei um 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 gemeinsamen Fall.

verwandte Informationen