web-dev-qa-db-fra.com

Compiler sans libc

Je veux compiler mon code C sans la (g) libc. Comment puis-je le désactiver et quelles fonctions en dépendent?

J'ai essayé -nostdlib mais cela n'aide pas: le code est compilable et s'exécute, mais je peux toujours trouver le nom de la libc dans le hexdump de mon exécutable.

52
u149796

Si vous compilez votre code avec -nostdlib, Vous ne pourrez pas appeler de fonctions de bibliothèque C (bien sûr), mais vous n'obtiendrez pas non plus le C bootstrap En particulier, le véritable point d'entrée d'un programme sous Linux n'est pas main(), mais plutôt une fonction appelée _start(). Les bibliothèques standard fournissent normalement une version de ceci qui exécute une certaine initialisation code, puis appelle main().

Essayez de compiler ceci avec gcc -nostdlib -m32:

void _start() {

    /* main body of program: call main(), etc */

    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
}

La fonction _start() doit toujours se terminer par un appel à exit (ou à tout autre appel système non retourné tel que exec). L'exemple ci-dessus appelle l'appel système directement avec l'assembly en ligne car la fonction exit() habituelle n'est pas disponible.

67
ataylor

Le moyen le plus simple est de compiler le code C en fichiers objets (gcc -c Pour obtenir des fichiers *.o), Puis de les lier directement avec l'éditeur de liens (ld). Vous devrez lier vos fichiers objets avec quelques fichiers objets supplémentaires tels que /usr/lib/crt1.o Afin d'obtenir un exécutable fonctionnel (entre le point d'entrée, vu par le noyau, et la main() fonction, il y a un peu de travail à faire). Pour savoir avec quoi lier, essayez de lier avec la glibc, en utilisant gcc -v: Cela devrait vous montrer ce qui vient normalement dans l'exécutable.

Vous constaterez que gcc génère du code qui peut avoir des dépendances avec quelques fonctions cachées. La plupart d'entre eux sont en libgcc.a. Il peut également y avoir des appels masqués à memcpy(), memmove(), memset() et memcmp(), qui sont dans la libc, vous devrez donc fournir vos propres versions (ce qui n'est pas difficile, du moins tant que vous n'êtes pas trop pointilleux sur les performances).

Les choses peut-être deviennent parfois plus claires si vous regardez l'assemblage produit (utilisez le drapeau -S).

6
Thomas Pornin