Beberapa pustaka glibc pada satu host


171

Beberapa pustaka glibc pada satu host

Server linux (SLES-8) saya saat ini memiliki glibc-2.2.5-235, tetapi saya memiliki program yang tidak dapat digunakan pada versi ini dan membutuhkan glibc-2.3.3.

Apakah mungkin untuk menginstal beberapa glibcs ​​pada host yang sama?

Ini adalah kesalahan yang saya dapatkan ketika saya menjalankan program saya di glibc lama:

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

Jadi saya membuat direktori baru bernama newglibc dan menyalin file-file berikut ke:

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

dan

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Tapi saya mendapat kesalahan:

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

Jadi sepertinya mereka masih terhubung ke / lib dan tidak mengambil dari tempat saya meletakkannya?

Terima kasih


1
masalah yang sama dengan server SLES-11. Tidak dapat memperbarui dan membutuhkan hal-hal terbaru. oh my ...
UmNyobe

FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH memang memecahkan masalah bagi saya! Ini tentu saja tidak akan berhasil untuk semua orang, tetapi ini adalah perbaikan yang mudah jika berhasil! Terima kasih! :)
rinogo

Jawaban:


229

Sangat mungkin untuk memiliki beberapa versi glibc pada sistem yang sama (kami melakukannya setiap hari).

Namun, Anda perlu tahu bahwa glibc terdiri dari banyak bagian (200+ pustaka bersama) yang semuanya harus cocok. Salah satunya adalah ld-linux.so.2, dan itu harus cocok dengan libc.so.6, atau Anda akan melihat kesalahan yang Anda lihat.

Path absolut ke ld-linux.so.2 adalah hard-coded menjadi executable pada waktu link, dan tidak dapat dengan mudah diubah setelah tautan selesai.

Untuk membangun yang dapat dieksekusi yang akan bekerja dengan glibc baru, lakukan ini:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

The -rpathpilihan linker akan membuat runtime pencarian loader untuk perpustakaan di /path/to/newglibc(sehingga Anda tidak perlu set LD_LIBRARY_PATHsebelum menjalankannya), dan -dynamic-linkerpilihan akan "panggang" jalan untuk benar ld-linux.so.2ke dalam aplikasi.

Jika Anda tidak dapat menautkan kembali myappaplikasi (mis. Karena ini adalah biner pihak ketiga), tidak semua hilang, tetapi akan semakin rumit. Salah satu solusinya adalah menetapkan chrootlingkungan yang tepat untuknya. Kemungkinan lain adalah menggunakan rtldi dan editor biner .


3
Perhatikan bahwa -Wl,--dynamic-linker=file(butuh dua '-') hanya berfungsi saat kompilasi untuk executable ELF. Periksa/sbin/ldconfig -p | grep ld
Tom

49
Sekarang Anda dapat menggunakan utilitas yang mudah digunakan patchelf( nixos.org/patchelf.html ), yang memungkinkan Anda untuk memodifikasi rpath dan interpreter dari ELF yang sudah dikompilasi.
Michael Pankov

10
Perlu disebutkan bahwa menentukan jalur ke glibc baru menggunakan -Wl,--rpathdaripadaLD_LIBRARY_PATH penting untuk alasan lain selain kenyamanan: jika program meluncurkan proses anak, nilai LD_LIBRARY_PATHbiasanya akan diwarisi oleh mereka, tetapi jika mereka juga tidak dikompilasi untuk menggunakan glibc yang lebih baru (misalnya, jika mereka seperti binari saham bash), mereka tidak akan diluncurkan.
HighCommander4

13
Opsi lain adalah menjalankan ld.so baru secara langsung, meneruskannya program biner Anda sebagai parameter; ini akan secara efektif menggantikan ld.so yang digunakan tanpa perlu mengkompilasi ulang program:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk


67

