Il tuo programma avrà (come minimo) bisogno di collegarsi a un caricatore per l'esecuzione. Considera il seguente codice banale:
tpost@tpost-desktop:~$ cat count.c
int main(void)
{
unsigned int i;
for (i = 0; i < 10; i++) {;;}
return 0;
}
Ora lo compiliamo:
tpost@tpost-desktop:~$ gcc -Wall -o count count.c
E ora esaminiamo cosa ha fatto il linker:
linux-gate.so.1 => (0x002b5000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00482000)
/lib/ld-linux.so.2 (0x00241000)
Version information:
./count:
libc.so.6 (GLIBC_2.0) => /lib/tls/i686/cmov/libc.so.6
/lib/tls/i686/cmov/libc.so.6:
ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
Di interesse è il fatto che ldd
non ha trovato file fisico per linux-gate.so.1
e ld-linux.so.2
, questo perché entrambi sono virtual oggetti dinamici condivisi che risiedono in ogni spazio di indirizzamento del processo . Gli oggetti condivisi sono esposti dal kernel e contengono il codice necessario per caricare effettivamente il programma, che funziona in congiunzione con la libreria C del sistema.
Colleghiamo staticamente questo, vogliamo?
tpost@tpost-desktop:~$ gcc -static -Wall -o count count.c
tpost@tpost-desktop:~$ ldd -v count
not a dynamic executable
Non ho eliminato la dipendenza di collegamento qui, tutto ciò che ho fatto è stato preso il codice del loader e la libreria del sistema C e li ho resi parte dell'eseguibile. Sembra un po 'sciocco, perché il mio eseguibile non usa più una copia perfettamente valida di quel codice che è già in memoria.
Potresti scrivere il tuo codice loader e non usare quello fornito dalla libreria C di sistema, ma non perderete le dipendenze dal caricatore del kernel stesso.
Questo è un esempio molto orientato a Linux, ma è tutto ciò che ho a disposizione per illustrare il punto:)