Wiele bibliotek glibc na jednym hoście

Wiele bibliotek glibc na jednym hoście

Mój serwer linux (SLES-8) ma obecnie glibc-2.2.5-235, ale mam program, który nie będzie działał na tej wersji i wymaga glibc-2.3.3.

Czy możliwe jest zainstalowanie wielu glibc na tym samym hoście?

Jest to błąd, który pojawia się, gdy uruchamiam mój program na Starym glibc:

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

Więc utworzyłem nowy katalog o nazwie newglibc i skopiowałem następujące pliki:

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

I

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Ale dostaję błąd:

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

Więc wygląda na to, że nadal linkują do / lib i nie odbierają z miejsca, gdzie je umieściłem?

Dzięki

Author: dogbane, 2009-05-11

10 answers

Bardzo możliwe jest posiadanie wielu wersji glibc na tym samym systemie(robimy to codziennie).

Musisz jednak wiedzieć, że glibc składa się z wielu elementów (ponad 200 bibliotek współdzielonych), do których wszystkie muszą pasować. Jednym z elementów jest ld-linux. so. 2 i musi pasować do libc.so. 6, inaczej zobaczysz błędy, które widzisz.

Absolutna ścieżka do ld-linux. so. 2 jest zakodowana w pliku wykonywalnym w czasie łącza i nie może być łatwo zmieniona po tym, jak łącze jest załatwione.

Aby zbudować plik wykonywalny, który będzie działał z nową biblioteką glibc, wykonaj następujące czynności:

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

Opcja -rpath linker spowoduje, że runtime loader będzie wyszukiwał biblioteki w /path/to/newglibc (więc nie będziesz musiał ustawiać LD_LIBRARY_PATH przed uruchomieniem), a opcja -dynamic-linker będzie "piec" ścieżkę do poprawienia ld-linux.so.2 do aplikacji.

Jeśli nie możesz ponownie połączyć aplikacji myapp (np. ponieważ jest to plik binarny innej firmy), nie wszystko jest stracone, ale staje się trudniejsze. Jednym z rozwiązań jest ustawienie właściwego chroot środowisko dla niego. Inną możliwością jest użycie rtldi i edytora binarnego .

 176
Author: Employed Russian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 00:35:37

Użyj LD_PRELOAD: umieść swoją bibliotekę gdzieś z katalogów man lib i uruchom:

LD_PRELOAD='mylibc.so anotherlib.so' program

Zobacz: Artykuł w Wikipedii

 17
Author: PiedPiper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-11 22:36:00

To pytanie jest stare, inne odpowiedzi są stare. Odpowiedź "zatrudniony Rosyjski" jest bardzo dobra i pouczająca, ale to działa tylko, jeśli masz kod źródłowy. Jeśli nie, wtedy alternatywy były bardzo trudne. Na szczęście w dzisiejszych czasach mamy proste rozwiązanie tego problemu (jak skomentował w jednej z jego odpowiedzi), używając patchelf . Wszystko co musisz zrobić to:

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

A potem możesz po prostu wykonać swój plik:

$ ./myapp

Nie trzeba chroot lub ręcznie edytować binaria, na szczęście. Pamiętaj jednak, aby wykonać kopię zapasową pliku binarnego przed jego poprawką, jeśli nie jesteś pewien, co robisz, ponieważ modyfikuje on Twój plik binarny. Po poprawieniu nie można przywrócić starej ścieżki do interpretera/rpath. Jeśli to nie zadziała, będziesz musiał go łatać, dopóki nie znajdziesz ścieżki, która faktycznie zadziała... To nie musi być proces prób i błędów. Na przykład w przykładzie OP, potrzebował GLIBC_2.3, więc można łatwo znaleźć, która lib udostępnia tę wersję za pomocą strings:

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

Teoretycznie pierwszy grep byłby pusty, ponieważ systemowa libc nie ma żądanej wersji, a drugi powinien wypisać GLIBC_2.3, ponieważ ma wersję myapp, której używa, więc wiemy, że możemy patchelf użyć naszej binarnej ścieżki.

Kiedy próbujesz uruchomić plik binarny w Linuksie, plik binarny próbuje załadować linker, a następnie biblioteki i wszystkie powinny znajdować się w ścieżce i/lub we właściwym miejscu. Jeśli masz problem z linkerem i chcesz się dowiedzieć której ścieżki szuka Twój plik binarny, możesz dowiedzieć się za pomocą tego polecenia:

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

Jeśli masz problem z bibliotekami, komendy, które dadzą ci używane biblioteki to:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Wyświetli listę bibliotek, których potrzebuje twój binarny, ale prawdopodobnie znasz już problematyczne, ponieważ już generują błędy, jak w przypadku OP.