Pertanyaan ini sudah tua, jawaban yang lain sudah tua. Jawaban "Employed Russian" sangat bagus dan informatif, tetapi hanya berfungsi jika Anda memiliki kode sumber. Jika tidak, alternatif saat itu sangat sulit. Untungnya saat ini kami memiliki solusi sederhana untuk masalah ini (seperti yang dikomentari dalam salah satu balasannya), menggunakan patchelf . Yang harus Anda lakukan adalah:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

Dan setelah itu, Anda bisa menjalankan file Anda:

$ ./myapp

chrootUntungnya, tidak perlu atau secara manual mengedit binari. Tapi ingat untuk membuat cadangan biner Anda sebelum menambalnya, jika Anda tidak yakin apa yang Anda lakukan, karena memodifikasi file biner Anda. Setelah Anda menambalnya, Anda tidak dapat mengembalikan jalur lama ke interpreter / rpath. Jika tidak berhasil, Anda harus terus menambalnya sampai Anda menemukan jalan yang benar-benar berfungsi ... Yah, itu tidak harus menjadi proses coba-coba. Misalnya, dalam contoh OP, ia perlu GLIBC_2.3, sehingga Anda dapat dengan mudah menemukan lib yang menyediakan versi itu menggunakan strings:

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

Secara teori, grep pertama akan kosong karena sistem libc tidak memiliki versi yang diinginkannya, dan grep ke-2 harus menampilkan GLIBC_2.3 karena memiliki versi myappyang digunakan, jadi kami tahu patchelfbahwa biner kami dapat menggunakan jalur itu.

Ketika Anda mencoba menjalankan biner di linux, biner mencoba memuat tautan, lalu pustaka, dan semuanya harus berada di jalur dan / atau di tempat yang tepat. Jika masalah Anda ada pada tautan dan Anda ingin mencari tahu jalur mana yang dicari biner Anda, Anda bisa mengetahuinya dengan perintah ini:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

Jika masalah Anda dengan libs, perintah yang akan memberi Anda libs yang digunakan adalah:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Ini akan mencantumkan lib yang dibutuhkan biner Anda, tetapi Anda mungkin sudah tahu yang bermasalah, karena mereka sudah menghasilkan kesalahan seperti dalam kasus OP.

"patchelf" berfungsi untuk banyak masalah berbeda yang mungkin Anda temui saat mencoba menjalankan suatu program, terkait dengan 2 masalah ini. Misalnya, jika Anda mendapatkan ELF file OS ABI invalid:, mungkin diperbaiki dengan menetapkan loader baru ( --set-interpreterbagian dari perintah) seperti yang saya jelaskan sini . Contoh lain adalah untuk masalah mendapatkan No such file or directoryketika Anda menjalankan file yang ada dan dapat dieksekusi, seperti dicontohkan di sini . Dalam kasus khusus itu, OP tidak memiliki tautan ke loader, tetapi mungkin dalam kasus Anda Anda tidak memiliki akses root dan tidak dapat membuat tautan. Mengatur juru bahasa baru akan menyelesaikan masalah Anda.

Terima kasih Mempekerjakan Rusia dan Michael Pankov untuk wawasan dan solusi!


1
Ini yang paling membantu! Saya menambal biner python untuk menggunakan glibc baru untuk tensorflow
faizan

Ini adalah solusi yang rapi (saya belum pernah tahu sebelumnya patchelf), tetapi frasa "Tidak perlu ... mengedit binari" mungkin sedikit menyesatkan (karena Anda sebenarnya mengedit binari Anda).
larsks

Di sana, diperbaiki. ;)
msb

Utilitas yang sangat membantu! Terima kasih! Meskipun saya hanya berhasil mendapatkan kesalahan segmentasi setelah berjam-jam menyelesaikan dependensi secara manual kemudian menambal semuanya untuk menginstal chrome secara lokal tanpa hak admin ...
G. Bergeron

