Kompilieren ohne libc

Lesezeit: 4 Minuten

Benutzeravatar von u149796
u149796

Ich möchte meinen C-Code ohne die (g)libc kompilieren. Wie kann ich es deaktivieren und welche Funktionen hängen davon ab?

Ich habe -nostdlib versucht, aber es hilft nicht: Der Code ist kompilierbar und läuft, aber ich kann immer noch den Namen der libc im Hexdump meiner ausführbaren Datei finden.

  • -nostdlib sollte es tun, welche Plattform/Compiler-Version verwenden Sie?

    – Karl Norum

    30. März 2010 um 20:36 Uhr

  • “hilft nicht”, da dies die Bibliothek nicht deaktiviert hat, oder Sie konnten mit diesem Flag nichts kompilieren?

    – Josh Lee

    30. März 2010 um 20:47 Uhr

  • Sie möchten wahrscheinlich auch -nostartupfiles.

    Benutzer1831086

    30. März 2010 um 22:03 Uhr

  • blog.ksplice.com/2010/03/libc-free-world hat eine sehr gute Beschreibung der präzisen Steuerung der programmatischen Ausgabe des gcc. Bearbeiten: Sie (ksplice) haben gerade Teil 2 des obigen Tutorials / Leitfadens veröffentlicht. Sehen Sie es hier: blog.ksplice.com/2010/04/libc-free-world-2 Dies betrifft hauptsächlich Linker-Einstellungen, um unnötige Flusen aus Dateien zu entfernen.

    – Adam Schiemke

    31. März 2010 um 1:18 Uhr


  • Es gibt keine Option -nostartupfiles. Sie meinen wahrscheinlich -nostartfiles, was bereits durch -nostdlib impliziert wird.

    – ataylor

    31. März 2010 um 18:24 Uhr

Benutzeravatar von ataylor
ataylor

Wenn Sie Ihren Code mit kompilieren -nostdlib, können Sie (natürlich) keine C-Bibliotheksfunktionen aufrufen, aber Sie erhalten auch nicht den regulären C-Bootstrap-Code. Insbesondere ist dies nicht der eigentliche Einstiegspunkt eines Programms unter Linux main()sondern eine aufgerufene Funktion _start(). Die Standardbibliotheken stellen normalerweise eine Version davon bereit, die einen Initialisierungscode ausführt und dann aufruft main().

Versuchen Sie, dies mit zu kompilieren gcc -nostdlib -m32:

// Tell the compiler incoming stack alignment is not RSP%16==8 or ESP%16==12
__attribute__((force_align_arg_pointer))
void _start() {

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

    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
    __builtin_unreachable();  // tell the compiler to make sure side effects are done before the asm statement
}

Das _start() Die Funktion sollte immer mit einem Aufruf von enden exit (oder andere nicht zurückkehrende Systemaufrufe wie z exec). Das obige Beispiel ruft den Systemaufruf wie üblich direkt mit Inline-Assemblierung auf exit() ist nicht verfügbar.

  • Für 64 Bit muss der Assembler-Code so aussehen: asm("mov rax,60; mov rdi,0; syscall").

    – Sigal

    3. Mai 2016 um 18:03 Uhr

  • Hinzufügen zu @sigalors Kommentar, um damit zu kompilieren gcc Sie müssen die AT&T-Syntax verwenden, also sollte dies wie folgt aussehen: asm(mov $60,%rax; mov $0,%rdi; syscall)

    – Lanox

    11. Mai 2016 um 11:59 Uhr

  • @ataylor: Warum sollte die Funktion _start() immer mit dem Aufruf von exit() enden? Was ist, wenn ich exit() nicht in die Funktion start() schreibe?

    – Destruktor

    25. Mai 2017 um 5:52 Uhr

  • @Destructor auf meinem System hängt es für ein paar Sekunden, dann segfaults.

    – Mondkind

    15. August 2017 um 23:18 Uhr

  • Beachten Sie, dass der Stapel bei der Eingabe anders ausgerichtet ist _start: keine Rücksprungadresse auf dem Stack, also immer noch 16-Byte-ausgerichtet. GCC geht jedoch davon aus, dass es sich um eine normale Funktion handelt, und verletzt daher die ABI, wenn andere Funktionen aufgerufen werden. Verwenden -mincoming-stack-boundary=2 für diese Datei (Dokumente) um GCC mitzuteilen, dass der Stapel beim Funktionseintrag möglicherweise nur 4-Byte-ausgerichtet ist, oder vielleicht ein __attribte__((target("something"))) nur auf _start

    – Peter Cordes

    2. Juni 2020 um 12:59 Uhr

Der einfachste Weg ist, den C-Code in Objektdateien zu kompilieren (gcc -c Um Etwas zu bekommen *.o Dateien) und dann direkt mit dem Linker verlinken (ld). Sie müssen Ihre Objektdateien mit einigen zusätzlichen Objektdateien verknüpfen, z /usr/lib/crt1.o um eine funktionierende ausführbare Datei zu erhalten (zwischen dem Einstiegspunkt, wie er vom Kernel gesehen wird, und der main() Funktion, es gibt ein wenig Arbeit zu tun). Um zu wissen, womit Sie verknüpfen müssen, versuchen Sie, mit der glibc zu verknüpfen, indem Sie verwenden gcc -v: Dies sollte Ihnen zeigen, was normalerweise in die ausführbare Datei kommt.

Sie werden feststellen, dass gcc Code generiert, der einige Abhängigkeiten zu einigen versteckten Funktionen haben kann. Die meisten sind dabei libgcc.a. Es kann auch versteckte Anrufe geben memcpy(), memmove(), memset() und memcmp()die sich in der libc befinden, daher müssen Sie möglicherweise Ihre eigenen Versionen bereitstellen (was nicht schwierig ist, zumindest solange Sie nicht zu wählerisch in Bezug auf die Leistung sind).

Dinge könnte wird manchmal klarer, wenn Sie sich die produzierte Baugruppe ansehen (verwenden Sie die -S Flagge).

  • Ich muss _start anstelle von main verwenden, aber wenn ich versuche, eine libc-Funktion aufzurufen, beschwert sich gcc nicht. Verschwindet der libc-Link, wenn ich alle libc-Aufrufe entferne?

    – u149796

    1. April 2010 um 7:50 Uhr

  • Nicht direkt. Wenn du es versuchst gcc -vdu wirst das sehen gcc gibt dem Linker einige Objektdateien (die *.o). Der Linker schließt alle ihm übergebenen Objektdateien ein. “Verschwinden” tritt nur bei Bibliotheken auf (*.a), da es sich um Repositorys von Objektdateien handelt, die der Linker verwenden oder nicht verwenden kann.

    – Thomas Pornin

    1. April 2010 um 13:37 Uhr

1417300cookie-checkKompilieren ohne libc

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy