3 ポイント 投稿者 GN⁺ 2024-06-10 | 2件のコメント | WhatsAppで共有
  • libtree は、ldd の出力をツリーに変換し、共有ライブラリがどのように発見されたのか、またはなぜ見つからないのかを説明するツール
  • デフォルトの出力では一部の 標準依存関係 を隠し、-v-vv-vvv で隠されたライブラリや既に出会ったライブラリの依存関係まで段階的に確認できる
  • --path または -p は soname の代わりに パス を表示し、--max-depth で再帰探索の深さを制限できる
  • インストールは v3.1.1 の事前ビルド済みバイナリ、Fedora/RHEL/CentOS、Ubuntu 22.04+、GNU Guix から可能
  • ソースからのビルドには C99 を理解する C コンパイラが必要で、make 使用時は LDFLAGS=-static が推奨される

libtree がすること

  • libtreeldd をツリー形式に変換するツール
  • 共有ライブラリが どのように発見されるか、またはなぜ場所を見つけられないのかを説明する
  • README には doc/screenshot.png のスクリーンショットが含まれている

出力オプション

  • デフォルトの出力では一部の 標準依存関係 は表示されない
  • より詳細な出力は verbosity オプションで制御する
    • libtree -v: デフォルトでスキップされるライブラリを表示する
    • libtree -vv: デフォルトでスキップされるライブラリの依存関係も表示する
    • libtree -vvv: 既に出会ったライブラリの依存関係も表示する
  • --path または -p フラグは soname の代わりに パス を表示する
    • 例: libtree -p $(which tar)
  • --max-depth は再帰の深さを制限する

インストール方法

ソースからビルド

  • libtree には C99 を理解する C コンパイラが必要
  • 基本的なビルド手順は、リポジトリをクローンしてから make を実行する方法
  • make 使用時は LDFLAGS=-static が推奨される
  • README には、curllibtree.c を取得してコンパイルする unsafe quick install コマンドも別の折りたたみセクションとして用意されている

