リンカ基本事項 シンボルの導入

前回リンクについて軽くまとめたが、リンクする際にはリンカが必要なわけだが、リンカはどのような処理を行っているのかをまとめてみた。

まず大きく分けてリンカが行っていることは以下の二つである。

  • オブジェクトファイルをまとめて一つの実行ファイルにする
  • ラベルの参照を解決してアドレスを決定する

まずオブジェクトファイルには機械語とデータ以外に、シンボル情報とリロケーション情報が含まれている。このシンボルは、アセンブリで言うところのラベルであり、アセンブルする際にシンボルへと変換される。シンボルは定義ずみシンボルと未定義シンボルの二つに分けられる。

  • 定義ずみシンボル:アセンブリでラベルで表されるもので、ファイル内に実体があるシンボルのこと。ファイル内のオフセット、追加情報、文字列表現の情報などを持つ。
  • 未定義シンボル:オブジェクトファイルに実体が存在しないシンボルのことで、追加情報や文字列表現の情報は持つが、ファイル内のオフセットに関する情報は持たない。

以下のアセンブリアセンブルしてオブジェクトファイルを作り、中身をobjdumpで確認してみる。

 .globl    _start
    .globl    sym0
_start:
    nop

sym0:
    nop
sym1:
    nop
    nop
    nop
    nop
sym2:
    nop
$ objdump -d hoge.s

hoge.o: file format mach-o 64-bit x86-64

Disassembly of section __TEXT,__text:

0000000000000000 <_start>:
       0: 90                            nop

0000000000000001 <sym0>:
       1: 90                            nop

0000000000000002 <sym1>:
       2: 90                            nop
       3: 90                            nop
       4: 90                            nop
       5: 90                            nop

0000000000000006 <sym2>:
       6: 90                            nop

シンボル値として_start, sym0, sym1, sym2が現れていることが見て取れる。

このオブジェクトファイルのシンボルの種類などをreadelfコマンドで確認しようとしたが、エラーを吐いてしまった。原因は以下のようにMac上で作成されるオブジェクトファイルはELFではなく、Mach-Oという形式であるからだ。この形式については、第12回 Universal Binary【前編】:Undocumented Mac OS X(3/5 ページ) - ITmedia エンタープライズで確認してもらいたい。

$ file hoge.o
hoge.o: Mach-O 64-bit object x86_64

そこでLinux環境で実行してみる。

$ readelf -s hoge.o
Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000002     0 NOTYPE  LOCAL  DEFAULT    1 sym1
     5: 0000000000000006     0 NOTYPE  LOCAL  DEFAULT    1 sym2
     6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 _start
     7: 0000000000000001     0 NOTYPE  GLOBAL DEFAULT    1 sym0

Valueというのがファイル内のオフセット、SizeとTypeカラムはデバッグ情報にも使えるカラムを表す。Bindカラムでシンボルが、グローバルシンボル・ローカルシンボル・エクスポートシンボルのどれであるかを表している。ローカルシンボルとはファイル内でのみ参照できるシンボルのことである。逆にいうとグローバルシンボルは外部ファイルからも参照できるシンボルである。エクスポートシンボルとは共有ライブラリを作る時などに用いられるシンボルで、実行時にもファイルを超えて参照される参照される定義ずみシンボルのことである。VisカラムがDEFAULTだとエクスポートシンボルであるらしい。

とりあえず今回はここまでで次回以降、さらに詳しくまとめていくつもりだ。

参照

  • リンカ: 今回かなり参照したサイトで、より詳しい情報を知りたかったらこちらのサイトを見てみることをおすすめする。
  • リンカーとライブラリ: こちらはリンカについて調べていたらたまたま見つけたサイトだが、リンカにについて非常に詳しくまとめられている。