"patchelf" działa na wiele różnych problemów, które możesz napotkać podczas próby uruchomienia programu, związanych z tymi 2 problemami. Na przykład, jeśli otrzymasz: ELF file OS ABI invalid, można to naprawić, ustawiając nowy loader (część --set-interpreter polecenia), jak wyjaśniam tutaj. Innym przykładem jest problem uzyskania No such file or directory podczas uruchamiania pliku, który jest tam i wykonywalny, jak na przykładzie tutaj . W tym konkretnym przypadku OP brakowało linku do loadera, ale może w Twoim przypadku nie masz dostępu do roota i nie możesz utworzyć linku. Ustawienie nowego interpretera rozwiązałoby twój problem.

Dzięki Rosyjski i Michael Pankov za wgląd i rozwiązanie!

 16
Author: msb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-06 22:52:13

Czy można rozważyć użycie Nix http://nixos.org/nix / ?

Nix obsługuje zarządzanie pakietami dla wielu użytkowników: wielu użytkowników może udostępniać wspólne Nix przechowywać bezpiecznie, nie trzeba mieć uprawnień roota do instalować oprogramowanie, a może instalować i używać różnych wersji paczka.

 6
Author: Igor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-31 11:10:46

Przede wszystkim najważniejszą zależnością każdego dynamicznie połączonego programu jest linker. Wszystkie biblioteki so muszą pasować do wersji linkera.

Weźmy prosty exaple: mam system newset ubuntu, w którym uruchamiam jakiś program (w moim przypadku jest to kompilator D - ldc2). Chciałbym uruchomić go na Starym CentOS, ale ze względu na starszą bibliotekę glibc jest to niemożliwe. Mam

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)

Muszę skopiować wszystkie zależności z ubuntu do centos. Właściwą metodą jest "po": {]}

Najpierw sprawdźmy wszystkie zależności:

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 nie jest prawdziwą biblioteką i nie musimy się nią przejmować.

/ lib64 / ld-linux-x86-64.so.2 jest linkerem, który jest używany przez Linuksa do łączenia pliku wykonywalnego ze wszystkimi bibliotekami dynamicznymi.

Reszta plików to prawdziwe biblioteki i wszystkie razem z linkerem muszą być skopiowane gdzieś w centos.

Załóżmy, że wszystkie biblioteki i linker są w " / mylibs" katalog.

Ld-linux-x86-64. so. 2 - Jak już mówiłem-jest linkerem. Nie jest to biblioteka dynamiczna, ale statyczna. Możesz go uruchomić i zobaczyć, że ma nawet jakieś parametry, np. --library-path (wrócę do niego).

Na Linuksie dynamicznie linkowany program może być uruchamiany tylko po jego nazwie, np.

/bin/ldc2

Linux ładuje taki program do pamięci RAM i sprawdza, który linker jest dla niego ustawiony. Zazwyczaj w systemie 64-bitowym jest to /lib64/ld-linux-x86-64. so. 2 (w Twoim systemie plików jest to dowiązanie symboliczne do rzeczywistego pliku wykonywalnego). Następnie linux uruchamia linker i ładuje dynamiczne biblioteki.

Możesz też to trochę zmienić i zrobić taki trik:

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

Jest to metoda zmuszająca Linuksa do używania określonego linkera.

I teraz możemy powrócić do wspomnianego wcześniej parametru --library-path

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

Uruchomi ldc2 i załaduje dynamiczne biblioteki z /mylibs.

Jest to metoda wywołania pliku wykonywalnego z wybranym (nie domyślnym systemem) biblioteki.

 5
Author: Arkadiusz Rychliński,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-04 21:01:45

Jeśli przyjrzysz się uważnie drugiemu wyjściu, zobaczysz, że używana jest nowa lokalizacja bibliotek. Być może wciąż brakuje bibliotek, które są częścią glibc.

Myślę również, że wszystkie biblioteki używane przez twój program powinny być skompilowane z tą wersją glibc. Jeśli masz dostęp do kodu źródłowego programu, świeża kompilacja wydaje się być najlepszym rozwiązaniem.

 1
Author: rsarro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-11 16:06:08

"zatrudniony Rosyjski" jest jedną z najlepszych odpowiedzi, i myślę, że wszystkie inne sugerowane odpowiedź może nie działać. Powodem jest po prostu to, że gdy aplikacja jest tworzona po raz pierwszy, wszystkie jej API, których potrzebuje, są rozwiązywane w czasie kompilacji. Używając "ldd" u można zobaczyć wszystkie statycznie powiązane zależności:

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)

