Solaris 移行ガイド

第 15 章 コンパイラ、リンカ、デバッガ

この章では、コンパイラ、リンカ、デバッガについて説明します。この章の内容は次のとおりです。

コンパイラ

SunOS 4 から Solaris 7 に移行する開発者にとって最も大きな変更点は、C コンパイラがバンドルされなくなったことです。コンパイラをバンドルしない理由の 1 つに、動的なカーネルがあります。動的なカーネルでは、必要に応じて自動的にデバイスが追加されるので、カーネルの再構築にコンパイラを使用する必要がありません。

Sun WorkShop(TM) には、ANSI C 互換コンパイラのほか、拡張されたデバッグ機能とプログラム開発環境があります。このコンパイラは、Solaris 7 のネイティブオブジェクト形式である 実行形式リンク形式から成る ELF 形式で実行可能ファイルを作成します。lint と lint ライブラリも Sun WorkShop の一部として提供されています。 lintlint ライブラリも Sun WorkShop の一部として提供されます。

Sun WorkShop については、http://www.sun.com にアクセスしてください。

Making the Transition to ANSI C』は、バンドル製品の SunOS 4 C コンパイラとアンバンドル製品の Sun WorkWhop C コンパイラのそれぞれによって実装される C 言語の違いを解説しています。一方のコンパイラ用のソースを他方に移植するときに参照してください。このマニュアルは、http://docs.sun.comSun WorkShop Compiler C 4.2 AnswerBook Collection で閲覧できます。

Sun WorkShop C コンパイラのオプションフラグ -Xs は、K&R C と ANSI C で動作が異なる言語構成要素について警告します。この特別なフラグについては、『C User's Guide』を参照してください。このマニュアルは、http://docs.sun.comSun WorkShop Compiler C 4.2 AnswerBook Collection でも閲覧できます。

リンカ

このリリースではリンクエディタ ld(1) に対していくつかの変更があります。最も重要な変更は新しい ELF のファイルフォーマットを処理する機能です。


注 -

ライブラリと実行可能プログラムを構築するには、リンカを直接起動することよりもコンパイラドライバによる方法をお勧めします。コンパイラは、リンカが必要とする多数のファイルを自動的に供給します。


ライブラリを混合することはできません - 32 ビットプログラムは 32 ビットライブラリ、64 ビットプログラムは 64 ビットライブラリとリンクする必要があります。ELF32 オブジェクトは他の ELF32 オブジェクト、ELF64 オブジェクトは他の ELF64 オブジェクトとリンクします。

リンクエディタオプションの相違

新しいリンカでリネームされたオプションもあれば同じものもあり、また不要になったオプションもあります。表 15-1 では SunOS 4 の ld を Solaris 7 の ld コマンドと比較します。

表 15-1 に続く節で、リンク作業がオプションの相違によってどのように影響を受けるかについて説明します。

表 15-1 ld オプションの比較

SunOS 4 のオプション 

Solaris 7 での変更 

注 

-align datum

-M mapfile

mapfile と異なるセクションの使用

-assert definitions

デフォルト 

 

-assert nodefinitions

-znodefs

警告ではなく重大なエラーを発行 

-assert nosymbolic

-zdefs

警告ではなく重大なエラーを発行 

-assert pure-text

-ztext

警告ではなく重大なエラーを発行 

-A name

変更なし 

dlopen(3X)dlclose(3X) はこの動作に接近可能

-Bdynamic

-Bdynamic

共用ライブラリの取り込みにのみ適用される。動的にリンクされた実行可能プログラムを構築するには -dy (デフォルト) を使用。「実行可能ファイルの作成」を参照。

-Bnosymbolic

-zdefs

 

-Bstatic

-dn & -Bstatic

動的なリンカを完全に除去するには、-dn オプションを指定しなければならない。アーカイブライブラリを取り込むために動的モードで -Bstatic を使用 (トグルとして使用。「実行可能ファイルの作成」を参照)。

-Bsymbolic

-Bsymbolic

このオプションを付けて-assert nosymbolic も取得する。

-d -dc -dp

デフォルト 

オフに設定するには、SVR4 で -b オプションを使用しなければならない。

-D hex

-M mapfile

