(g)libc を使用せずに C コードをコンパイルしたいと考えています。どうすれば非アクティブ化でき、どの機能がそれに依存していますか?
-nostdlib を試しましたが、役に立ちません。コードはコンパイル可能で実行可能ですが、実行可能ファイルの 16 進ダンプで libc の名前を見つけることができます。
コードを でコンパイルすると-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()
は使用できないため、インライン アセンブリを使用してシステム コールを直接呼び出します。
最も簡単な方法は、C コードをオブジェクト ファイルにコンパイルし (gcc -c
いくつかのファイルを取得するため*.o
)、それらをリンカーで直接リンクすることです ( ld
)。オブジェクト ファイルをいくつかの追加のオブジェクト ファイルとリンクする必要があります。たとえば/usr/lib/crt1.o
、動作する実行可能ファイルを取得するためです (カーネルから見たエントリ ポイントとmain()
関数の間には、少し作業が必要です)。何とリンクするかを知るには、 を使用して glibc とリンクしてみてくださいgcc -v
。
gcc が生成するコードは、いくつかの隠し関数に依存している可能性があります。それらのほとんどはにありますlibgcc.a
。また、libc に含まれるmemcpy()
、memmove()
、memset()
およびへの隠し呼び出しが存在する可能性memcmp()
があるため、独自のバージョンを提供する必要がある場合があります (少なくとも、パフォーマンスにこだわりすぎない限り、これは難しくありません)。
生成されたアセンブリ (フラグを使用)を見ると、状況がより明確になる場合があります。-S