Tek bir ana bilgisayarda birden fazla glibc kütüphanesi


171

Tek bir ana bilgisayarda birden fazla glibc kütüphanesi

Linux (SLES-8) sunucum şu anda glibc-2.2.5-235'e sahip, ancak bu sürümde çalışmayan ve glibc-2.3.3 gerektiren bir programım var.

Aynı ana bilgisayara birden fazla glibcs ​​yüklenmiş olabilir mi?

Bu benim program eski glibc üzerinde çalıştırmak aldığımda hata:

./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)

Bu yüzden newglibc adlı yeni bir dizin oluşturdum ve aşağıdaki dosyaları kopyaladım:

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

ve

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Ama bir hata alıyorum:

./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)

Öyleyse hala / lib ile bağlantı kuruyorlar ve onları koyduğum yerden almıyorlar mı?

Teşekkürler


1
SLES-11 sunucusuyla aynı sorun. Güncelleme yapılamıyor ve son zamanlara ihtiyaç duyuluyor. oh my ...
UmNyobe

FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH yaptığı benim için sorunu çözmek! Kesinlikle herkes için işe yaramaz, ama işe yarıyorsa kolay bir düzeltme! Teşekkürler! :)
rinogo

Yanıtlar:


229

Aynı sistemde birden fazla glibc sürümüne sahip olmak mümkündür (bunu her gün yapıyoruz).

Ancak, glibc'in hepsinin eşleşmesi gereken birçok parçadan (200+ paylaşılan kütüphane) oluştuğunu bilmeniz gerekir. Parçalardan biri ld-linux.so.2 olduğunu ve gereken libc.so.6 eşleşmeli veya Gördüğünüz hataları görürsünüz.

Ld-linux.so.2 dosyasının mutlak yolu, bağlantı sırasında yürütülebilir dosyaya sabit kodlanmıştır ve bağlantı yapıldıktan sonra kolayca değiştirilemez.

Yeni glibc ile çalışacak bir yürütülebilir dosya oluşturmak için şunu yapın:

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

-rpathBağlayıcı seçeneği de kütüphaneler için çalışma zamanı yükleyici arama yapacak /path/to/newglibc(sete olmazdı bu yüzden LD_LIBRARY_PATHçalıştırmadan önce) ve -dynamic-linkerdoğru seçeneği olacak "fırında" yol ld-linux.so.2uygulaması içine.

myappUygulamayı yeniden bağlayamıyorsanız (örneğin, üçüncü taraf bir ikili dosya olduğu için), hepsi kaybolmaz, ancak daha zorlaşır. Bir çözüm, chrootbunun için uygun bir ortam oluşturmaktır. Başka bir olasılık rtldi ve bir ikili editör kullanmaktır .


3
Not o -Wl,--dynamic-linker=fileELF çalıştırılabilir düzenleme yapılırken çalışır - ( '' iki sürer). Kontrol/sbin/ldconfig -p | grep ld
Tom

49
Şimdi , zaten derlenmiş ELF'nin rpath'ını ve yorumlayıcısını değiştirmenizi sağlayan kullanışlı bir yardımcı program patchelf( nixos.org/patchelf.html ) kullanabilirsiniz .
Michael Pankov

10
Kullanarak yeni glibc'nin yolunu belirterek söz It değerinde -Wl,--rpathziyade LD_LIBRARY_PATHkolaylık dışındaki nedenlerle önemli olabilir: programı başladı çocuk süreçlerinin ise, değeri LD_LIBRARY_PATHhiçbir görsel olmasa genellikle onlar tarafından miras olacaktır, ama aynı zamanda kullanımı derlenmiş değil daha yeni glibc (örneğin, hisse senedi ikili dosyalarıysa bash), başlamazlar.
HighCommander4

13
Başka bir seçenek yeni ld.so dosyasını doğrudan çalıştırır ve ikili programınızı parametre olarak iletir; Bu, ld.so kullanılır yerine programı yeniden derleme ihtiyacı olmadan yerini alacak:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk


