web-dev-qa-db-ja.com

共有ライブラリに依存するプログラムをビルドした後、共有ライブラリのファイル名を変更するにはどうすればよいですか?

ディレクトリ構造の奥深くにあると予想される共有ライブラリに依存するプログラムがあります。その共有ライブラリを移動して、より良い場所に移動したいと思います。 OS Xでは、これはinstall_name_toolを使用して実行できます。 Linuxに相当するものが見つかりません。

参考のため、 readelf -d myprogram次の言い換えられた出力を吐き出します。

Dynamic section at offset 0x1e9ed4 contains 30 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [this/is/terrible/library.so]
 0x00000001 (NEEDED)                     Shared library: [libGL.so.1]
 0x00000001 (NEEDED)                     Shared library: [libGLU.so.1]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
(continues in an uninteresting fashion)

(そしてリクエストにより、ldd myprogram :)

    linux-gate.so.1 =>  (0x0056a000)
    this/is/terrible/library.so => not found
    libGL.so.1 => /usr/lib/mesa/libGL.so.1 (0x0017d000)
    libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00a9c000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00710000)
   (etc, etc)

「this/is/terrible /library.so」を「shared/library.so」に正誤表にします。プログラムが、相対パスthis/is/terrible/library.soが実際に存在する「ビルド済み」の場所に残されている場合、lddは予想どおりにそれを見つけることができることに注意してください。

私はRPATHについて知っていますが、それは私が探しているものではありません。検索パスをグローバルに変更する必要はありません。

21
ZorbaTHut

[〜#〜] ht [〜#〜] -これは役立つかもしれません。

HTは、実行可能ファイル用のファイルエディター/ビューアー/アナライザーです。目標は、デバッガーの低レベルの機能とIDEの使いやすさを組み合わせることです。すべての(16進)編集機能と最も重要なファイル形式のサポートを実装する予定です。

ZorbaTHutのソリューションと大きく異なるものは見つかりませんでしたが、長さの異なる名前を付けても、バイナリを有効に保つことは可能かもしれません。

gelf -これも便利かもしれません。

GElfは、ELFオブジェクトファイルを操作するための汎用のELFクラスに依存しないAPIです。 GElfは、32ビットおよび64ビットのELF形式のオブジェクトファイルを処理するための単一の共通インターフェイスを提供します。

5
Dmitry Yudakov

patchelf を使用できます:

patchelf --replace-needed liboriginal.so.1 libreplacement.so.1 my-program

依存関係を削除することもできます。

patchelf --remove-needed libfoo.so.1 my-program

依存関係を追加します。

patchelf --add-needed libfoo.so.1 my-program

または、ライブラリを検索するパスを変更します( rpath ):

patchelf --set-rpath /path/to/lib:/other/path my-program
16
Bernardo Ramos

暫定的で恐ろしい、ハッキーな解決策を投稿する。

ライブラリの依存関係は、.dependsブロックと呼ばれるELFブロックに保存されます。そのブロックの形式は、識別子と文字列ポインタのペアの大きな配列であり、文字列ポインタは、バイナリのどこかにある標準のCヌル終了文字列を指しています。

これがどこに向かっているのか分かりますよね?

はい、必要な新しいパスが古いパスよりも大きくない限り、バイナリに直接アクセスして、単純な文字列置換を行うことができます。バイトを追加または削除しないように注意してください。そうしないと、バイナリ全体が壊れてしまいます。より安全にしたい場合は、実際にELF構造をトラバースして、正しい場所にあることを確認できます。現在、ソース文字列が1回だけ表示されることを確認しています。

ELFにはチェックサムが含まれていますが、実際にチェックサムを検証するローダーがないようです。そのため、面倒ではありますが、無視しても「安全」です。

「実際の解決策」は、ELF構造の低レベルの一般化された操作を可能にするユーティリティです。私が知る限り、そのようなユーティリティは存在しません。いくつかの特殊なケース(RPATHがほとんどです)を除いて、そのようなユーティリティを書くのがどれほど難しいかを知っているふりをしません。

私はこれに対するより良い解決策を絶対に望んでいますが、これまでのところ、これはうまくいくようです。

8
ZorbaTHut