mapfile には、希望する結果を達成するためにいろいろなメカニズムが含まれる。

-e entry

-e entry

 

no -e

-G

共有オブジェクトを作成する。 

-lx[.v]

-lx

共用ライブラリのメジャー番号が示すバージョンだけが現在サポートされている。 

-Ldir

-Ldir

dir は実行可能プログラムに記録されない。かわりに、-R オプションを使用。

-M

-m

 

-n

デフォルト 

SVR4 の実行可能プログラムのフォーマットは、ディスクイメージを -n として圧縮

-N

変更なし  

 

-o name

-o name

 

-p

デフォルト 

-M mapfile で取り消し可能。

-r

-r

 

-S

変更なし 

 

-s

-s

 

-t

変更なし  

 

-T hex

-M mapfile

mapfile には、希望する結果を達成するためにいろいろなメカニズムが含まれる。

-Tdata hex

-M mapfile

mapfile には、希望する結果を達成するためにいろいろなメカニズムが含まれる。

-u name

-u name

 

-x

変更なし  

 

-X

変更なし  

 

-y sym

変更なし 

 

-z

デフォルト 

-z としての SVR4 実行可能プログラムフォーマットのデマンドページ

共用ライブラリの作成

Solaris 7 で共用ライブラリを作成するには、-G オプションを指定する必要があります。SunOS 4 では、-e オプションなしの場合、共用ライブラリを作成することをリンカが自分で判断します。Solaris 7 では共用ライブラリがエントリポイントを持つ可能性があるため、このオプションは使用できなくなりました。

実行可能ファイルの作成

-Bdynamic-Bstatic オプションはまだ利用できますが、その動作はかなり異なります。現在では、これらのオプションは実行可能バインディングではなくライブラリのインクルードを指します。実行可能バインディングは、Solaris 7 で新しい -dy-dn オプションでのみ排他的に設定されます。-dy オプションがデフォルトです。これは、動的にリンクされた実行可能ファイルを作成するために必要です。-dn オプションは、静的にリンクされた実行可能ファイルを作成するために必要です。

-Bdynamic-Bstatic オプションは、-dy オプションを使用したときだけ適用されます。 -Bdynamic はリンクエディタに共用ライブラリを含めるように指示し、-Bstatic はアーカイブライブラリを含めるように指示します。これらのオプションは、次の -Bdynamic または -Bstatic オプション指定が現れるまで、-l 引数を管理する切り替え (トグル) として機能します。

次の例に、同様の実行可能プログラムを作成するのに使用できる SunOS 4 と Solaris 7 コマンドを示します。

ライブラリ検索パスの指定

SunOS 4 では、-L オプションを付けて指定したディレクトリはリンク時に検索され、その情報は実行時に使用するために保持されていました。この動作は現在では、 -L-R オプションに分けられています。 -L オプションはリンク時に検索するディレクトリを指定し、-R オプションはリンカに対して、実行時に使用するために保持する検索パスを指示します。詳細については、「検索パスの規則」を参照してください。

-Bdynamic-Bstatic オプションと同様に、 -L オプションの位置には意味があります。これは、それに続く -l オプションにだけに適用されます。

検索パスの規則

動的リンカと実行時リンカが SunOS 4 リンカによって使用されたのとは異なるアルゴリズムを使って検索パスを決定します。

以下の例では、SunOS 4 と Solaris 7 の動的リンカおよび実行時リンカの検索パスを比較します。Solaris 7 では、リンクエディタと実行時リンカの検索パスは LD_LIBRARY_PATH 設定値の影響を受けることに注意してください。ただし、実行時リンカでは、プログラムが LD_LIBRARY_PATH を設定しないで共用ライブラリを検索できるほか、共用ライブラリのローディングがさらに効率的になります。したがって、Solaris 7 では $ORIGIN を代用することをお勧めします。prog がインストールされた位置からの組み込みライブラリの相対パスを指定してプログラムをビルドしなければならないからです。 たとえば、.../package/bin/prog は、.../package/lib/libmine.so.1 を使用します。

SunOS 4 リンカ検索パス

LD_LIBRARY_PATH=dirlist1 がある Solaris 7 リンカ検索パス