68

Bu soru eski, diğer cevaplar eski. "Rus istihdam" cevap çok iyi ve bilgilendirici, ama sadece kaynak kodu varsa çalışır. Eğer yapmazsanız, o zaman alternatifler çok zor. Neyse ki günümüzde bu soruna (yanıtlarından birinde yorumlandığı gibi) patchelf kullanarak basit bir çözümümüz var . Tüm yapman gereken:

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

Ve bundan sonra dosyanızı yürütebilirsiniz:

$ ./myapp

chrootNeyse ki, ikili dosyaları düzenlemeye veya elle düzenlemeye gerek yok . Ancak ne yaptığınızdan emin değilseniz, ikili dosyanızı değiştirdiğinden, yamalamadan önce ikili dosyalarınızı yedeklemeyi unutmayın. Düzelttikten sonra eski yorumlayıcı / rpath yolunu geri yükleyemezsiniz. Eğer işe yaramazsa, gerçekten işe yarayacak yolu bulana kadar yama yapmaya devam etmeniz gerekir ... Eh, bir deneme yanılma süreci olmak zorunda değildir. Örneğin, OP'nin örneğinde ihtiyacı vardı GLIBC_2.3, böylece hangi lib'in bu sürümü sağladığını kolayca bulabilirsiniz strings:

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

Teorik olarak, ilk grep boş olurdu çünkü sistem libc istediği sürüme sahip değildir ve ikincisi GLIBC_2.3 çıktısı kullanmalıdır çünkü sürümü myappkullanıyor, bu yüzden patchelfikili dosyamızı bu yolu kullanarak yapabileceğimizi biliyoruz .

Linux'ta bir ikili çalıştırmayı denediğinizde, ikili, bağlayıcıyı, ardından kütüphaneleri yüklemeye çalışır ve bunların tümü yolda ve / veya doğru yerde olmalıdır. Sorununuz bağlayıcı ile ilgiliyse ve ikili dosyanızın hangi yolu aradığını bulmak istiyorsanız, bu komutla öğrenebilirsiniz:

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

Sorununuz kütüphanelerde ise, size kullanılan kütüphaneleri verecek komutlar şunlardır:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Bu, ikili gereksiniminiz olan kütüphaneleri listeleyecektir, ancak OP'nin durumunda olduğu gibi zaten hatalar verdikleri için muhtemelen problemli olanları zaten biliyorsunuzdur.

"patchelf", bir programı çalıştırmaya çalışırken karşılaşabileceğiniz birçok farklı sorun için bu 2 sorunla ilgili olarak çalışır. Örneğin: alırsanız ELF file OS ABI invalid, burada--set-interpreter açıkladığım gibi yeni bir yükleyici ( komutun bir parçası) ayarlanarak düzeltilebilir . Başka bir örnek, burada örneklendirildiği gibi orada ve yürütülebilir bir dosyayı çalıştırdığınızda karşılaşma sorunudur . Bu durumda, OP'nin yükleyiciye bir bağlantısı eksikti, ancak belki de sizin durumda root erişiminiz yoktur ve bağlantıyı oluşturamazsınız. Yeni bir tercüman ayarlamak sorununuzu çözecektir.No such file or directory

Anlayış ve çözüm için Rus ve Michael Pankov istihdam!


1
Bu en yararlı oldu! Tensorflow için yeni glibc kullanmak için python ikili yamalı
faizan

Bu temiz bir çözüm (daha önce bilmiyordum patchelf), ancak "İkili düzenlemek için gerek yok" ifadesi biraz yanıltıcı olabilir (çünkü aslında ikili dosyalarınızı düzenlediğiniz için).
larsks

Orada düzeltildi. ;)
msb

Gerçekten yararlı bir yardımcı program! Teşekkür ederim! Her ne kadar sadece bağımlılıkları manuel olarak çözdüğüm saatlerden sonra bir segmentasyon hatası almayı başardım, ancak yönetici ayrıcalıkları olmadan kromu yerel olarak yüklemek için her şeyi
G. Bergeron

