¿Cómo puedo saber con seguridad qué biblioteca de userland C utiliza mi sistema? Las posibles razones para necesitar esta información incluyen:
Hay un paquete fuente gigantesco que estoy considerando descargar, que estoy seguro hará las comprobaciones adecuadas y enumerará una versión de biblioteca mínima, pero prefiero ahorrarme una molestia potencial comprobando primero si funcionará.
Me preocupa la compatibilidad de ABI con algunos binarios de terceros que quiero probar e instalar fuera del sistema de administración de paquetes del sistema.
Tengo un paquete fuente cuya documentación menciona la necesidad de una versión mínima de la biblioteca de mi sistema, pero el proceso de compilación no realiza ninguna comprobación.
Estoy creando un compilador cruzado dirigido a un sistema específico y no quiero arriesgarme a problemas de compatibilidad .
fuente
ldd
. No estoy seguro de siotool --version
se puede considerar que proporciona la misma información.Respuestas:
Los sistemas GNU / Linux generalmente usan glibc (familia Fedora / Redhat, Arch) o su primo cercano, eglibc (familia Debian / Ubuntu); dado que eglibc ahora se está fusionando de nuevo en glibc ( ver EGLIBC 2.19 Rama creada en "Noticias" ), en un futuro cercano todos volverán a ser glibc.
La forma más fácil de verificar la versión exacta es preguntar
ldd
, que se envía con la biblioteca C.En Fedora 20:
Eso es glibc 2.18.
En Raspbian (puerto Debian 7 para ARMv6 Broadcom SoC):
Eso es eglibc 2.13.
Si por alguna razón ha mezclado y emparejado algunas partes o no está seguro
ldd
, puede consultar la biblioteca C directamente.Ninguno de ellos es ejecutable, pero proporcionan una pista sobre dónde encontrar uno.
Sin embargo, no es necesariamente tan fácil, porque la biblioteca C no tiene que residir en algún lugar donde
whereis
pueda encontrarlo.Lamentablemente, la página del manual no proporciona un número de versión.
ldd
sigue siendo útil, ya que cualquier ejecutable funcional y vinculado dinámicamente en el sistema (p. ej., casi todo lo que hay en/usr/bin
) se vinculará a la biblioteca C.libc.so.6
Está en la tercera línea.fuente
/lib/`uname -m`*
ruta. Así manera portátil sería:find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version
. Gracias por una buena explicación.Un sistema no está realmente limitado a una biblioteca C. Sin embargo, la mayoría usa principalmente uno, que también será el que usa el compilador predeterminado. Y como está descargando el código fuente para compilar, ese es el que le preocupa.
Comience con un programa trivial:
compílelo usando el compilador que usará para el código fuente, luego use
ldd
para averiguar dónde está la biblioteca C:Ahora tiene el camino a la biblioteca C. Puede buscar esto en su administrador de paquetes para encontrar el paquete (por ejemplo,
dpkg -S /lib/x86_64-linux-gnu/libc.so.6
orpm -q -f /lib/x86_64-linux-gnu/libc.so.6
).Al menos en el caso de eglibc / glibc, puede ejecutarlo:
Finalmente, puede ver si puede obtener pistas
objdump -p /lib/x86_64-linux-gnu/libc.so.6
, mirando en la sección de definiciones de versión :Observe cómo el símbolo GLIBC_2.18 tiene el número de versión más reciente entre los símbolos enumerados, y la versión de la biblioteca es de hecho 2.18. Sin embargo, es eglibc (tiene como objetivo ser compatible con binarios con glibc 2.18, por lo que utiliza las mismas versiones de símbolos).
También podría intentar usar
strings
para descubrir algo al respecto. Deberá especificar una longitud mínima más larga (-n
), o usar grep para buscar algo:ambos trabajan para este eglibc.
NOTA: La utilidad del paquete Debian se
dpkg-shlibdeps
utilizaobjdump
debajo del capó, junto con la información de símbolos almacenados en los paquetes de la biblioteca Debian para determinar las versiones mínimas de dependencias requeridas por los paquetes binarios Debian en el momento de la compilación. Básicamente, analiza los símbolos exportados por el paquete binario de Debian y luego encuentra las versiones mínimas de las bibliotecas que contienen esos símbolos.fuente
La respuesta obvia, aunque no es la más completa, es verificar su administrador de paquetes, por ej.
(Lamentablemente, glibc no tiene un
.pc
archivo pkconfig , porpkgconfig --modversion glibc
lo que no es un corredor). Consulte también la excelentegetconf
sugerencia de @Gnouc .El caso más simple, con gcc + glibc, y el que mayormente uso primero es simplemente ejecutar
libc.so
, como se describe en algunas de las otras respuestas aquí. No es necesario pasar ningún argumento, genera su versión por defecto. Esto funciona hasta glibc-2.1 (glibc-2.0 seg-faults, aunque en ese entonces podría verificar elglibcbug
script (ahora retirado) para confirmar la versión). Este método también funciona con versiones recientes (> 0.9.15) de musl-libc (que acaba de ser 1.0 hoy, 20 de marzo). No funciona con uClibc, se daña por defecto.Una manera simple de saber exactamente qué
gcc
va a hacer es compilar:(con glibc, que
<stdio.h>
incluye<features.h>
las macros GLIBC relevantes que necesita<gnu/libc-version.h>
para las declaraciones de funciones).Esto detecta casos más complejos (múltiples libc y / o múltiples compiladores), suponiendo que esté utilizando el compilador (y las banderas) correctos, por supuesto. (Sin embargo, sospecho que no distinguirá entre eglibc y glibc propiamente dicho).
Si está seguro de que está usando glibc (o eglibc)(lo siento, esto no es correcto).ld
, también confirmará la versiónSi
__GNU_LIBRARY__
no está definido, obtendrá errores, entonces es hora del plan B.gcc -dumpmachine
puede ayudar, por ejemplo, para uclibc tiene un-uclibc
sufijo, como puedegcc -dumpspecs | grep dynamic-linker
. Esto también puede implicar el ABI.gcc -print-file-name=libc.so
le dirá qué archivo utilizará el compilador para "-lc
", es casi seguro que es un script vinculador dentro de su instalación de gcc, que puede leer como texto sin formato. Eso mostrará la ruta exacta alibc.so
. Esto también funcionará si está pasando banderas como-m32
o-m64
.En el caso de que esté usando uclibc (como lo usa OpenWRT y más), define
__UCLIBC_MAJOR__
,__UCLIBC_MINOR__
y__UCLIBC_SUBLEVEL__
también__UCLIBC__
en<features.h>
, por lo que se detecta fácilmente usando una variación menor en el fragmento de código C anterior. En aras de la compatibilidad, uClibc también puede definir las macros GNU / GLIBC como se usa anteriormente, actualmente pretende ser glibc-2.2. Actualmente no implementa lasgnu_get_libc_X()
funciones, pero sí implementa logetconf
que también puede inducir a error (sospecho que devuelve una respuesta vacía paragetconf GNU_LIBC_VERSION
, mi entorno de compilación está de mal humor hoy, así que no puedo confirmar).En el improbable caso de que esté usando dietlibc , la ejecución
diet -v
mostrará la versión.(FWIW, durante varios años con el software que usa autoconf, he tenido más problemas con las funciones
gcc
yg++
requisitos no verificados que con las funciones glibc verificadas).fuente
GNU libc (lo que la mayoría de las distribuciones de Linux usan de una forma u otra) hace todo lo posible para mantener una estricta compatibilidad con versiones anteriores. Por lo tanto, debe tener problemas solo si intenta ejecutar un binario demasiado nuevo en una versión anterior (o una distribución "empresarial", normalmente congelan las versiones, particularmente las básicas como la biblioteca C, las correcciones de backport manteniendo la rigurosa compatibilidad binaria) . Creo que es mucho más probable que tenga problemas con otras bibliotecas (C ++ tuvo algunos cambios API / ABI en la memoria reciente, algunas otras bibliotecas simplemente no se preocupan por la compatibilidad con versiones anteriores).
Lamentablemente, la única forma de averiguarlo con certeza es intentarlo.
fuente
(Esto es esencialmente lo mismo que la respuesta de Ricitos de Oro pero con algo más de explicación de lo que sucede debajo del capó).
La biblioteca compartida principal para GNU libc,
libc.so.6
(en Linux; Hurd tiene un SONAME diferente), tiene la propiedad inusual (para bibliotecas compartidas) de que puede invocarla como un ejecutable. Si lo hace, imprime el tipo de cosas que las utilidades de GNU generalmente imprimen cuando se ejecutan--version
, de esta manera:Pero, por supuesto, el directorio donde
libc.so.6
vive no está$PATH
, así que debes saber dónde buscarlo. Podría ser en/lib
,/lib64
,/usr/lib
, o algo aún más loca (como en este caso). Convenientemente,ldd
te diré:Para que eso funcione, por supuesto, debe conocer el nombre de ruta completo de un ejecutable binario vinculado dinámicamente. Se
sh
garantiza que el ejecutable esté en/bin
(porque muchos#!
scripts esperan que lo esté), y no puede ser un#!
script en sí mismo . Se podría estar vinculado estáticamente, pero no he encontrado un sistema que hizo que en muchos años.No sé qué haces si estás corriendo con uClibc o musl o algo más exótico.
fuente
$ ldd $(which sh) | grep libc
. : DOtra forma de obtenerlo:
fuente