Solaris Application Binary Interface (ABI) はアプリケーション開発者用のインタフェースを定義します。この ABI に準拠することによって、アプリケーションのバイナリの安定性が強化されます。この章では、Solaris ABI についてと、アプリケーションが Solaris ABI に準拠しているかどうかを確認するためのツールについて説明します。
Solaris ABI の定義と目的については、Solaris ABI の定義を参照してください。
2 つの ABI ツール appcert および apptrace の使用方法については、Solaris ABI ツールを参照してください。
Solaris ABI とは、アプリケーションが Solaris オペレーティングシステムで利用できる (つまり、サポートされる) 実行時インタフェースセットのことです。ABI の最も重要な構成要素は次のとおりです。
Solaris システムライブラリが提供するインタフェース (マニュアルページの 3 章を参照)
Solaris カーネルシステムコールが提供するインタフェース (マニュアルページの 2 章を参照)
さまざまなシステムファイルとシステムディレクトリの場所と形式 (マニュアルページの 4 章を参照)
Solaris ユーティリティの入出力用の構文と意味論 (マニュアルページの 1 章を参照)
Solaris ABI の中心となる構成要素はシステムライブラリインタフェースセットです。この章では、「ABI」という用語はこのような構成要素だけを指します。Solaris オペレーティングシステムがインタフェースを提供するのは C 言語だけであるので、この ABI が持っているのも C 言語用のインタフェースだけです。
Solaris API (Application Programming Interface) 向けに作成された C ソースコードは C コンパイラによってバイナリに変換されます。このとき、バイナリはプラットフォームによって、3 つの ABI バージョン (32 ビット SPARC、64 ビットSPARC、または 32 ビットIntel) のうちの1 つになります。ABI は API とよく似ていますが、ソースをコンパイルするプロセスにいくつかの違いがあります。次に、違いについて説明します。
コンパイラ指令 (#define など) はソースレベルの構成を変更または置換する可能性があります。結果として、ソースに存在していたシンボルがバイナリに存在しなかったり、ソースに存在していなかったシンボルがバイナリに存在することがあります。
コンパイラはプロセッサ固有のシンボル (算術命令など) を生成することがあり、ソースレベルの構成を変更または置換する可能性があります。
コンパイラのバイナリレイアウトは、そのコンパイラと、コンパイラが受け入れるソース言語のバージョンに固有になることがあります。このような場合、同じコードを異なるコンパイラでコンパイルすると、互換性のないバイナリが生成される可能性があります。
このような理由のため、異なる Solaris リリースでコンパイルした場合、ソースレベル (API) では互換性があっても、バイナリレベルでは十分な互換性を得られません。
Solaris ABI は、オペレーティングシステムが提供する、サポートされるインタフェースから構成されます。システムで利用できるインタフェースの中には、オペレーティングシステムが排他的に使用することを目的としているインタフェースもあります。このような排他的なインタフェースは、アプリケーションでは使用できません。SunOS 5.6 より前のリリースでは、アプリケーション開発者は Solaris ライブラリのすべてのインタフェースを利用できていました。Solaris リンクエディタのライブラリシンボル有効範囲の手法を使用すると、ライブラリの外では使用する予定がないインタフェースの有効範囲をライブラリのローカルだけに縮小できます。詳細については、『リンカーとライブラリ』 を参照してください。ただし、システム要件のため、必ずしもすべての非公開インタフェースがこのように有効範囲を縮小できるわけではありません。このようなインタフェースには「private」というラベルが付いてあり、Solaris ABI には含まれていません。
Solaris ABI は Solaris ライブラリで定義されています。このような定義は、リンクエディタと実行時リンカーで使用されるライブラリバージョンの手法と方針によって行われます。
Solaris リンクエディタと実行時リンカーは、ファイルバージョン管理とシンボルバージョン管理の 2 種類のライブラリバージョン管理を使用します。ファイルバージョン管理では、ライブラリの名前にバージョン番号が追加されます (たとえば、libc.so.1)。このようなライブラリにある 1 つまたは複数の公開インタフェースに互換性のない変更を行ったとき、バージョン番号はインクリメントされます (たとえば、libc.so.2)。動的にリンクされるアプリケーションでは、構築時にバインドしたシンボルが実行時にライブラリに存在しないことがあります。シンボルのバージョンを管理するために、Solaris リンカーはシンボルのセットに名前を関連付けます。Solaris リンカーは次に、実行時のリンク中、その名前がライブラリに存在するかどうかを確認して、関連付けたシンボルが存在することを検証します。
ライブラリシンボルバージョン管理では、シンボルのセットにシンボルバージョン名を関連付け、その名前に番号付けスキーマがある場合は、マップファイルを使用して番号を関連付けます。次の例は、架空の Sun ライブラリ libfoo.so.1 のマップファイルです。
SUNW_1.2 { global: symbolD; symbolE } SUNW_1.1; SUNW_1.1 { global: symbolA; symbolB; symbolC; }; SUNWprivate { global: __fooimpl; local: *; };
このマップファイルでは、symbolA、symbolB、および symbolC がバージョン SUNW_1.1 に関連付けられ、symbolD および symbolE が SUNW_1.2 に関連付けられています。そして、SUNW_1.2 が SUNW_1.1 に関連付けられたすべてのシンボルを継承することを意味します。シンボル __fooimpl は、継承チェーンを持たない異なる名前付きセット SUNWprivate に関連付けられています。
構築時、リンクエディタはアプリケーションが使用しているシンボルを調査します。リンクエディタは次に、これらのシンボルが依存しているアプリケーションにセット名を記録します。(番号付け継承) チェーンを持っているセットの場合、リンクエディタは、アプリケーションが使用するすべてのシンボルが含まれる最小限の名前付きセットを記録します。例えばアプリケーションが symbolA および symbolB だけを使用する場合、リンクエディタは SUNW_1.1 への依存関係を記録します。また、アプリケーションが symbolA、symbolB、および symbolD を使用する場合、SUNW_1.2 は SUNW_1.1 を取り込んでいるためリンクエディタは SUNW_1.2 への依存関係を記録します。
実行時、リンカーは、依存関係としてアプリケーションに記録されたバージョン名がリンクされるライブラリに存在しているかどうかをチェックします。このプロセスによって、必要なシンボルが存在しているかどうかをすばやく確認できます。詳細については、『リンカーとライブラリ』を参照してください。
マップファイル内の「local:*」指令は、ライブラリ内のシンボルのうち、明示的に名前付きセットに関連付けられていないシンボルの有効範囲はライブラリにローカルであることを意味します。 つまり、このように有効範囲がローカルに制限されたシンボルはライブラリの外からは見えないことを意味します。この規約は、シンボルが見えるのは、シンボルバージョン管理名に関連付けられているときだけであることを保証します。
ライブラリ内のシンボルのうち、表示できるシンボルはなんらかの名前付きセットに属しているので、名前付けスキーマを使用すると、シンボルの ABI 状態にラベルを付けることができます。このラベル付けを行うには、すべての非公開インタフェースを SUNWprivate から始まるセット名に関連付けます。公開インタフェースはほかの名前から始まり、特に、次のような名前があります。
SYSVABI - System V ABI 定義で定義されたインタフェース用
SISCD - SPARC International の『SPARC Compliance Definition』で定義されたインタフェース用
SUNW - Sun Microsystems で定義されたインタフェース用
このような公開名前付きセットには major.minor 番号付けスキーマによって番号が付け られます。minor 番号は、新しいシンボルが名前付きセットに追加されるたびにインクリメントされます。既存のシンボルに互換性のない変更が行われたときにそのシンボルが含まれるセットの major 番号がインクリメントされます。既存のシンボルに互換性のない変更が行われたときは、ライブラリのファイル名のバージョン番号もインクリメントされます。
したがって、Solaris ライブラリ ABI の定義はライブラリに含まれており、SUNWprivate から始まらないシンボルバージョン名に関連付けられたシンボルセットから構成されます。pvs コマンドは、ライブラリ内にあるシンボルの一覧を表示します。
Solaris インタフェースを使用するアプリケーションが Solaris ABI に準拠しているかどうかを確認するために、Solaris オペレーティング環境は 2 つのツールを提供します。appcert ユーティリティは、ELF バイナリが使用している Solaris ライブラリインタフェースの非公開インタフェースのインスタンスの使用状況について静的に調査します。 次に、appcert ユーティリティは潜在的なバイナリ安定性の問題について、要約レポートと詳細レポートを生成します。apptrace ツールは実行時リンカーのリンク監査機能を使用して、アプリケーションを実行しながら動的に Solaris ライブラリルーチン呼び出しをトレースします。この機能によって、開発者は、アプリケーションが Solaris システムインタフェースを使用しているかどうかを調査できます。
ABI ツールを使用すると、特定の Solaris リリースで互換性の問題が存在するバイナリをすばやく簡単に識別できます。バイナリ安定性を確認するには、次のようにします。
現在の Solaris リリース上で appcert を使用して、問題のあるバイナリを選別します。バイナリが、問題のあるインタフェースを使用しているか否かを識別できます。
ターゲットの Solaris リリース上で apptrace を使用して、問題が存在するかどうかを確認します。インタフェースを使用しながら動的に観察することによって、インタフェース互換性の問題が存在するかどうかを確認できます。
appcert ユーティリティは、ELF バイナリを静的に調査して、使用されているライブラリシンボルを特定の Solaris リリースにおける公開インタフェースまたは非公開インタフェースのモデルに対して比較する Perl スクリプトです。appcert ユーティリティは SPARC またはIntel のどちらのプラットフォーム上でも動作します。appcert ユーティリティはさらに、SPARC と Intel の32 ビットインタフェースだけではなく、SPARC の 64 ビットインタフェースの使用状況も確認できます。appcert ユーティリティは C 言語インタフェースだけを調査することに注意してください。
新しい Solaris リリースが入手可能になると、いくつかのライブラリインタフェースは動作が変わったり、完全になくなったりします。すると、このようなインタフェースに依存するアプリケーションの性能に影響を与えることがあります。Solaris ABI は、アプリケーションが安全かつ安定して使用できる実行時ライブラリインタフェースを定義します。appcert ユーティリティは、アプリケーションが Solaris ABI に準拠していることを開発者が確認できるように設計されています。
アプリケーションを調査するとき、appcert ユーティリティは次のことを確認します。
非公開シンボルの使用
静的なリンク
非結合シンボル
非公開シンボルとは、Solaris ライブラリがお互いを呼び出すときに使用する関数またはデータのことです。非公開シンボルの意味論的な動作は変更されることがあり、ときには、削除されることもあります。このようなシンボルのことを「降格シンボル」と呼びます。非公開シンボルは変更されやすいので、非公開シンボルに依存しているアプリケーションには潜在的に安定性に問題があります。
Solaris ライブラリ間で非公開シンボルを呼び出すとき、その意味論はリリースごとに変わる可能性があります。したがって、アーカイブに静的にリンクすると、アプリケーションのバイナリ安定性が低下します。この問題を回避するためには、このようなアーカイブに対応する共有オブジェクトファイルに動的にリンクすることが必要です。
アプリケーションを調査するとき、appcert ユーティリティは動的リンカーを使用してアプリケーションが使用するライブラリシンボルを解決します。このとき、動的リンカーが解決できないシンボルのことを「非結合シンボル」と呼びます。非結合シンボルの原因には、LD_LIBRARY_PATH 環境変数が正しく設定されていないなどの環境の問題があります。非結合シンボルの原因にはまた、コンパイル時に -l lib または -z のスイッチの定義を省略したなどの構築時の問題もあります。ただしこのような例はまれで、多くの場合 appcert が非結合シンボルを報告するときは、存在しない非公開シンボルに依存しているなど、より深刻な問題が発生していることになります。
appcert ユーティリティで調査しているオブジェクトファイルがライブラリに依存する場合、このような依存関係をオブジェクトに記録しておく必要があります。このような依存関係をオブジェクトに記録するには、コードをコンパイルするときに、コンパイラの -l スイッチを使用します。オブジェクトファイルがほかの共有ライブラリに依存する場合、appcert ユーティリティを実行するときに、このような共有ライブラリには LD_LIBRARY_PATH または RPATH 経由でアクセスできる必要があります。
マシンが 64 ビットの Solaris カーネルを実行していなければ、appcert ユーティリティは 64 ビットアプリケーションを確認できません。Solaris では 64 ビットの静的ライブラリが提供されていないため、appcert は 64ビットアプリケーションの静的リンクを確認しません。
appcert は次のことを確認できません。
完全または部分的に静的にリンクされているオブジェクトファイル。完全に静的にリンクされているオブジェクトは「unstable (安定していない)」と報告される
実行権が設定されていない実行可能ファイル。appcert ユーティリティはこのような実行可能ファイルをスキップする。実行権が設定されていない共有オブジェクトは通常どおりに確認する
ユーザー ID が root に設定されているオブジェクトファイル
ELF 以外の実行可能ファイル (シェルスクリプトなど)
C 言語以外の言語の Solaris インタフェース。コードは C 言語である必要はないが、Solaris ライブラリへの呼び出しは C 言語を使う必要がある
appcert を使用して、利用しているアプリケーションを確認するには、次のように入力します。
appcert object|directory |
object|directory は次のどちらかです。
appcert で調査したいオブジェクトの完全な一覧
このようなオブジェクトが格納されているディレクトリの完全な一覧
appcert ユーティリティは、アプリケーションを実行する環境とは異なる環境で実行する場合もあります。このような環境では、appcert ユーティリティは Solaris ライブラリインタフェースへの参照を正しく解決できないことがあります。
appcert は Solaris 実行時リンカーを使用して、実行可能ファイルまたは共有オブジェクトファイルごとにインタフェース依存関係のプロファイルを構築します。このプロファイルを使用すると、アプリケーションが依存している Solaris システムインタフェースを判断できます。このプロファイルに記述されている依存関係を Solaris ABI と比較すると、Solaris ABI への準拠を確認できます。このプロファイルには、非公開インタフェースが見つかってはなりません。
appcert はディレクトリを再帰的に検索して、ELF 以外を無視しながら、オブジェクトファイルを探します。アプリケーションの確認が終了すると、appcert は長いレポートを標準出力 (通常は画面) に出力します。このレポートは、作業用ディレクトリ (通常は /tmp/appcert.pid) のReport という名前のファイルに書き込まれます。このサブディレクトリ名の pid は 1 から 6 桁の数字であり、appcert の当該インスタンスのプロセス ID を示します。appcert が出力ファイルを書き込むディレクトリ構造の詳細については、appcert の結果を参照してください。
次のオプションで、appcert の動作を変更できます。次のオプションは、コマンド行において appcert コマンドから object|directory オペランドの間のどこにでも入力できます。
appcert ユーティリティをバッチモードで実行します。
バッチモードでは、appcert は確認するバイナリごとに 1 行をレポートに書き込みます。
PASS で始まる行は、その行が示すバイナリには appcert の警告が発行されなかったことを意味します。
FAIL で始まる行は、その行が示すバイナリに問題が見つかったことを意味します。
INC で始まる行は、その行が示すバイナリが完全には確認できなかったことを意味します。
ファイル infile には、確認すべきファイルの一覧がファイル名ごとに 1 行ずつ書き込まれている必要があります。このファイルで指定されたファイルは、コマンド行に指定されたファイルに追加されます。このスイッチを使用する場合、オブジェクトまたはディレクトリをコマンド行に指定する必要はありません。
appcert の使用方法を出力します。
デフォルトでは、appcert はアプリケーション内にあるすべての共有オブジェクトを記して、このような共有オブジェクトが入っているディレクトリを LD_LIBRARY_PATH に追加しますが、-L スイッチはこの動作を無効にします。
デフォルトでは、ディレクトリを検索して確認すべきバイナリを探すとき、appcert はシンボリックリンクに従います。-n スイッチはこの動作を無効にします。
Solaris ライブラリディレクトリ /usr/openwin/lib および /usr/dt/lib を LD_LIBRARY_PATH に追加します。
ライブラリ構成要素を実行するディレクトリを指定します。このスイッチを指定した場合、appcert は一時ファイルをこのディレクトリに作成します。このスイッチを指定しない場合、appcert は一時ファイルを /tmp ディレクトリに作成します。
appcert を使用すると、指定されたセットの中でどのアプリケーションが潜在的に安定性の問題を持っているかをすばやく簡単に識別できます。appcert が何も安定性の問題を報告しなかった場合、そのアプリケーションは、以降の Solaris リリースでもバイナリ安定性問題は検証されにくいと考えられます。次の表に、よくあるバイナリ安定性問題の一覧を示します。
表 11–1 よくあるバイナリ安定性問題
問題 |
回避方法 |
---|---|
ある非公開シンボルを使用しているが、変更されることがわかっている |
このようなシンボルの使用をすぐに停止する |
ある非公開シンボルを使用しているが、まだ変更されていない |
今のところアプリケーションは動作しているが、このようなシンボルの使用をできるだけ早く停止する |
あるライブラリに静的にリンクしているが、同等な共有オブジェクトを入手できる |
代わりに、同等な共有オブジェクトを使用する |
あるライブラリに静的に共有しているが、同等な共有オブジェクトを入手できない |
可能であれば、ld -z allextract を使用して、.a ファイルを .so ファイルに変換する。変換できない場合、共有オブジェクトが利用できるようになるまで、静的なライブラリを使用し続ける |
ある非公開シンボルを使用しているが、同等な公開シンボルを入手できない |
Sun に連絡して、公開インタフェースを要求する |
あるシンボルを使用しているが、評判が悪いか、削除されることが計画されている |
今のところアプリケーションは動作しているが、このようなシンボルの使用をできるだけ早く停止する |
ある公開シンボルを使用しているが、すでに変更されている |
コンパイルし直す |
リリースによっては、非公開インタフェースを使用することによる潜在的な安定性の問題が発生しないこともあります。なぜなら、リリースが変わっても、非公開インタフェースの動作が変更されるとは限らないためです。ターゲットリリースで非公開インタフェースの動作が変更されているかどうかを確認するには、apptrace を使用します。apptrace の使用方法については、apptrace によるアプリケーションの確認を参照してください。
appcert ユーティリティがアプリケーションのオブジェクトファイルを解析した結果は、appcert ユーティリティの作業用ディレクトリ (通常は /tmp) にあるいくつかのファイルに書き込まれます。作業用ディレクトリの下にあるメインサブディレクトリは appcert.pid です。このとき、pid は appcert の当該インスタンスのプロセス ID です。appcert ユーティリティの結果は、次のファイルに書き込まれます。
確認されたバイナリ間のマッピングと、当該バイナリに固有な appcert の出力が格納されているサブディレクトリ名が書き込まれる
appcert を実行したときに stdout に出力されたレポートのコピーが書き込まれる
appcert が確認しようとしたが強制的にスキップされたバイナリの一覧と、各バイナリがスキップされた理由が書き込まれる。スキップされる理由には次のようなものが挙げられる
ファイルがバイナリオブジェクトではない
当該ユーザーではファイルを読み取ることができない
ファイル名にメタキャラクタが含まれている
ファイルの実行ビットが設定されていない
objects サブディレクトリの下には、appcert が確認するオブジェクトごとのサブディレクトリが作成される。サブディレクトリごとに、次のようなファイルが格納される
check.demoted.symbols |
Solaris 降格シンボルであると appcert が疑っているシンボルの一覧 |
|
check.dynamic.private |
オブジェクトが直接バインドされている Solaris 非公開シンボルの一覧 |
|
check.dynamic.public |
オブジェクトが直接バインドされている Solaris 公開シンボルの一覧 |
|
check.dynamic.unbound |
ldd -r を実行したときに、動的リンカーによってバインドされなかったシンボルの一覧。ldd が戻す行には、「file not found 」も含まれる |
|
summary.dynamic |
appcert が調査したオブジェクト内にある動的バインドの要約がプリンタ形式で書き込まれる (各 Solaris ライブラリから使用される公開シンボルと非公開シンボルのテーブルも含まれる) |
appcert は終了するときに、次の 4 つのうちの 1 つを返します。
appcert はバイナリ安定性問題の潜在的な原因を見つけなかった。
appcert は正常に実行されなかった。
appcert が確認した一部のオブジェクトにバイナリ安定性問題が見つかった。
appcert が確認すべきバイナリオブジェクトが見つからなかった。
非公開シンボルの使用 – 開発したときの Solaris リリースとは異なる Solaris リリース上で実行しようとすると、非公開シンボルに依存するアプリケーションは動作しない可能性があります。これは、非公開シンボルはSolaris リリース間で変更または削除される可能性があるためです。アプリケーション内で非公開シンボルが使用されていることを appcert が報告した場合は、非公開シンボルを使用しないようにアプリケーションを再作成してください。
降格シンボル – 降格シンボルとは、後の Solaris リリースにおいて削除された、あるいは、有効範囲がローカルに制限された Solaris ライブラリの関数またはデータ変数のことです。このようなシンボルを直接呼び出すアプリケーションは、ライブラリが当該シンボルをエクスポートしないリリース上では動作できません。
非結合シンボル – 非結合シンボルとは、アプリケーションが参照するライブラリシンボルのうち、appcert によって呼び出されたときに動的リンカーが解決できなかったライブラリシンボルのことです。非結合シンボルは必ずしも常にバイナリ安定性が低いことを示す指標ではありませんが、降格シンボルへの依存関係など、より深刻な問題が発生していることを示す場合もあります。
廃止ライブラリ – 廃止ライブラリとは、将来のリリースで Solaris オペレーティング環境から削除される可能性があるライブラリのことです。appcert ユーティリティは廃止ライブラリのすべての使用に対して警告を発します。廃止ライブラリに依存するアプリケーションは、将来のリリースでサポートされなくなり、機能しなくなる可能性があります。廃止ライブラリのインタフェースを使用しないでください。
sys_errlist または sys_nerr の使用 – sys_errlist シンボルおよび sys_nerr シンボルを使用すると、バイナリ安定性が低下する可能性があります。これは、sys_errlist 配列の終わりを越えた参照が行われる可能性があるためです。代わりに strerror を使用してください。
強いシンボルと弱いシンボルの使用 – 将来の Solaris リリースで動作が変更される可能性があるので、弱いシンボルに関連付けられた強いシンボルは非公開シンボルとして予約されます。アプリケーションは弱いシンボルに直接参照する必要があります。強いシンボルの例としては、弱いシンボル socket に関連付けられた _socket があります。
apptrace は、アプリケーションを実行しながら動的に Solaris ライブラリルーチンへの呼び出しをトレースする C 言語のプログラムです。apptrace ユーティリティは SPARC またはIntel のどちらのプラットフォーム上でも動作します。apptrace ユーティリティは、SPARC と Intel の32 ビットインタフェースだけではなく、SPARC の 64 ビットインタフェースへのインタフェース呼び出しをトレースできます。ただし appcert と同様に、apptrace が調査するのは C 言語のインタフェースだけです。
appcert を使用してアプリケーションのバイナリ安定性低下の危険性を判断した後は、apptrace を使用して各ケースの危険度を評価します。apptrace を使用すると、アプリケーションが 各インタフェースを正しく使用しているかどうかを確認し、特定のリリースとのバイナリ互換性を判断できます。
apptrace を用いると、アプリケーションが公開インタフェースを正しく使用しているかどうかを確認できます。たとえば、システム管理ファイル /etc/passwd を開くとき、アプリケーションは open() を使用するのではなく、適切なプログラマティックインタフェースを使用する必要があります。このような Solaris ABI を正しく使用しているかどうかを検査 できる機能を使用すると、潜在的なインタフェースの問題をすばやく簡単に識別できます。
apptrace を実行するとき、トレースするアプリケーションは何も変更する必要がありません。apptrace を使用するには、まず apptrace を入力し、次に希望のオプションを入力、最後に対象となるアプリケーションを実行するコマンド行に入力します。apptrace は実行時リンカーのリンク監査機能を使用して、アプリケーションによる Solaris ライブラリインタフェースへの呼び出しを遮断します。次に、apptrace は呼び出しをトレースして、呼び出しの引数と戻り値についての名前と値を出力します。トレースは単一の行に出力することも、読みやすさのために複数の行に分けて出力することも可能です。公開インタフェースは人が読める形式で出力されます。非公開インタフェースは 16 進数で出力されます。
apptrace は、個々のインタフェースとライブラリの両方のレベルで、トレースする呼び出しを選択できます。たとえば、apptrace は libnsl から printf() への呼び出しをトレースできるし、特定のライブラリ内にあるすべての printf() 呼び出しをトレースすることもできます。apptrace はまた、ユーザーが指定した呼び出しを詳細にもトレースできます。apptrace の動作を規定する仕様は、truss(1) の使用方法と整合性がある構文によって規定されます。-f オプションを指定すると、apptrace はフォークされた子プロセスもトレースします。-o オプションを指定すると、apptrace は -o に指定されたファイルに結果を出力します。
apptrace がトレースするのはライブラリレベルの呼び出しだけであり、また、実行中のアプリケーションのプロセスにロードされるので、truss よりも性能が上がります。しかし、printf は例外ですが apptrace は可変引数リストを受け入れたり、スタックなどの呼び出し側の情報を調査したりする関数への呼び出しをトレースできません (たとえば、setcontext、 getcontext、setjmp、longjmp、および vfork)。
次は、apptrace で単純な 1 バイナリアプリケーション ls をトレースしたときの出力例です。
% apptrace ls /etc/passwd ls -> libc.so.1:atexit(func = 0xff3cb8f0) = 0x0 ls -> libc.so.1:atexit(func = 0x129a4) = 0x0 ls -> libc.so.1:getuid() = 0x32c3 ls -> libc.so.1:time(tloc = 0x23918) = 0x3b2fe4ef ls -> libc.so.1:isatty(fildes = 0x1) = 0x1 ls -> libc.so.1:ioctl(0x1, 0x540d, 0xffbff7ac) ls -> libc.so.1:ioctl(0x1, 0x5468, 0x23908) ls -> libc.so.1:setlocale(category = 0x6, locale = "") = "C" ls -> libc.so.1:calloc(nelem = 0x1, elsize = 0x40) = 0x23cd0 ls -> libc.so.1:lstat64(path = "/etc/passwd", buf = 0xffbff6b0) = 0x0 ls -> libc.so.1:acl(pathp = "/etc/passwd", cmd = 0x3, nentries = 0x0, aclbufp = 0x0) = 0x4 ls -> libc.so.1:qsort(base = 0x23cd0, nel = 0x1, width = 0x40, compar = 0x12038) ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 ls -> libc.so.1:strlen(s = "") = 0x0 ls -> libc.so.1:strlen(s = "/etc/passwd") = 0xb ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 ls -> libc.so.1:strlen(s = "") = 0x0 ls -> libc.so.1:printf(format = 0x12ab8, ...) = 11 ls -> libc.so.1:printf(/etc/passwd format = 0x12abc, ...) = 1 ls -> libc.so.1:exit(status = 0) |
上記例は、ls /etc/passwd というコマンド上で、すべてのライブラリ呼び出しをトレースしたときのデフォルトのトレース動作を示しています。apptrace はシステムコールごとに、次のような情報を含む 1 行を出力します。
システムコールの名前
システムコールが属するライブラリ
システムコールの引数と戻り値
% apptrace -t \*printf ls /etc/passwd ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 ls -> libc.so.1:printf(format = 0x12ab8, ...) = 11 ls -> libc.so.1:printf(/etc/passwd format = 0x12abc, ...) = 1 |
上記例は、正規表現を使用することによって、apptrace がトレースする呼び出しを選択する方法を示しています。この例では、前の例と同じ ls コマンド上で、printf で終わるインタフェース (sprintf も含まれる) への呼び出しをトレースします。 この結果、apptrace は printf および sprintf への呼び出しだけをトレースします。
% apptrace -v sprintf ls /etc/passwd ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 buf = (char *) 0x233d0 "" format = (char *) 0x12af8 "%s%s%s" ls -> libc.so.1:sprintf(buf = 0x233d0, format = 0x12af8, ...) = 0 buf = (char *) 0x233d0 "" format = (char *) 0x12af8 "%s%s%s" /etc/passwd |
上記例は、詳細トレースモードを示しており、読みやすさのために、sprintf への引数が複数の行に出力されています。最後に、apptrace は ls コマンドの出力を表示します。