@fgiraldeau iltifat için teşekkürler. :) ama soru 2009 yılında sorulmuş, cevaplanmış ve kabul edilmiş, bir cevap kabul etmeden önce 8 yıl beklemek beklemem. heheh; D
msb

20

LD_PRELOAD kullanın: kitaplığınızı man lib dizinlerinden bir yere koyun ve çalıştırın:

LD_PRELOAD='mylibc.so anotherlib.so' program

Bkz: Wikipedia makalesi


1
bunun karmaşık bir Makefile için güzel bir çözüm olacağını düşündüm, ama benim için işe yaramadı
galactica

Bu özellikle hiçbir kaynak ikili olanlar yararlıdır. teşekkürler
kodlayıcı

2
um ... yanılmışım, kaynak derleme ve bağlantı yaparken ld-linux.so / path / to / new / lib / frist'e rpath'a ihtiyacım var gibi görünüyor
kodlayıcı

1
Ld - #. ##. Yani (sistem glibc lib sisteminizden) libc.so. # ile aynı glibc sürümü değilse (alternatif glibc lib'nizden)
Andy

12

Her şeyden önce, dinamik olarak bağlı her programın en önemli bağımlılığı bağlayıcıdır. Tüm kütüphaneler bağlayıcı sürümüyle eşleşmelidir.

Basit exaple yapalım: Ben bazı program çalıştırmak newset ubuntu sistemi var (benim durumumda D derleyici - ldc2). Eski CentOS'ta çalıştırmak istiyorum, ancak eski glibc kütüphanesi nedeniyle imkansız. Bende var

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)

Tüm bağımlılıkları ubuntu'dan centos'a kopyalamalıyım. Uygun yöntem aşağıdaki gibidir:

İlk olarak, tüm bağımlılıkları kontrol edelim:

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 gerçek bir kütüphane değildir ve bununla ilgilenmemiz gerekmez.

/lib64/ld-linux-x86-64.so.2 linux tarafından çalıştırılabilir dosyayı tüm dinamik kütüphanelere bağlayan linker'dir.

Geri kalan dosyalar gerçek kütüphanelerdir ve linker ile birlikte bunların hepsi centos'ta bir yere kopyalanmalıdır.

Tüm kütüphanelerin ve bağlayıcıların "/ mylibs" dizininde olduğunu varsayalım.

ld-linux-x86-64.so.2 - daha önce de söylediğim gibi - bağlayıcıdır. Dinamik kütüphane değil, statik yürütülebilir. Çalıştırabilir ve hatta bazı parametreler olduğunu görebilirsiniz, örneğin --library-path (buna geri döneceğim).

Linux'ta, dinamik olarak bağlantılı program sadece adıyla, örneğin

/bin/ldc2

Linux bu tür bir programı RAM'e yükler ve bunun için hangi bağlayıcıyı ayarladığını kontrol eder. Genellikle, 64 bit sistemde, /lib64/ld-linux-x86-64.so.2 (dosya sisteminizde gerçek yürütülebilir dosyaya sembolik bağlantıdır). Daha sonra linux bağlayıcıyı çalıştırır ve dinamik kütüphaneleri yükler.

Bunu biraz değiştirebilir ve böyle bir hile yapabilirsiniz:

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

Linux'u belirli bir bağlayıcı kullanmaya zorlama yöntemidir.

Ve şimdi bahsedilen önceki parametreye dönebiliriz - library-path

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

Ldc2'yi çalıştırır ve / mylibs'ten dinamik kütüphaneler yükler.

Bu, seçili (sistem varsayılanı değil) kitaplıklarla yürütülebilir dosyayı çağırmak için kullanılan yöntemdir.


