Múltiples bibliotecas glibc en un solo host


Múltiples bibliotecas glibc en un solo host

Mi servidor linux (SLES-8) actualmente tiene glibc-2.2.5-235, pero tengo un programa que no funcionará en esta versión y requiere glibc-2.3.3.

¿Es posible tener varios glibcs instalados en el mismo host?

Este es el error que obtengo cuando corro mi programa en el viejo 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)

Así que creé un nuevo directorio llamado newglibc y copié los siguientes archivos en:

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

Y

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Pero consigo un error:

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

Así que parece que todavía están enlazando a /lib y no recogiendo de donde los pongo?

Gracias

Author: dogbane, 2009-05-11

10 answers

Es muy posible tener varias versiones de glibc en el mismo sistema (lo hacemos todos los días).

Sin embargo, necesita saber que glibc consta de muchas piezas (más de 200 bibliotecas compartidas) que todas deben coincidir. Una de las piezas es ld-linux.so.2, y debe coincidir con libc.so.6, o verá los errores que está viendo.

La ruta absoluta a ld-linux.so. 2 está codificada en el ejecutable en el momento del enlace, y no se puede cambiar fácilmente después de que el enlace Terminado.

Para construir un ejecutable que funcione con el nuevo glibc, haga esto:

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

La opción enlazador -rpath hará que el cargador de tiempo de ejecución busque bibliotecas en /path/to/newglibc (por lo que no tendría que configurar LD_LIBRARY_PATH antes de ejecutarlo), y la opción -dynamic-linker "horneará" la ruta para corregir ld-linux.so.2 en la aplicación.

Si no puede volver a vincular la aplicación myapp (por ejemplo, porque es un binario de terceros), no todo se pierde, pero se vuelve más complicado. Una solución es establecer un chroot ambiente para ello. Otra posibilidad es usar rtldi y un editor binario .

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-29 00:35:37

Use LD_PRELOAD: ponga su biblioteca en algún lugar fuera de los directorios man lib y ejecute:

LD_PRELOAD='mylibc.so anotherlib.so' program

Ver: el artículo de Wikipedia

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-11 22:36:00

Esta pregunta es vieja, las otras respuestas son viejas. La respuesta de "Ruso empleado" es muy buena e informativa, pero solo funciona si tiene el código fuente. Si no lo haces, las alternativas en ese entonces eran muy difíciles. Afortunadamente hoy en día tenemos una solución simple a este problema (como comentó en una de sus respuestas), usando patchelf. Todo lo que tienes que hacer es:

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

Y después de eso, simplemente puede ejecutar su archivo:

$ ./myapp

No hay necesidad de chroot o editar manualmente binarios, afortunadamente. Pero recuerde hacer una copia de seguridad de su binario antes de parchearlo, si no está seguro de lo que está haciendo, porque modifica su archivo binario. Después de parchearlo, no puede restaurar la ruta antigua a interpreter/rpath. Si no funciona, tendrá que seguir parcheándolo hasta que encuentre el camino que realmente funcionará... Bueno, no tiene que ser un proceso de prueba y error. Por ejemplo, en el ejemplo de OP, necesitaba GLIBC_2.3, por lo que puede encontrar fácilmente qué lib proporciona esa versión usando strings:

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

En teoría, el primer grep vendría vacío porque el sistema libc no tiene la versión que quiere, y el segundo debería mostrar GLIBC_2.3 porque tiene la versión myapp que está usando, así que sabemos que podemos patchelf nuestro binario usando esa ruta.

Cuando intenta ejecutar un binario en linux, el binario intenta cargar el enlazador, luego las bibliotecas, y todas deben estar en la ruta y/o en el lugar correcto. Si tu problema es con el enlazador y quieres averiguarlo qué ruta está buscando su binario, puede averiguarlo con este comando:

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

Si su problema es con las libs, los comandos que le darán las libs que se están utilizando son:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Esto listará las libs que su binario necesita, pero probablemente ya conozca las problemáticas, ya que ya están produciendo errores como en el caso de OP.