@fgiraldeau terima kasih atas pujiannya. :) tetapi pertanyaan itu diajukan, dijawab dan diterima pada tahun 2009, saya tidak akan mengharapkan seseorang menunggu 8 tahun sebelum menerima jawaban. heheh; D
msb

20

Gunakan LD_PRELOAD: letakkan perpustakaan Anda di suatu tempat dari direktori man lib dan jalankan:

LD_PRELOAD='mylibc.so anotherlib.so' program

Lihat: artikel Wikipedia


1
berpikir ini akan menjadi solusi yang bagus untuk Makefile yang kompleks, tetapi itu tidak berhasil untuk saya
galactica

itu berguna terutama yang tidak ada sumber binary.thanks
coder

2
um ... saya salah ,, sepertinya saya perlu membuka ld-linux.so ke / path / ke / new / lib / frist saat source compile & menghubungkan
coder

1
Ini tidak berfungsi jika ld - #. ##. Jadi (dari sistem Anda glibc lib) bukan versi glibc yang sama dengan libc.so. # (dari lib glibc alternatif Anda)
Andy

12

Pertama-tama, ketergantungan paling penting dari setiap program yang terhubung secara dinamis adalah penghubung. Semua perpustakaan harus cocok dengan versi tautannya.

Mari kita ambil contoh sederhana: Saya memiliki sistem ubuntu newset tempat saya menjalankan beberapa program (dalam kasus saya ini adalah kompiler D - ldc2). Saya ingin menjalankannya di CentOS lama, tetapi karena pustaka glibc yang lebih lama, itu tidak mungkin. saya mendapatkan

ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)

Saya harus menyalin semua dependensi dari ubuntu ke centos. Metode yang tepat adalah sebagai berikut:

Pertama, mari kita periksa semua dependensi:

ldd ldc2-1.5.0-linux-x86_64/bin/ldc2 
    linux-vdso.so.1 =>  (0x00007ffebad3f000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)

linux-vdso.so.1 bukan perpustakaan nyata dan kami tidak perlu mempedulikannya.

/lib64/ld-linux-x86-64.so.2 adalah linker, yang digunakan oleh linux do link yang dapat dieksekusi dengan semua pustaka dinamis.

Sisa file adalah perpustakaan nyata dan semuanya bersama dengan linker harus disalin di suatu tempat di centos.

Mari kita asumsikan semua perpustakaan dan tautan ada di direktori "/ mylibs".

ld-linux-x86-64.so.2 - seperti yang sudah saya katakan - adalah penghubungnya. Ini bukan perpustakaan dinamis tetapi dieksekusi statis. Anda dapat menjalankannya dan melihat bahwa ia bahkan memiliki beberapa parameter, misalnya --library-path (saya akan kembali ke sana).

Di linux, program yang terhubung secara dinamis dapat disantap hanya dengan namanya, misalnya

/bin/ldc2

Linux memuat program tersebut ke dalam RAM, dan memeriksa linker mana yang diatur untuk itu. Biasanya, pada sistem 64-bit, ini adalah /lib64/ld-linux-x86-64.so.2 (dalam sistem file Anda ini adalah tautan simbolis ke executable yang sebenarnya). Kemudian linux menjalankan linker dan memuat pustaka dinamis.

Anda juga dapat mengubah ini sedikit dan melakukan trik seperti itu:

/mylibs/ld-linux-x86-64.so.2 /bin/ldc2

Ini adalah metode untuk memaksa linux menggunakan penghubung tertentu.

Dan sekarang kita dapat kembali ke parameter yang disebutkan sebelumnya --library-path

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

Ini akan menjalankan ldc2 dan memuat pustaka dinamis dari / mylibs.

Ini adalah metode untuk memanggil executable dengan pustaka yang dipilih (bukan sistem default).


Saya menyusun program di RH7 dan membutuhkannya untuk berjalan di RH6. Saya tidak ingin membangun executable baru atau menggunakan patchelf, jadi ini adalah alternatif yang bagus.
Mark Rajcok

9

