71

(g)libc を使用せずに C コードをコンパイルしたいと考えています。どうすれば非アクティブ化でき、どの機能がそれに依存していますか?

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

4

2 に答える 2

86

コードを でコンパイルすると-nostdlib、(もちろん) C ライブラリ関数を呼び出すことはできませんが、通常の C ブートストラップ コードも得られません。特に、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()は使用できないため、インライン アセンブリを使用してシステム コールを直接呼び出します。

于 2010-03-30T20:48:09.170 に答える
9

最も簡単な方法は、C コードをオブジェクト ファイルにコンパイルし (gcc -cいくつかのファイルを取得するため*.o)、それらをリンカーで直接リンクすることです ( ld)。オブジェクト ファイルをいくつかの追加のオブジェクト ファイルとリンクする必要があります。たとえば/usr/lib/crt1.o、動作する実行可能ファイルを取得するためです (カーネルから見たエントリ ポイントとmain()関数の間には、少し作業が必要です)。何とリンクするかを知るには、 を使用して glibc とリンクしてみてくださいgcc -v

gcc が生成するコードは、いくつかの隠し関数に依存している可能性があります。それらのほとんどはにありますlibgcc.a。また、libc に含まれるmemcpy()memmove()memset()およびへの隠し呼び出しが存在する可能性memcmp()があるため、独自のバージョンを提供する必要がある場合があります (少なくとも、パフォーマンスにこだわりすぎない限り、これは難しくありません)。

生成されたアセンブリ (フラグを使用)を見ると、状況より明確になる場合があります。-S

于 2010-03-30T20:44:45.920 に答える