elfedit - ELF ファイルの検査または編集
elfedit [-adrV] [-e cmd] [-L path] [-o default | simple | canon | num] [infile] [outfile]
elfedit は、既存の ELF オブジェクトの内容を検査または変更するためのツールです。ELF ヘッダー、セクションヘッダーテーブル、プログラムヘッダーテーブル、動的セクション、ハードウェアおよびソフトウェア機能、文字列テーブル、シンボルテーブルなどの、オブジェクトに含まれているほとんどの ELF データへのアクセスが提供されます。
elfedit は、コマンド行 (–e オプション) または標準入力からのコマンドを処理します。標準入力が端末である場合、elfedit では端末編集機能のほか、広範囲のコマンド完了が提供されます。ELF では、特殊な整数値やビットマスクのために多くの標準の記号名が使用されます。elfedit は、このような名前に関する、可能性のあるほとんどの完了を認識します。elfedit コマンドの入力中はいつでも TAB キーを押すことができ、それにより、elfedit は現在のカーソル位置にあるテキストの使用法に関するメッセージや既知の完了を表示します。
elfedit の機能は、モジュールの形式で構成されています。各モジュールは、関連する機能に焦点を絞った一連のコマンドを提供します。コマンドは、モジュールとコマンド名をコロン (:) の区切り記号で結合する (空白は入れない) ことによって指定されます。たとえば、dyn:runpath は、dyn モジュールによって提供される runpath コマンドを示します。モジュール名は一意である必要があります。特定のモジュール内のコマンド名はそのモジュール内では一意ですが、その同じコマンド名を複数のモジュールで使用できます。
一部のモジュールでは、コマンドの 1 つが、そのモジュールのデフォルトコマンドとして指定されます。このコマンドは、ユーザーがモジュール名のみを指定した場合に実行されます。ほとんどの elfedit モジュールでは、そのモジュールがサポートする ELF ファイルの部分に関して elfdump ユーティリティーによって表示されるのと同じ情報を生成する、dump という名前のコマンドが提供されます。モジュールでは一般に、dump がデフォルトコマンドとして指定されます。
elfedit コマンドを実行するために使用される構文は、UNIX コマンド行ユーティリティーを使用しているすべてのユーザーが使いやすいように考慮されています。この構文は、空白で区切られたトークンで構成されます。最初のトークンはコマンド名です。コマンドのあとに、ハイフン (-) 文字で始まる引数である各オプションが指定されます。オプションのあとに、プレーン引数 (オペランド) が指定されます。特定のコマンドに対してオプションやオペランドを 0 個以上指定できますが、この両方が存在する場合は、常にオプションをプレーン引数の前に指定します。特殊オプション -- (2 つのハイフン) を使用して、オプションの終わりを表すことができます。このオプションが見つかると、残りの引数はすべて、- で始まっていたとしてもプレーン引数であると見なされます。
elfedit トークン内の文字の解釈は、使用されている引用の形式によって異なります。
単一引用符 (') または二重引用符 (“) の外側では、バックスラッシュ (\) がエスケープ文字として機能します。バックスラッシュ文字が見つかると、elfedit はこの文字を無視し、後続の文字を (その文字自体がバックスラッシュであっても) 文字どおりに処理します。この機能を使用すると、文字列を 2 つの個別のトークンに分割しなくても、コマンドの文字列引数に空白文字を挿入できます。同様に、この機能を使用すると、引用符またはバックスラッシュをリテラル文字として挿入できます。
単一引用符 (') 内では、空白文字によってトークンは区切られず、空白文字はトークン内のリテラル文字として解釈されます。二重引用符 (“) およびバックスラッシュ (\) 文字はリテラル文字として解釈され、特別な意味を持ちません。
二重引用符 (“) 内では、空白文字によってトークンは区切られません。単一引用符文字は文字どおり解釈され、引用機能を持ちません。バックスラッシュ (\) は、文字列リテラル内の C プログラミング言語で使用される場合と同様に動作するエスケープ文字です。
警告 (ベル)
バックスペース
フォームフィード
改行
復帰
水平タブ
垂直タブ
バックスラッシュ
単一引用符
二重引用符
8 進数の定数で、ooo は 1 つから 3 つまでの 8 進数 (0...7) です
バックスラッシュのあとのその他の文字はすべてエラーです。
コアのコマンドは、sys という名前の内部モジュールに属しています。その他のモジュールはすべて、動的にロード可能な共有可能オブジェクトとしてパッケージ化されます。elfedit は、特定のモジュールを必要とするコマンドが実行された場合、または sys:load コマンドの実行の結果として、必要に応じてモジュールをロードします。その特殊な組み込みステータスのため、さらにはそのコマンドが頻繁に使用されるため、elfedit では、sys: 接頭辞を含めなくても sys モジュールのコマンドを指定できます (たとえば、sys:load ではなく load)。その他のすべてのモジュールのコマンドにアクセスするには、完全な module:cmd 形式を指定する必要があります。
elfedit は、次の標準モジュールとともに提供されます。
機能セクション
動的セクション
ELF ヘッダー
プログラムヘッダー配列
再配置セクション
セクションヘッダー配列
文字列テーブルセクション
シンボルテーブルセクション
シンボル情報セクション
コアに組み込まれた elfedit コマンド
ステータスおよびコマンドドキュメント
status (sys:status) コマンドは、現在の elfedit セッションに関する情報を表示します。
入力および出力ファイル
オプション設定
モジュール検索パス
ロードされたモジュール
どの elfedit モジュールにも、コマンドごとの広範囲なオンラインドキュメントが、UNIX のマニュアルページと同様の形式で含まれています。help (sys:help) コマンドは、この情報を表示するために使用されます。elfedit についての詳細を表示するには、elfedit を起動し、ヘルプコマンドを引数なしで使用します。
% elfedit > help
elfedit はウェルカムメッセージと、elfedit およびヘルプシステムの使用方法に関する詳細情報を表示します。
モジュールのサマリー情報を取得するには:
> help module
モジュールが提供する特定のコマンドの詳細なドキュメントを取得するには、次のようにします。
> help module:command
例としての dyn モジュールおよび dyn:runpath コマンドの使用:
> help dyn > help dyn:runpath
help (sys:help) を使用すると、それ自体に関するヘルプを取得できます。
> help help
elfedit モジュールは、必要に応じてロードされる共有可能オブジェクトとして実装されます。あるモジュールが必要になると、elfedit は、そのモジュールを実装している共有可能オブジェクトを見つけるためにモジュールパスを検索します。このときのパスは、一連のディレクトリ名をコロン (:) 文字で区切ったものです。そのパスには、通常の文字に加えて、次のいずれかのトークンも含めることができます。
elfedit コマンドの ELFCLASS (32、64) に展開されます。
64 ビット ELFCLASS に展開されます。これは、64 ビットバージョンの elfedit では %e と同等ですが、32 ビットバージョンでは空の文字列に展開されます。
elfedit コマンドの現在の命令セットアーキテクチャー (ISA) の名前 (sparc、sparcv9、i386、amd64) に展開されます。
64 ビット ISA に展開されます。これは、64 ビットバージョンの elfedit では %i と同等ですが、32 ビットバージョンでは空の文字列に展開されます。
ビルトインのデフォルトモジュールパスの値に展開されます。これは、デフォルトのパスの前またはあとにディレクトリを追加する場合に役立ちます。
elfedit プログラムが格納されているファイルシステムツリーのルート。標準のシステムでは、これは単純に標準のシステムのルートディレクトリ (/) です。elfedit のコピーをほかの場所にインストールできる開発システムでは、%r を使用することにより、一致した一連のモジュールが使用されることを保証できます。
1 つの % 文字に展開されます。
これらのトークンを使用する、elfedit のデフォルトモジュール検索パスを表示できます。
% elfedit -e status
デフォルト検索パスは、ELFEDIT_PATH 環境変数を設定するか、または –L コマンド行オプションを使用することによって変更できます。両方を指定した場合、環境変数が –L オプションより優先されます。
サポートしているオプションは、次のとおりです。
autoprint モードを有効にします。autoprint が有効になっている場合、elfedit は、ELF ファイルが変更されたときに生成される変更された値を出力します。この出力は、–o オプションを使用して変更できる現在の出力形式で示されます。デフォルトの出力形式は、elfdump(1) ユーティリティーによって使用される形式です。autoprint モードは、elfedit が対話的に使用されている場合 (stdin と stdout が端末である場合) にデフォルトになります。そのため、–a オプションは、elfedit が非対話型コンテキストで使用されている場合にのみ意味を持ちます。対話型セッションで autoprint を無効にするには、elfedit コマンドを使用します。
> set a off
このオプションが設定されていると、elfedit は、処理されている ELF オブジェクトの内部の動作や詳細が記述された情報メッセージを発行します。これは、内部で実行されている動作を深く理解したい場合に役立ちます。
編集コマンドを指定します。複数の –e オプションを指定できます。0コマンド行に編集コマンドが存在する場合、elfedit はバッチモードで動作します。ファイルを開いたあと、elfedit は各コマンドを指定された順序で実行します。そのあと、変更されたファイルが保存され、elfedit が終了します。バッチモードは、シェルスクリプトやメイクファイルから単純な操作を実行する場合に役立ちます。
elfedit モジュールを検索するためのデフォルトのパスを設定します。モジュールは、このマニュアルページの「モジュール検索パス」セクションで説明されています。
ELF データを表示するために使用される形式。このオプションによって、セッションの現在の形式が確立されます。この形式は、elfedit セッション内から set (sys:set) コマンドを使用するか、またはセッション内で実行される個々のコマンドに –o オプションを指定することによって変更できます。
デフォルトの形式では、人間が見ることを目的にした形式で出力を表示します。この形式は、elfdump ユーティリティーによって使用される形式と同じです。
整数値は常に、整数の形式で表示されます。文字列は、包含する文字列テーブルへの整数オフセットとして表示されます。
ELF ファイル内から文字列を表示する場合は、文字列のみが表示されます。整数値は、可能な場合は記号定数として表示され、それ以外の場合は整数の形式で表示されます。タイトルやヘッダーなどの補足的な出力は表示されません。
simple と canon の各スタイルは、記号定数の表示方法で異なります。simple が指定されている場合、記号定数はもっとも一般的に使用される形式で表示されます。canon が指定されている場合、記号定数は、/usr/include/sys/elf.h や /usr/include/sys/link.h にある完全に標準的な形式で表示されます。報告される出力の安定性が必要なシェルスクリプトやその他のコンテキストでは、標準的な形式を使用することをお勧めします。
読み取り専用モード。入力ファイルは読み取り専用アクセス用に開かれ、編集セッションの結果は保存されません。elfedit では、–r が指定された場合、outfile 引数は許可されません。ファイルを変更する意図がない場合は、読み取り専用モードを強くお勧めします。誤った変更に対する追加の保護を提供することに加えて、ユーザーが書き込み権を持っていないファイルの検査も可能になります。
バージョン情報を出力してすぐに終了します。
使用法に関するメッセージを出力したあと、すぐに終了します。
次のオペランドがサポートされています。
処理する ELF オブジェクトを含む入力ファイル。
実行可能ファイル (ET_EXEC)、共有オブジェクト (ET_DYN)、または再配置可能オブジェクトファイル、(ET_REL) を指定できます。アーカイブは、直接にはサポートされていません。アーカイブ内のオブジェクトを編集するには、オブジェクトを抽出し、そのコピーを編集してから、それをアーカイブ内に戻す必要があります。
infile が存在しない場合、elfedit は、sys: モジュールからのコマンドの実行のみが許可される制限されたモードで実行されます。このモードは主に、help (sys:help) コマンドから使用可能なコマンドドキュメントへのアクセスを許可するためのものです。
infile が存在し、outfile が指定されていない場合、elfedit は所定のファイルを編集し、その結果を同じファイルに書き込むため、元のファイルの内容が上書きされます。通常、elfedit をこのモードで使用することはやめ、出力ファイルを指定することをお勧めします。結果として得られるファイルがテストされ、検証されたあと、そのファイルを元のファイルの場所に移動できます。
–r オプションを使用すると、infile を読み取り専用アクセス用に開くことができます。これは、変更したくない既存のファイルを検査する場合に役立ちます。
出力ファイル。infile と outfile の両方が存在する場合は、infile が読み取り専用アクセス用に開かれ、変更されたオブジェクト内容が outfile に書き込まれます。
システムでサポートされている場合、elfedit は 64 ビットアプリケーションとして実行されるため、2G バイト (2^31 バイト) 以上のファイルを処理できます。
起動時に、elfedit は libelf を使用して入力ファイルを開き、その内容のコピーを編集のためにメモリー内にキャッシュします。そのあと、1 つ以上のコマンドを実行できます。変更されたオブジェクトを必要に応じて出力ファイルに書き込むことによってセッションが完了し、次に終了します。
infile が存在しない場合、elfedit は、sys モジュールからのコマンドの実行のみが許可される制限されたモードで実行されます。このモードは主に、help (sys:help) コマンドから使用可能なコマンドドキュメントへのアクセスを許可するためのものです。
1 つ以上の –e オプションが指定されている場合は、そこで指定されているコマンドが指定された順序で実行されます。elfedit は、指定されたコマンドの直後に書き込み (sys:write) および終了 (sys:quit) のための暗黙の呼び出しを追加して、出力ファイルが書き込まれ、elfedit プロセスが終了するようにします。シェルスクリプトやメイクファイルでは、この形式の使用が便利です。
–e オプションが指定されていない場合、elfedit は stdin からコマンドを読み取り、それらのコマンドを指定された順序で実行します。呼び出し側は、このモードで実行中に作業を保存して終了するには write (sys:write) コマンドと quit (sys:quit) コマンドを明示的に発行する必要があります。
次の終了ステータスが返されます。
正常終了。
致命的なエラーが発生しました。
無効なコマンド行オプションが指定された。
次の例では、シェルプロンプト (%) と elfedit プロンプト (>) での elfedit の対話型使用が示されています。ユーザーは、これらのいずれの文字も入力しないでください。
使用例 1 実行可能ファイルの実行パスの変更次の例では、共有可能オブジェクト用の lib ディレクトリに隣接する bin ディレクトリ内に、prog という名前の実行可能ファイルがインストールされていることを前提にしています。次のコマンドは、その実行可能ファイルの runpath を lib ディレクトリに設定します。
% elfedit -e 'dyn:runpath $ORIGIN/../lib'
–e オプションの引数での単一引用符の使用は、シェルがこのコマンド全体を elfedit に確実に 1 つの引数として渡すようにするために必要です。
あるいは、elfedit を非バッチモードで使用することによって、同じ操作を実行できます。
% elfedit prog > dyn:runpath $ORIGIN/../lib index tag value [30] RUNPATH 0x3e6 $ORIGIN/../lib > write > quit
runpath などの要素や、必要なエントリの追加または変更は、オブジェクト内にパディングが存在する場合にのみ実現できる可能性があります。「注意事項」を参照してください。
使用例 2 ハードウェア機能ビットの削除実行のためにオプションハードウェアのサポートを必要とするオブジェクトは、必要な機能を指定したビットのマスクを含む機能セクションを使用して構築されます。実行時リンカー (ld.so.1) は、このマスクを実行中のシステムの属性に対してチェックして、現在のシステムが特定のオブジェクトを実行できるかどうかを判定します。そのシステム上で使用できない機能を必要とするプログラムは、実行を妨げられます。
このチェックによって、必要なハードウェアサポートを明示的にチェックしない不備なプログラムが紛らわしい方法でクラッシュすることが防止されます。ただし、記述されるプログラムが、実行時にシステムの機能を明示的にチェックすることは不便な場合があります。このようなプログラムは、ハードウェアでサポートされている場合に使用する最適化されたコードを備える一方、それ以外の場合は、より低速ではあっても実行可能な汎用のフォールバックバージョンを提供していることがあります。この場合は、ハードウェア互換性マスクによって、このようなプログラムの古いハードウェア上での実行が妨げられます。このような場合は、関連するビットをマスクから削除すると、そのプログラムを実行できます。
次の例では、SSE3 CPU 拡張機能を使用する x86 バイナリから AV_386_SSE3 ハードウェア機能を削除します。これにより、SSE3 を使用するための機能を検証する責任が、実行時リンカーからプログラム自体に移転されます。
% elfedit -e 'cap:hw1 -and -cmp sse3' prog使用例 3 オブジェクトからの情報の読み取り
elfedit を使用すると、対象を絞った特定の情報をオブジェクトから抽出できます。次のシェルコマンドは、ファイル /usr/bin/ls に含まれているセクションヘッダーの数を読み取ります。
% SHNUM=`elfedit -r -onum -e 'ehdr:e_shnum' /usr/bin/ls` % echo $SHNUM 29
Oracle Solaris のバージョンや、使用しているマシンの種類によっては、異なる値が取得されることがあります。–r オプションを指定すると、ファイルが読み取り専用で開かれるため、通常のアクセス権を持つユーザーはファイルを開くことができ、また重要なシステム実行可能ファイルが誤って破損されることが防止されます。num 出力形式は、無関係なテキストを含まない、目的の値のみを取得するために使用されます。
同様に、次のコマンドは、シンボル unlink のシンボルの型を C 実行時ライブラリから抽出します。
% TYPE=`elfedit -r -osimple -e 'sym:st_type unlink' \ /lib/libc.so` % echo $TYPE STT_FUNC使用例 4 実行可能ファイルの ASLR 設定の指定
実行可能ファイルのデフォルトのアドレス空間配置のランダム化 (ASLR) 動作は、DT_SUNW_SX_ASLR 動的セクションエントリを使って指定します。次に、指定されたプログラムの ASLR を有効または無効にする方法を示します。
% elfedit prog > dyn:sunw_sx aslr enable index tag value [40] SUNW_SX_ASLR 0x2 ENABLE > dyn:sunw_sx aslr disable index tag value [40] SUNW_SX_ASLR 0x1 DISABLE
デフォルトのモジュール検索パスを変更します。モジュール検索パスは、このマニュアルページの「モジュール検索パス」セクションで説明されています。
64 ビットの elfedit の自動実行を抑止します。デフォルトでは、64 ビットバージョンの elfedit は、システムが 64 ビットに対応している場合に実行されます。
elfedit から画面への出力を対話的に提供します。設定されていない場合は、more が使用されます。more(1) を参照してください。
編集コマンドを提供するために必要に応じてロードされる elfedit モジュールのデフォルトディレクトリ。
コマンド行編集のための個人用 tecla カスタマイズファイル。tecla(7) を参照してください。
属性についての詳細は、マニュアルページの attributes(7) を参照してください。
|
dump(1), elfcompress(1), elfdump(1), ld.so.1(1), more(1), nm(1), pvs(1), elf(3ELF), libelf(3LIB), attributes(7), tecla(7), sxadm(8)
OracleSolaris 11.4 リンカーとライブラリガイド
elfedit は、ELF システムのテストおよび開発のためのツールとして設計されています。このツールでは、オブジェクト内のほぼすべての ELF メタデータの検査および変更のための機能が提供されます。無効な、または使用できない ELF ファイルを生成する可能性のある編集でも、何も出力せずに許可されます。ユーザーは、ELF の形式と、それを制御している規則や規約に関する知識を持っているものと想定されています。elfedit を使用する場合は、Oracle Solaris 11.4 Linkers and Libraries Guideが役立ちます。
elfedit を使用すると、ユーザーはオブジェクト内の ELF メタデータを変更できますが、実際のプログラムのコードを理解したり、変更したりすることはできません。そのため、タイプ、サイズ、配置などの ELF 属性を、そのファイルの実際の内容に一致しない方法で設定すると、壊れていて、使用できない出力オブジェクトが生成される可能性があります。このような変更はリンカーコンポーネントのテストに役立つ場合がありますが、それ以外の場合は避けるようにしてください。
dyn:runpath コマンドを使用してオブジェクトの runpath を変更するなどの、より高いレベルの操作は安全であり、このセクションで詳細に説明している種類のリスクを冒すことなく実行できます。
elfedit でサポートされているすべての ELF 操作を、すべての ELF オブジェクトに対して正常に実行できるわけではありません。elfedit は、ファイル内にある既存のセクションによって制約されます。
特に注意する点の 1 つは、elfedit が特定のオブジェクトの runpath を変更できない可能性があることです。runpath を変更するには、次の条件を満たしている必要があります。
目的の文字列が動的な文字列テーブル内にすでに存在するか、またはこのセクション内に新しい文字列を追加するための予約された十分な領域が存在する必要があります。オブジェクトに文字列テーブルの予約領域が存在する場合は、.dynamic DT_SUNW_STRPAD 要素の値がその領域のサイズを示します。これをチェックするには、次の elfedit コマンドを使用できます。
% elfedit -r -e 'dyn:tag DT_SUNW_STRPAD' file
動的セクションにすでに runpath 要素が存在するか、またはこの要素を入力できる使用可能な未使用の動的スロットが存在する必要があります。既存の runpath の存在をテストするには、次のようにします。
% elfedit -r -e 'dyn:runpath' file
動的セクションは、タイプ DT_NULL の要素を使用して、そのセクション内にある配列を終了します。最後の DT_NULL は変更できませんが、この要素が複数存在する場合、elfedit はそのいずれかを runpath 要素に変換できます。追加の動的スロットをテストするには、次のようにします。
% elfedit -r -e 'dyn:tag DT_NULL' file
古いオブジェクトには、このような操作を完了するために必要な追加の領域が存在しません。それを行うために必要な領域は、Oracle Solaris Express Community Edition リリースで導入されました。
ある操作が失敗した場合は、–d (debug) オプションを使用して出力された詳細情報が、その原因を見つけるために非常に役立ちます。
elfedit モジュールは、ELF 構造内のフィールドを直接操作するコマンドはそのフィールドと同じ名前を持つが、より高いレベルの概念を実装するコマンドはそれに当てはまらないという規約に従っています。たとえば、ELF ヘッダー内の e_flags フィールドを操作するためのコマンドには ehdr:e_flags という名前が付けられています。そのため一般には、モジュールを識別し、ELF フィールドの名前を持つコマンドを探すことによって、そのフィールドを変更するためのコマンドが見つかります。
elfedit は、圧縮されたセクションの読み取り専用のサポートを提供します。圧縮されたセクションは SHF_COMPRESSED セクションヘッダーフラグによって識別されます。そのようなセクションを elfedit で変更するには、まず elfcompress(1) などの外部ユーティリティーを使用してセクションを圧縮解除する必要があります。
elfedit コマンドはコアファイルを変更できません。–r オプションは readonl モードでコアファイルを操作するように指定できます。