Setup 1: kompilasi glibc Anda sendiri tanpa GCC khusus dan gunakan

Penyiapan ini mungkin berfungsi dan cepat karena tidak mengkompilasi ulang seluruh rantai alat GCC, hanya glibc.

Tapi itu tidak dapat diandalkan karena menggunakan tuan C runtime objek seperti crt1.o, crti.o, dan crtn.odisediakan oleh glibc. Ini disebutkan di: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Benda-benda itu melakukan penyetelan awal yang bergantung pada glibc, jadi saya tidak akan terkejut jika ada hal-hal yang terjadi pada glibc, dan cara-cara yang sangat halus.

Untuk pengaturan yang lebih andal, lihat Pengaturan 2 di bawah ini.

Bangun glibc dan instal secara lokal:

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

Setup 1: verifikasi build

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * /programming/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Kompilasi dan jalankan dengan test_glibc.sh:

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

Program menghasilkan yang diharapkan:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

Perintah diadaptasi dari https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location tetapi --sysrootmembuatnya gagal dengan:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

jadi saya menghapusnya.

lddoutput mengonfirmasi bahwa lddpustaka dan yang baru saja kita bangun sebenarnya digunakan seperti yang diharapkan:

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

The gcckompilasi men-debug output yang menunjukkan bahwa host saya objek runtime yang digunakan, yang buruk seperti yang disebutkan sebelumnya, tapi saya tidak tahu bagaimana bekerja di sekitarnya, misalnya mengandung:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

Pengaturan 1: modifikasi glibc

Sekarang mari kita ubah glibc dengan:

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

Kemudian mengkompilasi ulang dan menginstal ulang glibc, dan mengkompilasi ulang dan menjalankan kembali program kami:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

dan kami melihat hackeddicetak beberapa kali seperti yang diharapkan.

Ini lebih lanjut menegaskan bahwa kami benar-benar menggunakan glibc yang kami kompilasi dan bukan yang host.

Diuji pada Ubuntu 18.04.

Pengaturan 2: pengaturan murni crosstool-NG

Ini adalah sebuah alternatif untuk setup 1, dan itu adalah setup yang benar yang paling saya telah mencapai jauh: semuanya sudah benar sejauh yang saya dapat mengamati, termasuk runtime C objek seperti crt1.o, crti.o, dancrtn.o .

Dalam pengaturan ini, kami akan mengkompilasi toolchain GCC khusus yang menggunakan glibc yang kami inginkan.

Satu-satunya downside ke metode ini adalah bahwa pembangunan akan memakan waktu lebih lama. Tapi saya tidak akan mengambil risiko setup produksi dengan sesuatu yang kurang.

crosstool-NG adalah sekumpulan skrip yang mengunduh dan mengkompilasi semuanya dari sumber untuk kita, termasuk GCC, glibc dan binutils.

Ya sistem build GCC sangat buruk sehingga kami membutuhkan proyek terpisah untuk itu.

Pengaturan ini hanya tidak sempurna karena crosstool-NG tidak mendukung pembuatan executable tanpa -Wlflag tambahan , yang terasa aneh karena kami telah membangun GCC sendiri. Tapi semuanya sepertinya berhasil, jadi ini hanya ketidaknyamanan.

Dapatkan crosstool-NG, konfigurasikan dan bangun:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

Pembangunan memakan waktu sekitar tiga puluh menit hingga dua jam.

Satu-satunya opsi konfigurasi wajib yang dapat saya lihat, adalah membuatnya cocok dengan versi kernel host Anda untuk menggunakan header kernel yang benar. Temukan versi kernel host Anda dengan:

uname -a

yang menunjukkan saya:

4.15.0-34-generic

jadi di menuconfigsaya lakukan:

  • Operating System
    • Version of linux

jadi saya pilih:

4.14.71

yang merupakan versi sama atau lebih tua pertama. Itu harus lebih tua karena kernel kompatibel.

