tagger tag picard musicbrainz mp3tag kid3 full editar easytag linux linker libc

linux - tag - Vinculación con una versión anterior de libc para proporcionar una mayor cobertura de aplicaciones



music tagger (4)

Desafortunadamente, la solución de @ Sam no funciona bien en mi situación. Pero de acuerdo con su manera, encontré mi propia manera de resolver eso.

Esta es mi situación:

Estoy escribiendo un programa C ++ utilizando el marco Thrift (es un middleware RPC). Prefiero el enlace estático al enlace dinámico, por lo que mi programa está vinculado a libthrift.a estáticamente en lugar de libthrift.so . Sin embargo, libthrift.a está vinculado dinámicamente a glibc, y como mi libthrift.a está construido en mi sistema con glibc 2.15, mi libthrift.a usa memcpy de la versión 2.14 ( memcpy@GLIBC_2.14 ) provisto por glibc 2.15.

Pero el problema es que nuestras máquinas servidor solo tienen la versión glibc 2.5 que solo tiene memcpy@GLIBC_2.2.5 . Es mucho más bajo que memcpy@GLIBC_2.14 . Entonces, por supuesto, mi programa de servidor no puede ejecutarse en esas máquinas.

Y encontré esta solificación:

  1. Usando .symver para obtener la referencia a memcpy@GLIBC_2.2.5 .

  2. Escriba mi propia función __wrap_memcpy que simplemente llama a memcpy@GLIBC_2.2.5 directamente.

  3. Al vincular mi programa, agregue -Wl, - wrap = opción memcpy a gcc / g ++.

El código involucrado en los pasos 1 y 2 está aquí: https://gist.github.com/nicky-zs/7541169

Los binarios de Linux suelen estar vinculados dinámicamente a la biblioteca del sistema principal (libc). Esto mantiene la huella de memoria del binario bastante pequeña, pero los binarios que dependen de las últimas bibliotecas no se ejecutarán en sistemas más antiguos. Por el contrario, los binarios vinculados a bibliotecas antiguas se ejecutarán felizmente en los últimos sistemas.

Por lo tanto, para asegurarnos de que nuestra aplicación tenga una buena cobertura durante la distribución, debemos determinar la biblioteca más antigua que podemos admitir y vincular nuestro archivo binario con esa.

¿Cómo deberíamos determinar la versión más antigua de libc a la que podemos vincular?


Determine qué símbolos del ejecutable crean la dependencia de la versión no deseada de glibc.

$ objdump -p myprog ... Version References: required from libc.so.6: 0x09691972 0x00 05 GLIBC_2.3 0x09691a75 0x00 03 GLIBC_2.2.5 $ objdump -T myprog | fgrep GLIBC_2.3 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.3 realpath

Mire dentro de la biblioteca dependiente para ver si hay símbolos en versiones anteriores con las que pueda vincular:

$ objdump -T /lib/libc.so.6 | grep -w realpath 0000000000105d90 g DF .text 0000000000000021 (GLIBC_2.2.5) realpath 000000000003e7b0 g DF .text 00000000000004bf GLIBC_2.3 realpath

Estamos de enhorabuena!

Solicite la versión de GLIBC_2.2.5 en su código:

#include <limits.h> #include <stdlib.h> __asm__(".symver realpath,realpath@GLIBC_2.2.5"); int main () { realpath ("foo", "bar"); }

Observe que GLIBC_2.3 ya no es necesario:

$ objdump -p myprog ... Version References: required from libc.so.6: 0x09691a75 0x00 02 GLIBC_2.2.5 $ objdump -T myprog | grep realpath 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 realpath

Para obtener más información, consulte http://www.trevorpounds.com/blog/?p=103 .


Para hacer esto de una manera más automatizada, puede usar la siguiente secuencia de comandos para crear una lista de todos los símbolos que son más nuevos en su GLIBC que en una versión dada (configurada en la línea 2). Crea un archivo glibc.h (nombre de archivo establecido por el argumento script) que contiene todas las declaraciones .symver necesarias. A continuación, puede agregar -include glibc.h a su CFLAGS para asegurarse de que se recoja en todas partes de su compilación.

Esto es suficiente si no utiliza ninguna biblioteca estática que se haya compilado sin incluir lo anterior. Si lo hace, y no desea volver a compilar, puede usar objcopy para crear una copia de la biblioteca con los símbolos renombrados a las versiones anteriores. La segunda línea de la secuencia de comandos crea una versión de su sistema libstdc++.a que se vinculará con los viejos símbolos glibc. Añadiendo -L. (o -Lpath/to/libstdc++.a/ ) hará que su programa enlace estáticamente libstdc ++ sin vincular un montón de nuevos símbolos. Si no necesita esto, elimine las dos últimas líneas y la línea printf ... redeff .

#!/bin/bash maxver=2.9 headerf=${1:-glibc.h} set -e for lib in libc.so.6 libm.so.6 libpthread.so.0 libdl.so.2 libresolv.so.2 librt.so.1; do objdump -T /usr/lib/$lib done | awk -v maxver=${maxver} -vheaderf=${headerf} -vredeff=${headerf}.redef -f <(cat <<''EOF'' BEGIN { split(maxver, ver, //./) limit_ver = ver[1] * 10000 + ver[2]*100 + ver[3] } /GLIBC_/ { gsub(//(|/)/, "",$(NF-1)) split($(NF-1), ver, /GLIBC_|/./) vers = ver[2] * 10000 + ver[3]*100 + ver[4] if (vers > 0) { if (symvertext[$(NF)] != $(NF-1)) count[$(NF)]++ if (vers <= limit_ver && vers > symvers[$(NF)]) { symvers[$(NF)] = vers symvertext[$(NF)] = $(NF-1) } } } END { for (s in symvers) { if (count[s] > 1) { printf("__asm__(/".symver %s,%s@%s/");/n", s, s, symvertext[s]) > headerf printf("%s %s@%s/n", s, s, symvertext[s]) > redeff } } } EOF ) sort ${headerf} -o ${headerf} objcopy --redefine-syms=${headerf}.redef /usr/lib/libstdc++.a libstdc++.a rm ${headerf}.redef


glibc 2.2 es una versión mínima bastante común. Sin embargo, encontrar una plataforma de compilación para esa versión puede no ser trivial.

Probablemente, una mejor dirección es pensar en el sistema operativo más antiguo que desea admitir y aprovecharlo.