"patchelf" funciona para muchos problemas diferentes que puede encontrar al intentar ejecutar un programa, relacionados con estos 2 problemas. Por ejemplo, si obtiene: ELF file OS ABI invalid, puede arreglarse estableciendo un nuevo cargador (la parte --set-interpreter del comando) como explico aquí. Otro ejemplo es para el problema de obtener No such file or directory cuando se ejecuta un archivo que está allí y ejecutable, como se ejemplifica aquí. En ese caso en particular, a OP le faltaba un enlace al cargador, pero tal vez en su caso no tiene acceso de root y no puede crear el enlace. Configurar un nuevo intérprete resolvería su problema.

Gracias Empleado Ruso y Michael Pankov para la visión y la solución!

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 22:52:13

¿Puede considerar usar Nix http://nixos.org/nix / ?

Nix admite la gestión de paquetes multiusuario: varios usuarios pueden compartir un común Nix almacenar de forma segura, no es necesario tener privilegios de root para instalar software, y puede instalar y utilizar diferentes versiones de un paquete.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 11:10:46

En primer lugar, la dependencia más importante de cada programa enlazado dinámicamente es el enlazador. Todas las bibliotecas so deben coincidir con la versión del enlazador.

Tomemos un ejemplo simple: Tengo el sistema newset ubuntu donde corro algún programa (en mi caso es D compiler - ldc2). Me gustaría ejecutarlo en el viejo CentOS, pero debido a la antigua biblioteca glibc es imposible. Tengo

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)

Tengo que copiar todas las dependencias de ubuntu a centos. El método adecuado es siguiente:

Primero, vamos a comprobar todas las dependencias:

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 no es una biblioteca real y no tenemos que preocuparnos por ella.

/lib64/ld-linux-x86-64.so.2 es el enlazador, el cual es usado por linux para enlazar el ejecutable con todas las bibliotecas dinámicas.

El resto de los archivos son bibliotecas reales y todos ellos junto con el enlazador deben copiarse en algún lugar de los centos.

Asumamos que todas las bibliotecas y el enlazador están en " / mylibs" directorio.

Ld-linux-x86-64.so.2 - como ya he dicho - es el enlazador. No es una biblioteca dinámica, sino un ejecutable estático. Puede ejecutarlo y ver que incluso tiene algunos parámetros, por ejemplo library library-path (volveré a él).

En Linux, el programa enlazado dinámicamente puede ser almorzado solo por su nombre, por ejemplo

/bin/ldc2

Linux carga dicho programa en la RAM, y comprueba qué enlazador está configurado para él. Por lo general, en un sistema de 64 bits, es / lib64 / ld-linux-x86-64. so. 2 (en su sistema de archivos es enlace simbólico al ejecutable real). Luego linux ejecuta el enlazador y carga bibliotecas dinámicas.

También puedes cambiar esto un poco y hacer tal truco:

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

Es el método para forzar a linux a usar un enlazador específico.

Y ahora podemos volver al parámetro mencionado anteriormente library library-path

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

Ejecutará ldc2 y cargará bibliotecas dinámicas desde /mylibs.

Este es el método para llamar al ejecutable con choosen (no por defecto del sistema) biblioteca.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-04 21:01:45

Si observa de cerca la segunda salida, puede ver que se utiliza la nueva ubicación para las bibliotecas. Tal vez todavía faltan bibliotecas que son parte de la glibc.

También creo que todas las bibliotecas utilizadas por su programa deben compilarse contra esa versión de glibc. Si tiene acceso al código fuente del programa, una nueva compilación parece ser la mejor solución.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-11 16:06:08

"Ruso empleado" es una de las mejores respuestas, y creo que todas las demás respuestas sugeridas pueden no funcionar. La razón es simplemente porque cuando se crea una aplicación por primera vez, todas sus API que necesita se resuelven en tiempo de compilación. Usando " ldd " u puede ver todas las dependencias estáticamente vinculadas:

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)

