Con un programma come
int main()
{
return 0;
}
- e ti colleghi in modo statico, qualche libreria sul tuo sistema sarà collegata al binario finale.
- e ti colleghi dinamicamente, una libreria verrà caricata durante l'esecuzione?
In sostanza, una libreria è sempre necessaria anche per i programmi più semplici, se sì perché? Lo chiedo perché pensavo che il punto di ingresso canonico per tutto ciò che vuole essere eseguito sia in realtà _start (che pensavo fosse in una libreria, ovvero glibc). Forse non capisco cosa fa realmente _start per quanto riguarda l'impostazione delle cose, quindi anche eventuali suggerimenti sarebbero utili.
Risposta accettata:
Se vuoi scrivere il tuo programma in C portatile standard, hai ovviamente bisogno di un po' di runtime che chiami main()
funzione in primo luogo.
Ma se non ti interessa, puoi fare a meno di qualsiasi libreria ed eseguire chiamate di sistema direttamente tramite l'assemblaggio in linea. Per esempio. per x86-64:
$ cat q.c
#include <sys/syscall.h>
void _start(void){
__asm__( "syscall" : : "D"(0), "a"(SYS_exit) );
}
$ cc -O2 -static -nostdlib -nostartfiles -Wall q.c -o q
$ strace ./q
execve("./q", ["./q"], 0x7fffc72d8d20 /* 39 vars */) = 0
exit(0) = ?
+++ exited with 0 +++
Devi fare almeno una chiamata di sistema, ovvero _exit(2)
, a meno che l'arresto anomalo dell'uscita non sia accettabile per un "programma più semplice", nel qual caso andrà bene anche un file vuoto;-):
$ > foo.c
$ cc -static -nostdlib -nostartfiles -Wall foo.c -o ./foo
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
$ ./foo
Segmentation fault
Ho pensato che il punto di ingresso canonico per tutto ciò che vuole essere eseguito sia in realtà _start
non c'è niente di canonico in questo; _start
è il nome predefinito che verrà utilizzato dal linker; puoi puntarlo altrove con il -e sym
opzione (-Wl,-e,sym
con gcc
).