RH7'de bir program derledim ve RH6'da çalışmasını istiyorum. Yeni bir yürütülebilir dosya oluşturmak veya patchelf kullanmak istemedim, bu yüzden bu harika bir alternatif.
Mark Rajcok

9

Kurulum 1: Özel GCC olmadan kendi glibc'nizi derleyin ve kullanın

Bu kurulum işe yarayabilir ve tüm GCC araç zincirini yeniden derlemediği için hızlıdır, sadece glibc.

Bu gibi konakçı C çalışma zamanı gibi nesneleri kullanmaktadır Ancak güvenilir değildir crt1.o, crti.ove crtn.oglibc'nin sağladığı. Bu konuda şu adresten bahsedilir: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Bu nesneler glibc'nin dayandığı erken kurulum yapıyor, bu yüzden işler harika bir şekilde çöktüyse şaşırmam ve müthiş ince yollar.

Daha güvenilir bir kurulum için aşağıdaki Kurulum 2'ye bakın.

Glibc oluşturun ve yerel olarak yükleyin:

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`

Kurulum 1: Derlemeyi doğrulayın

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);
}

Derleyin ve çalıştırın 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 beklenen çıktıyı verir:

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

Komut https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location adresinden uyarlandı ancak --sysrootbaşarısız oldu:

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

bu yüzden kaldırdım.

lddoutput, yeni oluşturduğumuz lddve kütüphanelerin gerçekte beklendiği gibi kullanıldığını doğrular :

+ 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)

gccDaha önce belirtildiği, ama bunu geçici bir çözüm için nasıl bilmiyorum kadar kötü benim ev sahibi çalışma zamanı nesneler kullanıldığını derleme ayıklama çıkışı gösterileri, örneğin içerdiği:

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

Kurulum 1: glibc'yi değiştirin

Şimdi glibc'yi aşağıdakilerle değiştirelim:

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)");

Sonra glibc'i yeniden derleyin ve yeniden kurun ve programımızı yeniden derleyip yeniden çalıştırın:

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

ve hackedbeklendiği gibi birkaç kez basıldığını görüyoruz .

Bu ayrıca, ana bilgisayar değil, derlediğimiz glibc'yi kullandığımızı doğrular.

Ubuntu 18.04'te test edildi.

Kurulum 2: Crosstool-NG bozulmamış kurulumu

Bu kurulum 1'e alternatif olduğunu ve ben kadar elde ettik en doğru kurgusunda: herşey C çalışma zamanı gibi nesneleri de dahil olmak üzere, gözlemlemek kadarıyla doğru olduğunu crt1.o, crti.ove crtn.o.

Bu kurulumda, istediğimiz glibc'yi kullanan tam bir özel GCC araç zinciri derleyeceğiz.

Bu yöntemin tek dezavantajı, yapının daha uzun sürecek olmasıdır. Ama daha az bir şeyle bir üretim kurulumu riske atmam.

crosstool-NG , GCC, glibc ve binutils dahil olmak üzere her şeyi kaynağından indirip derleyen bir dizi komut dosyasıdır .

Evet, GCC inşa sistemi o kadar kötü ki bunun için ayrı bir projeye ihtiyacımız var.

Bu kurulum sadece mükemmel değildir, çünkü crosstool-NG,-Wl GCC'nin kendisini oluşturduğumuz için garip hisseden ekstra bayraklar olmadan yürütülebilir dosyalar oluşturmayı desteklemez . Ama her şey işe yarıyor gibi görünüyor, bu yüzden bu sadece bir rahatsızlık.

Crosstool-NG'yi alın, yapılandırın ve oluşturun:

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`

Yapı yaklaşık otuz dakika ila iki saat sürer.

Görebildiğim tek zorunlu yapılandırma seçeneği, doğru çekirdek başlıklarını kullanmak için ana makine çekirdek sürümünüzle eşleşmesini sağlamaktır. Şununla ana makine çekirdek sürümünü bulun:

uname -a

bu bana gösteriyor:

4.15.0-34-generic