Pero en tiempo de ejecución, firefox también cargará muchas otras bibliotecas dinámicas, por ejemplo (para firefox) hay muchas bibliotecas etiquetadas con"glib" cargadas (a pesar de que están vinculadas estáticamente ninguno):

 /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

Muchas veces, puede ver los nombres de una versión que está vinculada a otra versión. 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

Por lo tanto, esto significa que existe una versión diferente de "bibliotecas" en un sistema, lo cual no es un problema, ya que es el mismo archivo, y proporcionará compatibilidades cuando las aplicaciones tengan varias dependencias de versiones.

Por lo tanto, a nivel del sistema, todas las bibliotecas son casi interdependientes entre sí, y simplemente cambian la prioridad de carga de las bibliotecas a través de la manipulación de LD_PRELOAD o LD_LIBRARY_PATH no ayudará-incluso se puede cargar, tiempo de ejecución todavía puede bloquearse.

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

La mejor alternativa es chroot (mencionado brevemente por ER): pero para esto tendrá que recrear todo el entorno en el que se ejecuta el binario original, generalmente a partir de /lib, /usr/lib/, /usr/lib/x86, etc. Puede usar" Buildroot", o YoctoProject, o simplemente tar desde un entorno de distribución existente. (como Fedora/Suse, etc.).

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-09 00:41:34

No estoy seguro de que la pregunta siga siendo relevante, pero hay otra forma de solucionar el problema: Docker. Se puede instalar un contenedor casi vacío de la Distribución Fuente (La Distribución utilizada para el desarrollo) y copiar los archivos en el Contenedor. De esta manera no necesita crear el sistema de archivos necesario para 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 18:44:10

Setup 1: compila tu propio glibc sin GCC dedicado y úsalo

Esta configuración podría funcionar y es rápida ya que no recompila toda la cadena de herramientas de GCC, solo glibc.

Pero no es confiable, ya que utiliza objetos de tiempo de ejecución del host C, como crt1.o, crti.o, y crtn.o proporcionado por glibc. Esto se menciona en: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Esos objetos hacen la configuración temprana que glibc depende de, por lo que no me sorprendería si las cosas se estrellaron de maneras maravillosas e increíblemente sutiles.

Para una configuración más confiable, consulte Configuración 2 a continuación.

