インストール - GLIBC
概要
GNU Cライブラリは、GNUシステムとGNU/Linuxシステム、そしてLinuxをカーネルとして使うシステムのためのコアライブラリである。
これらのライブラリは、ISO C11、POSIX.1-2008、BSD、OS固有のAPIなどを含む重要なAPIを提供しており、
APIには、open、read、write、malloc、printf、getaddrinfo、dlopen、pthread_create、crypt、login、exit等の基本的な機能が含まれている。
GNU Cライブラリは、下位互換性や移植性があり、高性能なISO Cライブラリになるように設計されている。
ISO C11、POSIX.1-2008、IEEE 754-2008を含むすべての関連規格に従うことを目指している。
依存関係のライブラリのインストール
Coreutilsのインストール (不要)
Coreutilsのビルドに必要なライブラリをインストールする。
sudo zypper install make gcc libcap-devel libattr-devel libacl-devel
Coreutilsの公式Webサイトにアクセスして、最新のCoreutilsをダウンロードする。
wget https://ftp.gnu.org/gnu/coreutils/coreutils-<バージョン>.tar.xz
ダウンロードしたCoreutilsを解凍して、Coreutilsディレクトリに移動する。
tar xf coreutils-<バージョン>.tar.xz cd coreutils-<バージョン>
ビルドディレクトリを作成する。
mkdir build && cd build
Coreutilsをビルドおよびインストールする。
../configure --prefix=<Coreutilsのインストールディレクトリ> make -j $(nproc) make install # または ../configure --prefix=<Coreutilsのインストールディレクトリ> \ CC="/<GCCのインストールディレクトリ>/bin/gcc-<バージョン名> -arch i386 -arch x86_64" \ CXX="/<GCCのインストールディレクトリ>/bin/g++-<バージョン名> -arch i386 -arch x86_64" \ CPP="/<GCCのインストールディレクトリ>/bin/gcc-<バージョン名> -E" CXXCPP="/<GCCのインストールディレクトリ>/bin/g++-<バージョン名> -E" make -j $(nproc) make install
Binutilsのインストール
Binutilsのビルドに必要な依存関係のライブラリをインストールする。
# RHEL sudo dnf install gmp-devel mpfr-devel libmpc-devel isl-devel # SUSE sudo zypper install patterns-base-basesystem patterns-devel-base-devel_basis patterns-devel-C-C++-devel_C_C++ \ gcc gcc-c++ gawk ncurses-devel make tar pkg-config m4 gperf bison flex expect expect-devel \ gmp-devel mpfr-devel mpc-devel isl-devel
Binutilsの公式Webサイトにアクセスして、最新のBinutilsをダウンロードする。
ダウンロードしたBinutilsを解凍して、Binutilsディレクトリに移動する。
tar xf Binutils-<バージョン>.tar.xz mkdir build && cd build
Binutilsをビルドおよびインストールする。
../configure --prefix=<Binutilsのインストールディレクトリ> make -j $(nproc) make install # または ../configure --prefix=<Binutilsのインストールディレクトリ> \ CC="/<GCCのインストールディレクトリ>/bin/gcc-<バージョン名> -arch i386 -arch x86_64" \ CXX="/<GCCのインストールディレクトリ>/bin/g++-<バージョン名> -arch i386 -arch x86_64" \ CPP="/<GCCのインストールディレクトリ>/bin/gcc-<バージョン名> -E" CXXCPP="/<GCCのインストールディレクトリ>/bin/g++-<バージョン名> -E" make -j $(nproc) make install
GLIBC(GNU C Library)のインストール
GLIBCのビルドに必要な依存関係のライブラリをインストールする。
# SUSE sudo zypper install patterns-base-basesystem patterns-devel-base-devel_basis patterns-devel-C-C++-devel_C_C++ \ gcc gcc-c++ gawk bison make m4 gperf bison flex \ ncurses-devel ncurses5-devel expect expect-devel \ gdbm-devel libbz2-devel zlib-devel libdb-4_8-devel \ libopenssl-devel libopenssl-1_1-devel # OpenSSL 1を使用する場合 libopenssl-3-devel # OpenSSL 3を使用する場合
現在使用しているGLIBCのバージョンを確認する。
ls -l /lib/libc-* # 出力例 -rwxr-xr-x 1 root root 2205616 9月 13 00:35 /lib/libc-2.31.so*
まず、GLIBCのインストールディレクトリおよびビルドディレクトリを作成する。
mkdir -p ~/InstallSoftware/GLIBC/build cd ~/InstallSoftware/GLIBC
GLIBCの公式Webサイトにアクセスして、GLIBCをダウンロードして解凍する。
または、wget
コマンドやgit clone
コマンドを実行してダウンロードする。
wget http://ftp.gnu.org/gnu/glibc/glibc-x.xx.tar.xz tar xf glibc-x.xx.tar.gz または git clone git://sourceware.org/git/glibc.git
次に、ビルドに関連する環境変数PATH
、LD_LIBRARY_PATH
、PKG_CONFIG_PATH
等を初期状態にする。
export PATH="/usr/local/bin:/usr/bin:/bin"; \ export LD_LIBRARY_PATH=""; \ export PKG_CONFIG_PATH="$(pkg-config --variable pc_path pkg-config)"; \ export CFLAGS=""; \ export CPPFLAGS="";
ビルドディレクトリに移動して、GLIBCをビルドおよびインストールする。
cd build ../glibc-x.xx/configure --prefix=<GLIBCのインストールディレクトリ> \ CC=/<GCCのインストールディレクトリ>/bin/gcc \ # GCCを指定する場合 CXX=/<GCCのインストールディレクトリ>/bin/g++ \ # G++を指定する場合 --host=x86_64-linux-gnu \ --enable-multi-arch \ # 32ビットを有効にする場合 --enable-stack-protector=strong \ --enable-obsolete-rpc \ --enable-obsolete-nsl \ --enable-add-ons=libidn \ --without-selinux \ # SELinuxが不要な場合 --with-binutils=<Binutilsのインストールディレクトリ> # 必要な場合 make -j $(nproc) make install # 各国語対応ファイルのインストール make localedata/install-others
configureスクリプトで使用可能なオプションを、以下に示す。
- --enable-multi-archオプション
- マルチアーキテクチャサポートを有効にする。
- 異なるCPUアーキテクチャ (例:x86_64, i386, Aarch64等) 向けのライブラリを同一システム上で共存させることができる。
- 動的リンカが実行時に最適なライブラリバージョンを選択できるようになる。
- クロスコンパイルや異なるアーキテクチャのバイナリの実行をサポートする。
- ロケールや文字セットのサポートを含む、アーキテクチャ固有の最適化を可能にする。
- --enable-stack-protector=strongオプション
- 強力なスタック保護機能を有効にする。
- バッファオーバーフロー攻撃からの保護を強化する。
- 関数の開始時にカナリア値 (ランダムな値) をスタックに配置して、関数終了時にこの値を確認する。
- カナリア値が変更されていた場合、スタックの破壊が検出され、プログラムは即座に終了する。
- strong値は、より多くの関数に対してこの保護を適用する。(サイズの小さな配列を持つ関数も含む)
- --enable-obsolete-rpcオプション
- 廃止予定のRPC(Remote Procedure Call)関連の機能を有効にする。
- 古いRPC関連の関数やライブラリ (例: rpc/rpc.hのヘッダファイル等) を含める。
- 後方互換性のために必要な場合がある。
- 新しいプログラムではこれらの機能の使用は推奨されないが、レガシーシステムとの互換性維持のために重要である。
- --enable-obsolete-nslオプション
- 廃止予定のNSL (Network Services Library) 関連の機能を有効にする。
- 古いネットワークサービスライブラリ関連の関数 (例: gethostbyname関数等) を含める。
- これらの関数は主にDNS解決に使用されていたが、現在では、getaddrinfo関数等の新しいAPIに置き換えられている。
- レガシーソフトウェアとの互換性のために必要な場合がある。
マルチアーキテクチャサポートと強力なスタック保護は、現代のシステムにおいて重要な機能である。
一方で、廃止予定のRPCとNSL機能の有効化は、主に古いソフトウェアとの互換性のために行われる。
最後に、GCCのヘルパーライブラリが必要になるので、/lib64ディレクトリからコピーする。
これにより、/home/ユーザ名/InstallSoftware/GLIBCディレクトリにおいて、システムファイルを使用する準備が整う。
# パッケージ管理システムによりインストールしたGCCを使用する場合 cp -r /lib64/libgcc* /<GLIBCのインストールディレクトリ>/lib64 # ホームディレクトリにインストールしたGCCを使用する場合 cp -r /<GCCのインストールディレクトリ>/lib64/libgcc* /<GLIBCのインストールディレクトリ>/lib64
Linux x86やUbuntuの場合、lib64ディレクトリではなく、libディレクトリを使用する必要がある。
Linuxカーネルヘッダのインストール (不要)
次に、Linuxの公式Webサイトにアクセスして、Linuxカーネルをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf linux-<バージョン>.tar.xz cd linux-<バージョン>
または、git clone
コマンドを実行して、Linuxカーネルをダウンロードする。
git clone --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git cd linux
Linuxのヘッダファイルをインストールする。
make -j $(nproc) headers_install INSTALL_HDR_PATH=<GLIBCのインストールディレクトリ>
ロケールデータ
まず、GLIBCのインストールディレクトリ内に、ロケールデータが正しく含まれているかどうかを確認する。
/<GLIBCのインストールディレクトリ>/share/i18n/locales /<GLIBCのインストールディレクトリ>/share/i18n/charmaps
次に、ロケールデータを生成する。
# 日本語のロケールデータを生成する場合 mkdir /<GLIBCのインストールディレクトリ>/lib/locale /<GLIBCのインストールディレクトリ>/bin/localedef -i ja_JP -f UTF-8 /<GLIBCのインストールディレクトリ>/lib/locale/ja_JP.UTF-8
必要ならば、ロケール環境変数を設定する。
ローカルインストールしたGLIBCを使用して任意のソフトウェアを実行する場合、以下に示す環境変数の設定が必要になる可能性がある。
export LOCPATH=/<GLIBCのインストールディレクトリ>/lib/locale export LOCALE_ARCHIVE=/<GLIBCのインストールディレクトリ>/lib/locale/locale-archive
GLIBCの確認
まず、インストールしたGLIBCのバージョンを確認する。
strings /<GLIBCのインストールディレクトリ>/lib/libc.so.6 | grep GLIBC_
次に、ビルドしたGLIBCを使用して、ソフトウェアを実行する。
ビルドディレクトリにあるtestrun.shファイルを使用して、以下のようにコマンドを実行する。
/<GLIBCのビルドディレクトリ>/build/testrun.sh <実行するソフトウェアのパス>
GLIBCを使用したソフトウェアの実行
GLIBCを使用してソフトウェアを実行する場合、再リンクする必要がある。
- まず、個別にインストールしたGLIBCのld-linux-x86-64.so.2ライブラリを直接実行して、パラメータとしてソフトウェアのパスを渡す。
これにより、ソフトウェアを再ビルドすることなく、ld-linux-x86-64.so.2ライブラリを置き換えることができる。
/<GLIBCのインストールディレクトリ>/lib/ld-linux-x86-64.so.2 \ --library-path /<GLIBCのインストールディレクトリ>/lib64:/<GLIBCのインストールディレクトリ>/lib:/usr/lib64:/usr/lib:/lib64:/lib \ <ソフトウェアの実行ファイルのパス>
# FileZillaを実行する場合
export PATH="/<FileZillaのインストールディレクトリ>/bin:$PATH"; \
export FZ_DATADIR="/<FileZillaのインストールディレクトリ>/share/filezilla"
/<GLIBCのインストールディレクトリ>/lib/ld-linux-x86-64.so.2 \
--library-path /<GLIBCのインストールディレクトリ>/lib64:/<GLIBCのインストールディレクトリ>/lib:/usr/lib64:/usr/lib:/lib64:/lib \
/<FileZillaのインストールディレクトリ>/bin/filezilla
GLIBCを使用したソフトウェアのビルド
同じシステム上で複数のバージョンのGLIBCを使用することは可能である。
しかし、GLIBCは多くのモジュールから(200以上の共有ライブラリ)から構成されており、それらが全て一致する必要がある。
例えば、ld-linux-x86-64.so.2ライブラリはlibc.so.6ライブラリと一致しなければ、エラーが発生する。
ld-linux-x86-64.so.2ライブラリへの絶対パスは、リンク時に実行ファイルにハードコードされており、リンク後は簡単に変更できない。
(patchelfを使用することで可能である)
ソフトウェアを再リンクする場合、以下の方法がある。
- patchelfを使用する。
既にビルドされたELFのパスとインタプリタを変更することができる。 - 個別にインストールしたGLIBCのld-linux-x86-64.so.2ライブラリを直接実行して、パラメータとしてソフトウェアのパスを渡す。
ソフトウェアを再ビルドすることなく、ld-linux-x86-64.so.2ライブラリを置き換えることができる。/<GLIBCのインストールディレクトリ>/lib/ld-linux-x86-64.so.2 \
--library-path /<GLIBCのインストールディレクトリ>/lib64:/<GLIBCのインストールディレクトリ>/lib:/usr/lib64:/usr/lib:/lib64:/lib \
<ソフトウェアの実行ファイルのパス>
- 適切なchroot環境を設定する。
- rtldiとバイナリエディタを使用する。
インストールしたGLIBCを使用してソフトウェアをビルドする場合
リンカオプションのrpath
オプションを指定して、ランタイムローダがGLIBCのインストールディレクトリにあるライブラリを検索する。
./configure --prefix=<インストールするソフトウェアのディレクトリ> \ LDFLAGS="-Wl,-rpath <GLIBCのインストールディレクトリ>/lib -Wl,--dynamic-linker=<GLIBCのインストールディレクトリ>/lib/ld-linux-x86-64.so.2"
dynamic-linker
オプションは、ld-linux-x86-64.so.2ライブラリへのパスをソフトウェアの実行ファイルに焼き付ける設定である。
(dynamic-linker
オプションは、ELF実行ファイル用にコンパイルする場合にのみ動作する)
patchelfを使用してソフトウェアを実行する場合
まず、ソフトウェアの実行ファイルをバックアップする。
(patchelfの実行後は、rpathに指定されているパスを復元できないため)
patchelfのGithubから、patchelfをダウンロードする。
git clone https://github.com/NixOS/patchelf.git
実行ファイルに対して、patchelfを実行する。
./patchelf -set-interpreter /<GLIBCのインストールディレクトリ>/lib/ld-linux-x86-64.so.2 \ -set-rpath <GLIBCのインストールディレクトリ> \ <ソフトウェアの実行ファイルのパス>
新しく生成された実行ファイルを実行する。
./<ソフトウェアの実行ファイル>
Linux上でソフトウェアを実行する場合、実行ファイルは①リンカ、②ライブラリの順に読み込む。
もし、リンカに問題がある時、実行ファイルがどのパスを探しているのかを知りたい場合、以下のコマンドで確認することができる。
readelf -l <ソフトウェアの実行ファイルのパス> | grep interpreter
もし、ライブラリファイルに問題がある場合、実行ファイルが必要とするライブラリファイル群を確認する。
readelf -d <ソフトウェアの実行ファイルのパス> | grep Shared ldd <ソフトウェアの実行ファイルのパス>
patchelfは、上記2つの問題に関連して、ソフトウェアを実行する時に遭遇する様々な問題に対して動作する。
例えば、"ELF file OS ABI invalid"と表示される場合、新しいローダを設定する(コマンドの-set-interpreter部分)ことで解決する場合がある。
また、ソフトウェアの実行時に"No such file or directory"と表示される場合、新しいインタプリタを設定することで解決する。