böylece menuconfigyapmam:

  • Operating System
    • Version of linux

bu yüzden seçiyorum:

4.14.71

ilk eşit veya eski sürüm. Çekirdek geriye dönük olarak uyumlu olduğundan daha eski olmalıdır.

Kurulum 2: İsteğe bağlı yapılandırmalar

Birlikte .configürettiğimiz ./ct-ng x86_64-unknown-linux-gnu:

CT_GLIBC_V_2_27=y

Bunu değiştirmek menuconfigiçin şunu yapın:

  • C-library
  • Version of glibc

kaydedin .configve derlemeye devam edin.

En son git den glibc kullanmak örneğin kendi glibc kaynağı kullanmak istiyorsanız Veya, devam böyle :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: true olarak ayarlandı
  • C-library
    • Source of glibc
      • Custom location: Evet de
      • Custom location
        • Custom source location: glibc kaynağınızı içeren bir dizinin üzerine gelin

burada glibc şu şekilde klonlandı:

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

Kurulum 2: Test Edin

İstediğiniz araç zincirini oluşturduktan sonra, aşağıdakilerle test edin:

#!/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

Artık doğru çalışma zamanı nesnelerinin kullanılması dışında, her şey Kurulum 1'deki gibi çalışıyor:

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

Kurulum 2: Başarısız verimli glibc yeniden derleme girişimi

Aşağıda açıklandığı gibi crosstool-NG ile mümkün görünmemektedir.

Sadece yeniden inşa ederseniz;

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

özel glibc kaynak konumundaki değişiklikleriniz dikkate alınır, ancak her şeyi sıfırdan oluşturur ve yinelemeli geliştirme için kullanılamaz hale getirir.

Eğer yaparsak:

./ct-ng list-steps

derleme adımlarına güzel bir genel bakış sunar:

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.

bu nedenle, GCC adımlarıyla iç içe geçmiş, en önemlisi libc_start_filesdaha önce gelen glibc adımlarının olduğunu görüyoruz cc_core_pass_2, bu da muhtemelen en pahalı adımdır cc_core_pass_1.

Yalnızca bir adım .configoluşturmak için ilk olarak intial derlemede "Ara adımları kaydet" seçeneğini ayarlamanız gerekir :

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

ve sonra deneyebilirsiniz:

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

ancak maalesef +şu adresten belirtildiği gibi gereklidir: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Ancak, bir ara adımda yeniden başlatmanın kurulum dizinini bu adım sırasındaki durumuna sıfırladığını unutmayın. Yani, yeniden oluşturulmuş bir libc'ye sahip olacaksınız - ancak bu libc ile inşa edilmiş son bir derleyici (ve dolayısıyla libstdc ++ gibi derleyici kütüphaneleri yok).

ve temel olarak, yeniden inşayı geliştirme için mümkün olmayacak kadar yavaş hale getiriyor ve crosstool-NG'yi yamalamadan bunun üstesinden nasıl geleceğini görmüyorum.

Dahası, adımdan başlayarak libckaynağın üzerinden tekrar kopyalanmadı Custom source locationve bu yöntemi daha fazla kullanılamaz hale getirdi.

Bonus: stdlibc ++

C ++ standart kitaplığıyla da ilgileniyorsanız bir bonus: GCC libstdc ++ C ++ standart kitaplık kaynağı nasıl düzenlenir ve yeniden oluşturulur?


6

Nix http://nixos.org/nix/ kullanmayı düşünebilir misiniz ?

Nix çok kullanıcılı paket yönetimini destekler: birden fazla kullanıcı ortak bir Nix mağazasını güvenli bir şekilde paylaşabilir, yazılım yüklemek için kök ayrıcalıklarına sahip olmak zorunda değildir ve bir paketin farklı sürümlerini kurabilir ve kullanabilir.


4

@msb güvenli bir çözüm sunar.

Bu problemi sadece sahip olduğu import tensorflow as tfconda ortamında yaptığım zaman tanıştım .CentOS 6.5glibc-2.12

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

