gccは3つの主要なステップからなる

gccは3つの主要なステップからなる

1. Cのソースをアセンブリに変換

  • gccはC compilerを呼び出し,それが.cをターゲットマシンのアセンブリコードの.sに変換する
  • C compilerは前処理,lexical 解析,parse,code生成などのフェーズを持つ

2. assembly codeをobject codeに変換

  • すべてのコンピュータは自身のマシン命令を持つ.Assemblerはassembly codeをバイナリの機械語に変換するプログラム
  • 結果の.oファイルはOBJECT codeと呼ばれる.
  • gccの第二ステップは.sを.oに変換するASSEMBLERを呼び出すこと
  • 各.o ファイルは次を含む
    • headerセクション: code, data,BSS のサイズ
    • DATAセクション: マシン命令
    • BSSセクション: 初期化されたglobal変数と初期化されたstatic local変数
    • CODE中のポインタのためのrelocation 情報とDATAとBSSのオフセット
    • non-static globalを含むsymbol table,関数名,それらの属性

3. LINKする

  • プログラムは互いに依存する複数の.oファイルからなることがあり,ccの最後のステップはLinkerですべての.oファイルと必要なライブラリを結合して一つのbinary executableにすること
  • 具体的には,
    • .oファイルのすべてのCODEセクションを一つのcode sectionにする
      • Cプログラムでは結合されたCode sectionはデフォルトCスタートアップコードcrt0.oで始まり,それがmian()を呼ぶ.(これがmain()がなければならない理由)
    • すべてのDATA secitonを一つのData sectionに結合する.結合されたdata sectionは初期化されたglobal変数と初期化されたstatic local変数のみを含む
    • すべてのBSSセクションを一つのbssセクションに結合する
    • .oファイルのrelocation情報を使って結合されたcode section中のpointersと結合されたDataとbss sectionのoffsetsを調節
      • symbol tableを使い,個別の.oファイルのcross referenceを解決する.例えば,compilerがc = mysum(a,b)をt1.cで見ても,mysumがどこにあるかわからない.そこで,compilerはt1.oに空白(ゼロ)をmysynのentry addressとして残しておいて,symbol tableに記録する
      • linkerがt1.oとt2.oを結合したときlinkerは,combined Code sectionでmysumの場所を知る
      • t1.oのblankをmysumのエントリアドレスで埋める
      • 他のcross referenceされたsymbolも同様.
      • static globalsはsymbol tableにはないので,linkerは利用できない.
      • 異なるファイルからreference static globalsを参照するいかなる試みもreference errorを出す
      • .oファイルがundefined なシンボルや関数名を参照していれば,linkerはcross reference errorを出す
      • すべてのcross referenceが解決されれば,linkerは結果を結合されたファイルにa.outとして書く.これはバイナリ実行ファイルである.

K.C.Wang, Systems Programming in Unix/Linux, 2018, pp.28-29, Springer, https://www.springer.com/gp/book/9783319924281