Ale w czasie wykonywania, firefox załaduje również wiele innych bibliotek dynamicznych, np. (dla Firefoksa) jest wiele bibliotek o etykiecie "glib"załadowanych (nawet jeśli statycznie są połączone brak): {]}

 /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

Wiele razy można zobaczyć nazwy jednej wersji, która jest miękko połączona z inną wersją. Eg:

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

Oznacza to zatem, że różne wersje "bibliotek"istnieją w jednym systemie - co nie stanowi problemu, ponieważ jest to ten sam plik i zapewni kompatybilność, gdy aplikacje będą miały wiele zależności od wersji.

Dlatego na poziomie systemu wszystkie biblioteki są niemal wzajemnie od siebie zależne, a jedynie zmiana priorytetu ładowania bibliotek manipulowanie LD_PRELOAD lub LD_LIBRARY_PATH nie pomoże - nawet może się załadować, runtime może się zawiesić.

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

Najlepszą alternatywą jest chroot (wspomniany krótko przez ER): ale w tym celu będziesz musiał odtworzyć całe środowisko, w którym znajduje się oryginalny binarny execute - zwykle zaczynając od /lib,/usr/ lib/,/usr/lib / x86 itd. Możesz albo użyć "Buildroot", albo YoctoProject, albo po prostu tar z istniejące środowisko Distro. (jak Fedora/SUSE itp.).

 1
Author: Peter Teoh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 00:41:34

Nie jestem pewien, czy pytanie jest nadal aktualne, ale jest inny sposób na naprawienie problemu: Docker. Można zainstalować prawie pusty kontener dystrybucji źródłowej (dystrybucji używanej do rozwoju) i skopiować pliki do kontenera. W ten sposób nie trzeba tworzyć systemu plików potrzebnego dla chroot.

 1
Author: user1396055,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-19 18:44:10

Setup 1: skompiluj własny glibc bez dedykowanego GCC i użyj go

Ta konfiguracja może działać i jest szybka, ponieważ nie rekompiluje całego łańcucha narzędzi GCC, tylko glibc.

Ale nie jest niezawodny, ponieważ używa hosta C runtime obiektów takich jak crt1.o, crti.o, i crtn.o dostarczone przez glibc. Jest to wymienione w: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location te obiekty robią wczesną konfigurację, którą glibc nie zdziwiłbym się, gdyby wszystko przebiegło w cudowny i niesamowicie subtelny sposób.

Aby uzyskać bardziej niezawodną konfigurację, zobacz Setup 2 poniżej.

Zbuduj glibc i zainstaluj lokalnie:

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: verify the 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.
     * https://stackoverflow.com/questions/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);
}

Skompiluj i uruchom z 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 wyświetla oczekiwane:

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