LD_LIBRARY_PATH=dirlist1, dirlist2) がある Solaris 7 リンカ検索パス

Solaris 7 リンカは、$ORIGIN を使ってパスを検索します。

また、Solaris 7 では、LD_LIBRARY_PATH_ 64LD_LIBRARY_PATH の 64 ビット専用バージョンです。

バージョン番号

SunOS 4 は、共用ライブラリに対してメジャーとマイナーの両方のバージョン番号をサポートしていました。Solaris 7 は、メジャーバージョン番号だけをサポートします。バイナリ互換性のサポートについては、メジャーおよびマイナーバージョン番号は SunOS 4 共用ライブラリで認識されます。これらのライブラリは、SunOS 4 ソフトウェアにあったのと同じメジャーおよびマイナーバージョン番号を保持するために必要となります。

表 15-2 は、SunOS 4 および Solaris 7 の共用ライブラリのバージョンを示します。

表 15-2 共用ライブラリの例

SunOS 4 

Solaris 7 

libc.so.1.7

libc.so.1

libdl.so.1.0

libdl.so.1

SunOS 4 システムソフトウェアにおいては、 -l オプションを指定した場合、build environment linker はメジャーおよびマイナー番号をともに持つライブラリを検索しました。たとえば、-ldl を指定した場合、ライブラリ、libdl.so.1.0 がリンクされます。Solaris 7 環境では、メジャー番号はサポートされていますが、デフォルトのリンクエディタはバージョン番号を無視します。前の例では、build envrionment linker は現在では libdl.so と特定のバージョンのファイルを指すシンボリックリンクを検索します。

リンカによって参照された時、デフォルトでは、動的に実行可能なオブジェクトまたは共有オブジェクト中の dependency レコードは関連する共有オブジェクトのファイル名です。依存性の指定をより一貫した方法にするために、共有オブジェクトは実行時に参照されるべきファイル名をそれ自身に記録することができます。これはライブラリファイルをリンクする時に -h オプションによって指定します。

Solaris 7 では、シンボリックリンクはほとんどのライブラリに対して作成されています。メジャー番号をつけて新しい共用ライブラリを構築し、それから最もよく使用するライブラリのバージョンを指すシンボリックリンクを作成してください。

新しいユーティリティの dump(1) (「ファイルのバックアップと復元」を参照) により、オブジェクトファイルのデバッグ、または静的および動的リンクのチェックが容易になります。dump -L オプションは、実行可能プログラムに含まれる実行時リンカに必要な情報を表示します。この情報は、ELF ファイルの動的セクションに含まれます。 RPATH エントリは、ld. の -R オプションにより指定された検索パスを表示します。

例を以下に示します。


examples% cc -G -o libx.so.1 -h libx.so.1 libx.o

examples% cp libx.so.1 /mylibs
examples% ln -s /mylibs/libx.so.1 /mylibs/libx.so
examples% dump -Lv libx.so.1

libx.so.1:

  **** DYNAMIC SECTION INFORMATION ****
.dynamic :
[INDEX] Tag      Value
[1]     INIT     0x3b8
[2]     FINI     0x3f4
[3]     SONAME   libx.so.1
[4]     HASH     0x94
[5]     STRTAB   0x33c
[6]     SYMTAB   0x14c
[7]     STRSZ    0x62
[8]     SYMENT   0x10
[9]     PLTGOT   0x10404
[10]    PLTSZ    0xc
[11]    PLTREL   0x7
[12]    JMPREL   0x3ac
[13]    RELA     0x3a0
[14]    RELASZ   0x18
[15]    RELAENT  0xc

ライブラリが他の動的ライブラリを必要とするときは、次の例に示すように、RPATH と共に動的ライブラリを指定するようにします。

次の例では prog.c をコンパイルし、(前の例で構築された) libx.so を動的にリンクし、バイナリが実行のためカレントディレクトリ情報を保持するように指定します。この例は、コンパイル済みプログラムの prog.c についての dump 出力を示します。ここで、前の例の SONAME フィールドに格納された情報は、prog により NEEDED として示されます。prog が実行されると、libx.so.1 は、libx.so でも、異なるバージョンにリンクされます。


