Linux 実行ファイルの共有ライブラリリンク

Linux 実行ファイルが依存している共有リンクライブラリの一覧は https://minosys.com/wp/2024/07/12/326/
で表示できることを書きましたが、elf.h を使っても探ることができます。

ELF header の構造

ELF ファイルは Ehdr, Phdr, Shdr から構成されていて、ファイル先頭は必ず Ehdr となります。Ehdr は固定長で、sizeof(Elf64_Ehdr) でヘッダサイズを指定することができます。

Phdr, Shdr は可変長で、Ehdr の中に開始オフセット(eh_poffset, eh_soffset)、エントリサイズ(eh_pentsize, eh_sentsize)、ヘッダ数(eh_pnum, eh_snum) が格納されています。sh[i] を「セクション」と呼びます。セクション文字列情報も可変長ですが、sh[Elf64_Ehdr.eh_strndx].sh_offset (このアドレスを仮に shtab とします)から sh[Elf64_Ehdr.eh_strndx].sh_size 長分定義されています。各文字列はゼロ終端です。

共有ライブラリ情報を取り出す際に必要なのは Shdr です。Shdr には様々な情報が定義されていますが、

  • 名称が .interp のセクション
  • 名称が .dynstr のセクション
  • sh[i].sh_type が SHT_DYNAMIC のセクション

が重要です。

.interp セクション

プログラム実行前に必ず呼び出されるライブラリを記述します。複数記述されている場合、その順序に実行します。

.dynstr セクション

ライブラリ名などの文字列を格納するセクションです。以前に記述したセクション文字列領域とは異なります。このセクションの開始アドレスを dynstr とします。

sh[i].sh_type が SHT_DYNAMIC のセクション

このセクションが共有ライブラリ情報を含むセクションになります。

Elf64_Dyn [] を記述するセクションです。開始オフセットは sh[i].sh_offset, サイズは sh[i].sh_size となります。

dyn = (Elf64_Dyn *)sh[i].sh_offset とすると、dyn は sh[i].sh_size / sizeof(Elf64_Dyn) の大きさの配列ですが、最後は必ず dyn[j].d_tag == DT_NULL となります。共有ライブラリ情報は dyn[j].d_tag == DT_NEEDED の要素に定義されています。

ライブラリ名は dynstr + dyn[j].d_un.d_val にゼロ終端されて格納されています。

ldconfig が実際にどのライブラリをリンクしているかは ldconfig -p などで調べる必要があります。

詳しくは、https://github.com/minosys-jp/linux_watcher/blob/master/graph.cc を参照してください。

投稿者について
みのしす

小さいときは科学者になろうとしたのに、その時にたまたま身に着けたプログラミングで未だに飯を食っているしがないおじさんです。(年齢的にはもうすぐおじいさん)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です