Bazı detayları vermek istiyorum:

İlk glibcönce ana dizininize yükleyin :

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

İkincisi, patchelf'i kurmak için aynı yolu izleyin ;

Üçüncü olarak, Python'unuzu yamalayın:

[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

@msb tarafından belirtildiği gibi

Şimdi kullanabilir tensorflow-2.0 alphaiçinde CentOS 6.5.

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


2

Sorunun hala alakalı olduğundan emin değilim, ancak sorunu düzeltmenin başka bir yolu var: Docker. Kaynak Dağıtımın (geliştirme için kullanılan Dağıtım) neredeyse boş bir kapını yükleyebilir ve dosyaları Kapsayıcıya kopyalayabilirsiniz. Bu şekilde, chroot için gereken dosya sistemini oluşturmanıza gerek yoktur.


1

İkinci çıktıya yakından bakarsanız, kütüphaneler için yeni konumun kullanıldığını görebilirsiniz. Belki de hala glibc'nin bir parçası olan eksik kütüphaneler var.

Programınız tarafından kullanılan tüm kütüphanelerin bu glibc sürümüne göre derlenmesi gerektiğini düşünüyorum. Programın kaynak koduna erişiminiz varsa, yeni bir derleme en iyi çözüm olarak görünmektedir.


1

"Çalışan Rus" en iyi cevap arasındadır ve bence önerilen diğer tüm cevaplar çalışmayabilir. Bunun nedeni, bir uygulama ilk oluşturulduğunda, ihtiyaç duyduğu tüm API'ları derleme zamanında çözülmesidir. "Ldd" u kullanarak statik olarak bağlı tüm bağımlılıkları görebilirsiniz:

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)

Ancak çalışma zamanında, firefox diğer birçok dinamik kütüphaneyi de yükleyecektir, örneğin (firefox için) yüklü birçok "glib" etiketli kitaplık vardır (statik olarak bağlı olmasa bile):

 /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

Manytimes, bir sürümün adlarının başka bir sürüme yumuşak bağlı olduğunu görebilirsiniz. Örneğin:

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

Bu nedenle, bir sistemde farklı "kütüphanelerin" sürümü olduğu anlamına gelir - bu, aynı dosya olduğu için bir sorun değildir ve uygulamaların birden çok sürüm bağımlılığı olduğunda uyumluluklar sağlayacaktır.

Bu nedenle, sistem düzeyinde, tüm kütüphaneler birbirine neredeyse bağımlıdır ve sadece LD_PRELOAD veya LD_LIBRARY_PATH'yi manipüle ederek kütüphanelerin yükleme önceliğini değiştirmek yardımcı olmayacaktır - yükleyebilse bile, çalışma zamanı yine de çökebilir.

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

En iyi alternatif kroottur (kısaca ER tarafından bahsedilir): ancak bunun için orijinal ikili yürütmenin olduğu tüm ortamı yeniden oluşturmanız gerekir - genellikle / lib, / usr / lib /, / usr / lib / x86 vb. "Buildroot" veya YoctoProject kullanabilir veya mevcut bir Distro ortamından katran kullanabilirsiniz. (Fedora / Suse gibi).


0

Ubuntu'da kesin (glibc-2.15) bir krom tarayıcı çalıştırmak istediğimde, "... libc.so.6: sürüm GLIBC_2.19 'bulunamadı ..." iletisini aldım. Dosyaların kalıcı olarak değil, sadece başlangıç ​​için gerekli olduğu gerçeğini düşündüm. Bu yüzden tarayıcı ve sudo için gerekli dosyaları topladım ve bir mini-glibc-2.19- ortamı yarattım, tarayıcıyı başlattım ve orijinal dosyaları tekrar kopyaladım. Gerekli dosyalar RAM'dedir ve orijinal glibc aynıdır.

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)

tarayıcıyı çalıştırmak için komut dosyası:

#!/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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.