examples% cc -o prog prog.c -L/mylibs -R/mylibs -lx
example% dump -Lv prog

prog:

  **** DYNAMIC SECTION INFORMATION ****
.dynamic :
[INDEX]   Tag   Value
[1]  NEEDED   libx.so.1
[2]  NEEDED   libc.so.1
[3]  INIT     0x1b1ac
[4]  FINI     0x1b248
[5]  RPATH    /mylibs
[6]  HASH     0x100e8
[7]  STRTAB   0x17f90
[8]  SYMTAB   0x12be0
[9]  STRSZ    0x31e1
[10] SYMENT   0x10
[11] DEBUG    0x0
[12] PLTGOT   0x2b25c
[13] PLTSZ    0x30
[14] PLTREL   0x7
[15] JMPREL   0x1b180
[16] RELA     0x1b174
[17] RELASZ   0x3c
[18] RELAENT  0xc

デバッガ

この節ではデバッグツールの変更について説明します。

dbxdbxtool

dbxdbxtool は、デフォルトのシステムソフトウェアには含まれません。アンバンドル製品の Sun WorkShop には、これらの改良版が含まれています。

adbkadb

adbkadb は、Solaris 7 オペレーティングシステムにバンドルされていて、SunOS 4 のツールと同じ機能を提供します。kadb はマルチプロセッサで使用できるよう改良されました。kadb のプロンプトにはプロセッサ ID が表示されます。以下の例では、プロセッサ ID が 0 になっています。

Solaris 7 環境で容易にカーネルのデバッグを行うには、次のようにします。

adb は、64 ビット用として次のように拡張されています。

kadb マクロ

以下の kadb マクロは、マルチスレッドカーネルといっしょに使用すると特に有効です。

現在のスレッドを表示します。現在のスレッドポインタは、SPARC グローバルレジスタ g7 です。

kadb[0]: <g7$<thread

threadlist は、システム内のすべてのカーネルスレッドのスタックトレースを表示します。このリストは非常に長くなることがあります。

kadb[0]: $<threadlist

mutex は、所有スレッドのアドレスを表示します。この例では、グローバルで危険なドライバ mutex を使用しています。

kadb[0]: unsafe_driver$<mutex

kadb[0]: moddebug/W 0x80000000

moddebug は、モジュールのロードを監視できるようにします。デバッグ専用に使用する moddebug の有効な値については、<sys/modctl.h> の最後を参照してください。

動作中のカーネルのデバッグ

稼働中のカーネルをデバッグするには、次のコマンドを使用します。


# adb -k /dev/ksyms /dev/mem

/dev/ksyms は、稼働中のカーネルの完全な名前を含む擬似デバイスです。

truss コマンド

truss は、実行したシステムコール、受信シグナル、ハードウェア障害などを追跡するために開発された新しいユーティリティです。truss には、 エントリを有効にして追跡対象のプロセスで実行されたユーザーレベルの関数呼び出しを終了するオプションのほか、フォークされたプロセスの追跡やマルチスレッドプロセスの処理のように SunOS 4 の trace(1) コマンドにない大幅な改良も加えられています。

また、truss は、プロセスのシステムコール、シグナル、ハードウェア障害を追跡します。このユーティリティには、エントリを有効にして、追跡対象のプロセスで実行されたユーザーレベルの関数呼び出しの追跡を終了する新しいオプションが追加されています。

次の例は、date コマンドの追跡結果を要約したものです。-c オプションを指定すると、truss は行単位の追跡を表示せず、システムコール、シグナル、フォルトの回数をカウントして、その合計を表示します。


example% truss -c date
Fri Sep 18 14:31:30 PDT 1992
syscall      seconds   calls  errors
_exit            .00       1
read             .00       7
write            .00       1
open             .03      12
close            .00      12
time             .00       1
brk              .01       4
lseek            .00       1
fstat            .00       4
ioctl            .00       1
execve           .00       1
mmap             .01      17
munmap           .00       8
                ----     ---    ---
sys totals:      .05      70      0
usr time:        .03
elapsed:         .28

truss オプションの詳細については、truss(1) のマニュアルページを参照してください。Solaris 7 ではこの他に pmap(1) のような proc(4) を基本としたデバッグツールが数多く用意されています。