Construir glibc e instalarlo localmente:

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`

Configuración 1: verificar la compilació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.
     * 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);
}

Compilar y ejecutar con 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

El programa produce lo esperado:

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

Comando adaptado de https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location pero --sysroot lo hizo fallar con:{[64]]}

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

Así que lo quité.

ldd la salida confirma que ldd y las bibliotecas que acabamos de construir se están utilizando como se esperaba:

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

La salida de depuración de la compilación gcc muestra que se usaron mis objetos de tiempo de ejecución del host, lo cual es malo como se mencionó anteriormente, pero no se cómo evitar it, e. g. it contains:

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

Configuración 1: modificar glibc

Ahora vamos a modificar glibc con:

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

Luego recompile y vuelva a instalar glibc, y recompile y vuelva a ejecutar nuestro programa:

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

Y vemos hacked impreso unas cuantas veces como se esperaba.

Esto confirma aún más que en realidad usamos el glibc que compilamos y no el host.

Probado en Ubuntu 18.04.

Configuración 2: crosstool-NG configuración prístina

Esto es un alternativa a la configuración 1, y es la configuración más correcta que he logrado hasta ahora: todo es correcto hasta donde puedo observar, incluidos los objetos de tiempo de ejecución de C, como crt1.o, crti.o, y crtn.o.

En esta configuración, compilaremos una cadena de herramientas GCC dedicada que use el glibc que queremos.

El único inconveniente de este método es que la compilación tomará más tiempo. Pero no arriesgaría una instalación de producción con nada menos.

Crosstool-NG es un conjunto de scripts que descargan y compilan todo desde source para nosotros, incluyendo GCC, glibc y binutils.

Sí, el sistema de compilación de GCC es tan malo que necesitamos un proyecto separado para eso.

Esta configuración no es perfecta porque crosstool-NG no soporta la construcción de ejecutables sin banderas adicionales -Wl , lo que se siente raro ya que hemos construido GCC. Pero todo parece funcionar, así que esto es solo un inconveniente.

Obtenga crosstool-NG y configure 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

La única opción obligatoria que puedo ver, es hacer que coincida con la versión del kernel de su host para usar las cabeceras del kernel correctas. Encuentre la versión del núcleo del host con:

uname -a

Que me muestra: {[64]]}

4.15.0-34-generic

Así que en menuconfig lo hago:

  • Operating System
    • Version of linux

Así que selecciono:

4.14.71

Que es la primera versión igual o anterior. Tiene que ser más antiguo ya que el núcleo está al revés compatible.

Ahora puedes construir con:

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

Y ahora esperar unos treinta minutos a dos horas para la compilación.

Configuración 2: configuraciones opcionales

El .config que generamos con ./ct-ng x86_64-unknown-linux-gnu tiene:

CT_GLIBC_V_2_27=y

Para cambiar eso, en menuconfig hacer:

  • C-library
  • Version of glibc

Guarda el .config, y continúa con la construcción.

O, si desea utilizar su propia fuente glibc, por ejemplo, para utilizar glibc desde el latest git, proceed like this :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: establecer a verdadero
  • C-library
    • Source of glibc
      • Custom location: di que sí
      • Custom location
        • Custom source location: apunta a un directorio que contiene tu fuente glibc

Donde glibc fue clonado como:

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

Configuración 2: probarlo

Una vez que haya construido la cadena de herramientas que usted quiero, probarlo con:

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

Todo parece funcionar como en Setup 1, excepto que ahora se usaron los objetos de tiempo de ejecución correctos:

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

Configuración 2: intento fallido de recompilación eficiente de glibc

No parece posible con crosstool-NG, como se explica a continuación.

Si usted acaba de volver a construir;

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

Luego se tienen en cuenta los cambios en la ubicación de origen glibc personalizada, pero se construye todo desde cero, lo que lo hace inutilizable para iterativos desarrollo.

Si lo hacemos:{[64]]}

./ct-ng list-steps

Da una buena visión general de los pasos de compilación:

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.

Por lo tanto, vemos que hay pasos glibc entrelazados con varios pasos GCC, más notablemente libc_start_files viene antes de cc_core_pass_2, que es probablemente el paso más caro junto con cc_core_pass_1.

Para construir solo un paso, primero debe configurar la opción" Guardar pasos intermedios " en .config para el inicio construcción:

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

Y luego puedes intentar: {[64]]}

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

Pero desafortunadamente, el + requerido como se menciona en: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Sin embargo, tenga en cuenta que reiniciar en un paso intermedio restablece el directorio de instalación al estado que tenía durante ese paso. Es decir, usted tendrá un libc reconstruido - pero no hay compilador final construido con este libc (y por lo tanto, no hay bibliotecas de compiladores como libstdc++ tampoco).

Y básicamente todavía hace que la reconstrucción sea demasiado lenta para ser factible para el desarrollo, y no veo cómo superar esto sin parchear crosstool-NG.

Además, a partir del paso libc no parecía copiar la fuente de nuevo desde Custom source location, haciendo aún más este método inutilizable.

Bonus: stdlibc++

Un bono si también eres interesado en la biblioteca estándar de C++: ¿Cómo editar y reconstruir el código fuente de la biblioteca estándar de C++ libstdc++ de GCC?

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-30 17:00:24

Cuando quise ejecutar un navegador chromium en Ubuntu precise (glibc-2.15), obtuve el (típico) mensaje "lib libc. so. 6: version' GLIBC_2. 19 ' no encontrado...". Consideré el hecho, que los archivos no son necesarios permamently, pero solamente para el comienzo. Así que recopilé los archivos necesarios para el navegador y sudo y creé un mini-glibc-2.19- entorno, inició el navegador y luego copió los archivos originales nuevo. Los archivos necesarios están en RAM y el glibc original es el mismo.

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)

El script para ejecutar el navegador:

#!/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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-29 23:16:37