チュートリアルに従って、自分のOS用にNewLibを移植しています。
crt0を終了したら、「最初のオブジェクトとしてリンクする」必要があると書かれています。どうやってやるの?
チュートリアルに従って、自分のOS用にNewLibを移植しています。
crt0を終了したら、「最初のオブジェクトとしてリンクする」必要があると書かれています。どうやってやるの?
crt0を終了したら、「最初のオブジェクトとしてリンクする」必要があると書かれています。
それは正確に言うことを意味します。OSのアプリケーションがリンクされている場合、crt0は、リンカーのコマンドラインの最初のオブジェクトファイルである必要があります。他のオブジェクトファイルの前です。
従来、UNIXリンカは、最初のオブジェクト/ライブラリから最後のオブジェクト/ライブラリにループオーバーしてルックアップを行うことにより、シンボルを解決します。最初のオブジェクトファイルとして配置すると、システムシンボル(関数、変数)が他のファイルではなくcrt0crt0
ファイルから選択されるようになります。
さらに、R ..が指摘しているように、従来のリンカは、アプリケーションのエントリポイントがコードセグメントの先頭にあると想定しています。これは、リンク先のページにあるソースコードにも当てはまります。コードの最初の記号は_start
、プログラムのエントリポイントの通常の名前です。
たとえばgcc -v a.c -o a
、Debianで実行している場合(に注意して-v
ください)、次のリンクコマンドが表示されます(読みやすくするために新しい行を追加しました)。
/usr/lib/gcc/i486-linux-gnu/4.4.4/collect2
--build-id
--eh-frame-hdr
-m elf_i386
--hash-style=both
-dynamic-linker /lib/ld-linux.so.2
-o a
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crti.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtbegin.o
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib
-L/lib/../lib
-L/usr/lib/../lib
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../..
/tmp/ccndJ4YV.o
-lgcc
--as-needed
-lgcc_s
--no-as-needed
-lc
-lgcc
--as-needed
-lgcc_s
--no-as-needed
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crtn.o
crt1がコマンドラインの最初のオブジェクトであることがわかります。リンカースクリプト(私のシステムでは-m elf_i386
-> ->)を見ると、Linuxにはがないことを確認できますが、:、、、、、があります。また、アプリケーションオブジェクトファイル(上記のサンプル)は、との間に配置されます。find /usr -name '*elf_i386*'
/usr/lib/ldscripts/elf_i386.x
crt0
crt1
crti
crtbegin
crtend
crtn
/tmp/ccndJ4YV.o
crtbegin
crtend
にジャンプする前にmain()
、cランタイムは初期化を行う必要があります。このジョブは。によって処理されcert{i,n,0}
ます。
少なくともテストするための1つの方法は、crt0.oをコンパイラまたはリンカのコマンドラインの最初のファイルとして配置することです。
本番環境では、リンカーコマンドファイルに配置します。