Me cuesta un poco avrdude
usardestellomi microcontrolador.
Depende delibm.so.6
GLIBC_2.29que no puede encontrar. Busca debajo /usr/lib/libm.so.6
dónde reside realmente este archivo, PERO también reside en /lib/lib.so.6
.
Así que mientras corría
sudo pacman -S glibc
para instalar/actualizar la bibliotecahttps://www.archlinux.org/packages/core/x86_64/glibc/
Estoy muy seguro de que lo instalé solo en /lib/
.
Pero como avrdude
lo estoy investigando, /usr/lib
todavía no lo encuentro. Me cuesta entender el sentido de estos dos directorios, ya que arruinan un poco las cosas y no ayudan en mi caso.
¿Cómo puedo hacerlo correctamente?
EDITAR
Quería hacer algo estúpido y lo hice, cp /lib/libm.so.6 /usr/lib/libm.o.6
pero el cp
comando me dice que los archivos son iguales.
Ahora no entiendo por qué avrdude
no puedo encontrar la versión correcta de GLIBC ya que está actualizada correctamente (hasta donde puedo ver).
Respuesta1
Tenga en cuenta que el archivo instalado
glibc
está incompleto.C runtime.
Para completarlo,C runtime
es posible que deba copiar encabezados adicionales que coincidan con el compilador que está utilizando, ya que el uso de--sysroot
restringirá su búsqueda al archivosysroot
.
Es muy posible tener varias versiones de glibc en el mismo sistema (lo hacemos todos los días).
Sin embargo, debe saber que glibc consta de muchas piezas (más de 200 bibliotecas compartidas) que 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 una vez finalizado el enlace.
Para crear 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 -rpath
opción del vinculador hará que el cargador en tiempo de ejecución busque bibliotecas /path/to/newglibc
(para que no tenga que configurarlas LD_LIBRARY_PATH
antes de ejecutarlo), y la -dynamic-linker
opción "preparará" la ruta para corregirla ld-linux.so.2
en la aplicación.
Si no puedes volver a vincular la myapp
aplicación (por ejemplo, porque es un binario de terceros), no todo está perdido, pero se vuelve más complicado. Una solución es crear un chroot
entorno adecuado para ello. Otra posibilidad es utilizarrtldiy uneditor binario.
SOLUCIÓN #1
LD_PRELOAD='mylibc.so anotherlib.so' program
Solución #2
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
proporcionados por glibc. Esto se menciona en:https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationEsos objetos realizan una configuración temprana en la que se basa glibc, por lo que no me sorprendería que las cosas fallaran de maneras maravillosas e increíblemente sutiles.
Para una configuración más confiable, consulte Configuración 2 a continuación.
Construya glibc
e instale 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
prueba_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);
}
Compile y ejecute 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 genera lo esperado:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Comando adaptado dehttps://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationpero --sysroot hizo que fallara con:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
así que lo eliminé.
La salida de ldd confirma que el ldd y las bibliotecas que acabamos de crear 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)
El resultado de depuración de la compilación de gcc muestra que se utilizaron los objetos de tiempo de ejecución de mi host, lo cual es malo como se mencionó anteriormente, pero no sé cómo solucionarlo, por ejemplo, contiene:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Configuración 1: modificar glibc
Ahora modifiquemos 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 vuelva a compilar y reinstalar glibc, y vuelva a compilar y ejecutar nuestro programa:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
y vemos impresos pirateados varias veces como se esperaba.
Esto confirma aún más que en realidad utilizamos el glibc que compilamos y no el host.
Probado en Ubuntu 18.04.
Fuentes:
https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229