Setup 2: konfigurasi opsional

Yang .configkami hasilkan ./ct-ng x86_64-unknown-linux-gnumemiliki:

CT_GLIBC_V_2_27=y

Untuk mengubahnya, menuconfiglakukan:

  • C-library
  • Version of glibc

Selamatkan .config , dan lanjutkan dengan membangun.

Atau, jika Anda ingin menggunakan sumber glibc Anda sendiri, misalnya untuk menggunakan glibc dari git terbaru, lanjutkan seperti ini :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: disetel ke true
  • C-library
    • Source of glibc
      • Custom location: bilang iya
      • Custom location
        • Custom source location: arahkan ke direktori yang mengandung sumber glibc Anda

di mana glibc dikloning sebagai:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

Setup 2: ujilah

Setelah Anda membangun rantai alat yang Anda inginkan, ujilah dengan:

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

Semuanya tampaknya berfungsi seperti dalam Pengaturan 1, kecuali bahwa sekarang objek runtime yang benar digunakan:

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

Penyiapan 2: upaya rekompilasi glibc gagal yang efisien

Tampaknya tidak mungkin dengan crosstool-NG, seperti yang dijelaskan di bawah ini.

Jika Anda hanya membangun kembali;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

maka perubahan Anda ke lokasi sumber glibc khusus diperhitungkan, tetapi itu membangun semuanya dari awal, sehingga tidak dapat digunakan untuk pengembangan berulang.

Jika kita melakukannya:

./ct-ng list-steps

ini memberikan gambaran bagus tentang langkah-langkah pembuatan:

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

oleh karena itu, kita melihat bahwa ada langkah-langkah glibc yang terkait dengan beberapa langkah GCC, terutama libc_start_filesdatang sebelumnya cc_core_pass_2, yang kemungkinan merupakan langkah paling mahal bersama dengancc_core_pass_1 .

Untuk membangun hanya satu langkah, Anda harus terlebih dahulu mengatur opsi "Simpan langkah-langkah lanjutan" di .configuntuk membangun awal:

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

dan kemudian Anda dapat mencoba:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

tapi sayangnya, +diperlukan seperti yang disebutkan di: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Namun perlu dicatat bahwa memulai kembali pada langkah menengah me-reset direktori instalasi ke keadaan selama langkah itu. Yaitu, Anda akan memiliki libc yang dibangun kembali - tetapi tidak ada kompiler akhir yang dibangun dengan libc ini (dan karenanya, tidak ada perpustakaan kompiler seperti libstdc ++ juga).

dan pada dasarnya masih membuat pembangunan kembali terlalu lambat untuk dapat dikembangkan, dan saya tidak melihat cara mengatasinya tanpa menambal crosstool-NG.

Lebih jauh lagi, mulai dari libclangkah sepertinya tidak menyalin dari sumber lagi dari Custom source location, lebih lanjut membuat metode ini tidak dapat digunakan.

Bonus: stdlibc ++

Bonus jika Anda juga tertarik dengan pustaka standar C ++: Bagaimana cara mengedit dan membangun kembali sumber libstdc GCC ++ C ++ standar?


6

Bisakah Anda mempertimbangkan menggunakan Nix http://nixos.org/nix/ ?

Nix mendukung manajemen paket multi-pengguna: banyak pengguna dapat berbagi toko Nix yang umum dengan aman, tidak perlu memiliki hak akses root untuk menginstal perangkat lunak, dan dapat menginstal dan menggunakan versi paket yang berbeda.


4

@msb memberikan solusi yang aman.

Saya menemukan masalah ini ketika saya melakukannya import tensorflow as tfdi lingkungan conda CentOS 6.5yang hanya memiliki glibc-2.12.

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

Saya ingin memberikan beberapa detail:

Pertama instal glibcke direktori home Anda:

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

Kedua, ikuti cara yang sama untuk menginstal patchelf ;

Ketiga, tempel Python Anda:

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