Polecenie zaadaptowane z https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location{[67]ale--sysroot udało się z:

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

Więc go usunąłem.

ldd wyjście potwierdza, że ldd i biblioteki, które właśnie zbudowaliśmy, są używane zgodnie z oczekiwaniami:

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

Wyjście debugowania kompilacji gcc pokazuje, że użyto moich obiektów runtime hosta, co jest złe, jak wspomniano wcześniej, ale nie wiem, jak to obejść zawiera np.:

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

Setup 1: modify glibc

Teraz zmodyfikujmy glibc za pomocą:

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

Następnie przekompiluj i zainstaluj ponownie glibc, a następnie przekompiluj i uruchom ponownie nasz program:

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

I widzimy hacked wydrukowane kilka razy zgodnie z oczekiwaniami.

To dodatkowo potwierdza, że w rzeczywistości użyliśmy skompilowanej biblioteki glibc, a nie hosta.

Testowane na Ubuntu 18.04.

Setup 2: crosstool-ng nieskazitelna konfiguracja

To jest alternatywa dla setup 1 i jest to najbardziej poprawna konfiguracja, jaką osiągnąłem: wszystko jest poprawne, o ile mogę zaobserwować, w tym obiekty C runtime, takie jak crt1.o, crti.o, i crtn.o.

W tej konfiguracji skompilujemy cały dedykowany łańcuch narzędzi GCC, który używa żądanej przez nas biblioteki glibc.

Jedynym minusem tej metody jest to, że budowa potrwa dłużej. Ale nie zaryzykowałbym instalacji produkcyjnej z niczym mniejszym.

Crosstool-NG jest zbiorem skrypty, które pobierają i kompilują dla nas wszystko ze źródła, w tym GCC, glibc i binutils.

Tak system budowania GCC jest tak zły, że potrzebujemy do tego osobnego projektu.

Ta konfiguracja nie jest idealna, ponieważ crosstool - ng nie obsługuje budowania plików wykonywalnych bez dodatkowych -Wl FLAG , co wydaje się dziwne, ponieważ zbudowaliśmy sam GCC. Ale wszystko wydaje się działać, więc jest to tylko niedogodność.

Pobierz crosstool-NG i skonfiguruj it:

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

Jedyną obowiązkową opcją, jaką widzę, jest dopasowanie wersji jądra hosta do poprawnego nagłówka jądra. Znajdź wersję jądra hosta za pomocą:

uname -a

Co pokazuje mi:

4.15.0-34-generic

Więc w menuconfig robię:

  • Operating System
    • Version of linux

Więc wybieram:

4.14.71

Który jest pierwszą równą lub starszą wersją. Musi być starszy, ponieważ jądro jest wstecz kompatybilny.

Teraz możesz budować z:

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

A teraz poczekaj około trzydziestu minut do dwóch godzin na kompilację.

Konfiguracja 2: opcjonalne konfiguracje

.config które wygenerowaliśmy z ./ct-ng x86_64-unknown-linux-gnu ma:

CT_GLIBC_V_2_27=y

Aby to zmienić, w menuconfig do:

  • C-library
  • Version of glibc

Zapisz .config i kontynuuj budowanie.

Lub, jeśli chcesz użyć własnego źródła glibc, np. aby użyć glibc z najnowszy git, Kontynuuj tak :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: Ustaw na true
  • C-library
    • Source of glibc
      • Custom location: Powiedz TAK
      • Custom location
        • Custom source location: wskaż katalog zawierający źródło glibc

Gdzie glibc został sklonowany jako:

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

Setup 2: przetestuj to

Gdy już zbudujesz on toolchain, że ty chcesz, przetestuj go za pomocą:

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

Wszystko wydaje się działać jak w Setup 1, z tym wyjątkiem, że teraz zostały użyte odpowiednie obiekty runtime:

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

Konfiguracja 2: nieudana próba skutecznej rekompilacji glibc

Nie wydaje się to możliwe z crosstool-NG, jak wyjaśniono poniżej.

If you just re-build;

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

Wtedy twoje zmiany w niestandardowej lokalizacji źródła glibc są brane pod uwagę, ale buduje ona wszystko od zera, przez co nie nadaje się do iteracji rozwój.

Jeśli zrobimy:

./ct-ng list-steps
To daje ładny przegląd kroków budowania:
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.

Dlatego widzimy, że istnieją kroki glibc splecione z kilkoma krokami GCC, w szczególności libc_start_files jest przed cc_core_pass_2, co jest prawdopodobnie najdroższym krokiem razem z cc_core_pass_1.

Aby zbudować tylko jeden krok, musisz najpierw ustawić opcję "Zapisz kroki pośrednie" w opcji .config dla intial Budowa:

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

A potem możesz spróbować:

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

Ale niestety, + wymagane jak wspomniano w: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Należy jednak pamiętać, że ponowne uruchomienie w pośrednim kroku resetuje katalog instalacyjny do stanu, który miał podczas tego kroku. Czyli będziesz miał przebudowana libc - ale żaden ostateczny kompilator zbudowany z tą libc (a więc również żadne biblioteki kompilatorów, takie jak libstdc++).

I zasadniczo nadal sprawia, że odbudowa jest zbyt powolna, aby mogła być wykonalna dla rozwoju, i nie widzę, jak to przezwyciężyć bez patchowania crosstool-NG.

Co więcej, począwszy od kroku libc wydawało się, że nie skopiowano ponownie źródła z Custom source location, co spowodowało, że ta metoda nie była możliwa do użycia.

Bonus: stdlibc++

Bonus, jeśli jesteś również interesuje Cię biblioteka standardowa C++: jak edytować i ponownie budować źródło biblioteki standardowej GCC libstdc++ C++?

 1
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 17:00:24

Kiedy chciałem uruchomić przeglądarkę chromium na Ubuntu (glibc-2.15), dostałem (typowa) wiadomość "... libc.so.6: nie znaleziono wersji `GLIBC_2. 19'...". Rozważałem fakt, że pliki nie są potrzebne permamentnie, a tylko na początek. Więc zebrałem pliki potrzebne do przeglądarki i sudo i utworzyłem mini-glibc-2.19- środowiska, uruchomił przeglądarkę, a następnie skopiował oryginalne pliki z powrotem jeszcze raz. Potrzebne pliki są w pamięci RAM i oryginalny glibc jest taki sam.

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)

Skrypt do uruchomienia przeglądarki:

#!/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
 0
Author: dudu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-29 23:16:37