2件のコメント

 
GN⁺ 2024-06-10
Hacker News の意見
  • このツールも、ldd が検査対象ライブラリの一部を実際に実行してしまうという予想外の動作をそのまま踏襲しているのだろうか?
    https://catonmat.net/ldd-arbitrary-code-execution

    • 最近の、だいたい5年以上前からのバージョンの ldd は対象バイナリを実行しない
      参考: https://manpages.debian.org/unstable/manpages/ldd.1.en.html#...
    • モバイルでコードをざっと見た限り、そうはしていないように見える
      実際には ELF ファイルを直接パースし、依存関係も再帰的にパースしているようで、なかなか良い
    • Python 向けにぼんやり似たようなものを作ったことがあるが、この問題を最後まで回避できなかった https://github.com/google/importlab/issues/69
    • objdump を使うと、ELF ファイルにエンコードされているそのままのデータを出力してくれる
      vdso が検索するライブラリ一覧まで含まれる
  • 似たツールとして lddtree がある
    https://github.com/gentoo/pax-utils/tree/master

  • ldd で欠けている依存関係を再帰的に追い続けるのはかなり退屈
    なのでこれは良い改善に見えるし、次に曖昧な not found に出会ったら使ってみるつもり

  • 基本的には Linux CLI 版の depends.exe みたいなもの

    • その特定のツールは、最近の Windows バージョンではもううまく動かない
      代わりに https://github.com/lucasg/Dependencies を使うほうがよい。これも完全に最新というわけではないが……
      Visual Studio をインストールしていて、インストーラーで x64/x86 build tools (latest) を選んでいるなら、VS Developer Command Prompt で dumpbin /dependents を実行するのが今でも最も信頼できる選択肢
    • そう、自分もまさにそう思った
      [1] https://www.dependencywalker.com/
  • 色が何を意味するのか気になる人のために書いておくと、manpage/README では見つけられなかった
    マゼンタ: 除外リストに入っており、-v[v[v]] の場合だけ表示される
    : 以前に見た項目なので、複数回出てくる依存関係を見つけられる

  • 「ライブラリが見つかる、または見つからない理由」とはどういう意味? LD_LIBRARY_PATH にあるかないかのどちらかでは?
    スクリーンショットだけでは、これが何を指しているのかよく分からない

    • このツールの文脈では正確には分からないが、ライブラリ検索は単一の環境変数よりずっと複雑
      システムの検索パス、runpath、rpath、LD_LIBRARY_PATH など、異なるディレクトリ検索方法がいくつもある
      ライブラリは普通 foo.so のような短い名前でリンクされるが、ライブラリのフルパスで動的リンクされることもある
      付け加えると、一般に LD_LIBRARY_PATH の設定は避けられるなら避けたほうがずっとよい。常に可能とは限らないが、設定するとすべての実行で検索優先順位の最上位に来る。何かがライブラリのフルパスで動的リンクされていても LD_LIBRARY_PATH が優先され、検索方法を完全に平坦化してしまう
    • ライブラリが見つかるために、必ずしも LD_LIBRARY_PATH 内にある必要はない
      タイトルの要点は、libtree が実行ファイルからすべての直接・間接依存関係へ続くパスを簡単に見つけられるようにする、ということ。その用途の一つが、欠けている依存関係の問題を把握する助けになること
      実際にパッケージシステムを使っているなら依存関係が欠けることはあまりないはずなので、libtree は別の理由で使う可能性が高い
    • LD_LIBRARY_PATH にあるかないかだけではなく、各ライブラリごとにロード時に評価される RPATH もある
      より大きなポイントは、依存関係がグラフを成し、それを木のように表示できるということ。どのライブラリを必要としたライブラリのせいで特定のライブラリが見つからなかったのかを知るのは有用
    • LD_LIBRARY_PATH だけでライブラリを探すわけではない。ローダーはライブラリを見つけるために、ほかにも複数の情報源を考慮する
      通常の設定なら、ロードされる各バイナリの一般的な ELF フィールドと、ローダーが知っている他のパスの組み合わせになる
      同じライブラリの複数バージョンや同名の複数ライブラリがあるシステムで LD_LIBRARY_PATH に依存するのは、かなり近視眼的になりうる。ローダーは各バイナリについて LD_LIBRARY_PATH のパスを順番に検索し、最初に一致したライブラリを選ぶ。別の方法でより高い優先順位のパスを設定していなければ、そのライブラリが実際に望んでいるものではない可能性があり、実行時に予期しないエラーにつながりうる
      より良い方法は、そのバイナリが必要とするライブラリの場所を指すように RPATH を設定すること
      環境と RPATH 設定が一貫していないと、同じライブラリの複数バージョンを同時にロードすることもある。このツールは問題があるか、そしてなぜそうなのかを把握する助けになる
    • 少なくとも RPATHRUNPATHLD_LIBRARY_PATH がある
      このツールは ldd ベースなので、おそらく DYLD_LIBRARY_PATHDYLD_FALLBACK_FRAMEWORK_PATHDYLD_FALLBACK_LIBRARY_PATH@executable_path@loader_path@rpath も解釈するはず
  • 本当に便利。普段は実際の要件が何なのかを把握しようとして、readelfセクションを読んでいる

  • LD_DEBUG=libs では足りない?

    • それはライブラリ依存関係の静的評価ではなくローダーのデバッグフラグなので、まったく同じではない
  • バグかどうかは分からないが、vim の例では ldd と libtree が互いに異なるライブラリを示している
    たとえば linux-vdso.so.1ldd ではリストの一番上に出てくるが、libtree にはまったく出てこない

    • linux-vdso.so.1 はファイルシステムのどこかで見つけられる実体のあるライブラリではなく、ELF ファイル内でも参照されていないため、libtree には分からない
      代わりに、新しく開始したプロセスのアドレス空間へカーネルが自動的にマッピングする。gettimeofday のような関数でシステムコールのオーバーヘッドを避けるための最適化機能。参考: https://man7.org/linux/man-pages/man7/vdso.7.html
  • NixOS でクローズドソースのバイナリを実行するために何を含めるべきか調べようとして、ldd を再帰的に回す雑な小さなスクリプトを作ったことがある
    またそういうことをすることになったら、このツールを試してみるつもり

 
kayws426 2024-06-11

良さそうですね!!