seperti yang disebutkan oleh @msb

Sekarang saya dapat menggunakan tensorflow-2.0 alphadiCentOS 6.5 .

ref: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/


2

Saya tidak yakin pertanyaannya masih relevan, tetapi ada cara lain untuk memperbaiki masalah: Docker. Seseorang dapat menginstal wadah yang hampir kosong dari Distribusi Sumber (Distribusi yang digunakan untuk pengembangan) dan menyalin file ke Kontainer. Dengan begitu Anda tidak perlu membuat sistem file yang dibutuhkan untuk chroot.


1

Jika Anda melihat dekat pada output kedua Anda dapat melihat bahwa lokasi baru untuk perpustakaan digunakan. Mungkin masih ada perpustakaan yang hilang yang merupakan bagian dari glibc.

Saya juga berpikir bahwa semua perpustakaan yang digunakan oleh program Anda harus dikompilasi terhadap versi glibc. Jika Anda memiliki akses ke kode sumber program, kompilasi baru tampaknya menjadi solusi terbaik.


1

"Mempekerjakan bahasa Rusia" adalah salah satu jawaban terbaik, dan saya pikir semua jawaban yang disarankan lainnya mungkin tidak berfungsi. Alasannya hanya karena ketika aplikasi pertama kali dibuat, semua API yang dibutuhkannya diselesaikan pada waktu kompilasi. Menggunakan "ldd" u dapat melihat semua dependensi yang terhubung secara statis:

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffd5c5f0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)

Tetapi pada saat runtime, firefox juga akan memuat banyak pustaka dinamis lain, misal (untuk firefox) ada banyak pustaka berlabel "glib" yang dimuat (walaupun terhubung secara statis tidak ada):

 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
 /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
 /usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2

Sering kali, Anda dapat melihat nama-nama dari satu versi dihubungkan dengan lembut ke versi lain. Misalnya:

lrwxrwxrwx 1 root root     23 Dec 21  2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar  1  2013 libdbus-glib-1.so.2.2.2

Karena itu ini berarti versi "libraries" yang berbeda ada dalam satu sistem - yang tidak menjadi masalah karena merupakan file yang sama, dan itu akan memberikan kompatibilitas ketika aplikasi memiliki banyak versi dependensi.

Oleh karena itu, pada tingkat sistem, semua pustaka hampir saling bergantung satu sama lain, dan hanya mengubah pustaka yang memuat prioritas melalui memanipulasi LD_PRELOAD atau LD_LIBRARY_PATH tidak akan membantu - meskipun ia dapat memuat, meskipun ia dapat memuat, runtime mungkin masih macet.

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

Alternatif terbaik adalah chroot (disebutkan secara singkat oleh ER): tetapi untuk ini Anda harus membuat ulang seluruh lingkungan yang merupakan biner eksekusi aslinya - biasanya mulai dari / lib, / usr / lib /, / usr / lib / x86 dll. Anda dapat menggunakan "Buildroot", atau YoctoProject, atau hanya tar dari lingkungan Distro yang ada. (seperti Fedora / Suse dll).


0

Ketika saya ingin menjalankan chromium-browser di Ubuntu (glibc-2.15), saya mendapatkan pesan (khas) "... libc.so.6: versi` GLIBC_2.19 'not found ... ". Saya mempertimbangkan fakta, bahwa file tidak diperlukan secara permanen, tetapi hanya untuk memulai. Jadi saya mengumpulkan file yang diperlukan untuk browser dan sudo dan menciptakan lingkungan mini-glibc-2.19-, memulai browser dan kemudian menyalin kembali file aslinya. File yang dibutuhkan dalam RAM dan glibc asli adalah sama.

as root
the files (*-2.15.so) already exist 

mkdir -p /glibc-2.19/i386-linux-gnu

/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so

mkdir -p /glibc-2.15/i386-linux-gnu

/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)

skrip untuk menjalankan browser:

#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.