web-dev-qa-db-ja.com

libcなしでコンパイルする

(g)libcなしでCコードをコンパイルしたい。無効にするにはどうすればよいですか、またどの機能に依存していますか?

-nostdlibを試しましたが、役に立ちません。コードはコンパイル可能で実行されますが、実行可能ファイルのhexdumpでlibcの名前を見つけることができます。

52
u149796

-nostdlibを使用してコードをコンパイルすると、Cライブラリ関数を呼び出すことはできません(もちろん)が、通常のC bootstrap= code特に、Linux上のプログラムの実際のエントリポイントはmain()ではなく、_start()という関数です。標準ライブラリは通常、初期化コードを実行するこのバージョンを提供します。 main()を呼び出します。

gcc -nostdlib -m32でこれをコンパイルしてみてください:

void _start() {

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

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

_start()関数は、常にexit(またはexecなどの他の非リターンシステムコール)の呼び出しで終了する必要があります。上記の例は、通常のexit()が利用できないため、インラインアセンブリを使用してシステムコールを直接呼び出します。

67
ataylor

最も簡単な方法は、Cコードをオブジェクトファイル(_gcc -c_にコンパイルして_*.o_ファイルを取得)し、それらをリンカー(ld)に直接リンクすることです。実行可能な実行可能ファイル(カーネルから見たエントリポイントとmain()関数の間)を取得するには、オブジェクトファイルを_/usr/lib/crt1.o_などのいくつかの追加オブジェクトファイルとリンクする必要があります。 、やることが少しあります)。リンクする対象を知るには、_gcc -v_を使用してglibcとリンクしてみてください。これにより、通常実行可能ファイルに含まれるものが表示されます。

Gccが生成するコードは、いくつかの隠された関数に依存する場合があります。それらのほとんどは_libgcc.a_にあります。 memcpy()memmove()memset()、およびmemcmp()への非表示呼び出しもあります。これらはlibcにあるため、独自のバージョンを提供します(少なくともパフォーマンスにあまりこだわりがない限り、これは難しくありません)。

物事might生成されたアセンブリを見ると、時々明確になります(_-S_フラグを使用します)。

6
Thomas Pornin