2012-07-15 15 views
6

estoy tratando de cargar dos bibliotecas compartidas en mi aplicación Android a través de la llamada loadLibrary:Vinculación con biblioteca compartida versionado en Android NDK

System.loadLibrary("mywrapper"); 
System.loadLibrary("crypto"); 

Sigo corriendo para controlar el `UnsatisfiedLinkError. Aquí hay una versión más detallada del error.

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1969]: 
    130 could not load needed library 'libcrypto.so.1.0.0' for 
    'libmywrapper.so' (load_library[1111]: Library 'libcrypto.so.1.0.0' not found) 

¿Alguna idea?

Después de pasar un tiempo descubrí que Android no es compatible con las bibliotecas versionadas. ¿Alguien ha enfrentado el mismo problema?

Respuesta

2

Parece que Android tiene un problema con la carga de librerías versionadas. El problema en cuestión se debía a la existencia de la biblioteca, en mi caso, libcrypto.so.1.0.0. Incluso si cambia el nombre de la biblioteca e intenta cargarla como una biblioteca compartida precompilada en un archivo make de Android, falla (tiene que ser porque el nombre de la biblioteca está de alguna manera incrustado en el archivo. Y cualquier biblioteca que lo vincule con ella espera ser vinculado con una biblioteca con el mismo nombre)

Espero que haya otras formas en lo que respecta a la gestión de bibliotecas con nombres de versión en Android.

Por el momento estoy eludiendo el problema, usando bibliotecas estáticas de openssl y vinculándolas con mi propia biblioteca compartida.

2

Año 2014 y aún no es compatible con versiones compartidas libs. Así que hice un script para parchar SONAME. Simplemente apunte el script al directorio de entrada donde colocaron todas las libs versionadas. Luego verifique el directorio de salida "unver".

#!/bin/bash 

DIR="$1" 

if [ "$DIR" == "" ]; then 
    echo "Usage: fix-soname.sh <target dir>" 
    exit 
fi 

if [ ! -d $DIR ]; then 
    echo "Not found: $DIR" 
    exit 
fi 

OUT="$DIR/unver" 
echo "Input=$DIR" 
echo "Output=$OUT" 

CWD=$(pwd) 
cd $DIR 

# prep dirs 
mkdir -p $OUT 
rm -f -R $OUT/* 

# rename libs and copy to out dir 
find "$DIR" -type f -name '*.so*' | while read FILE; do 

    NAME=$(basename "$FILE") 
    SONAME=$NAME 

    while read SYMLINK; do 
     X=$(basename "$SYMLINK") 
     #echo "$X (${#X}) -> $NAME (${#NAME})" 
     if [ "${#X}" -lt "${#SONAME}" ]; then 
      SONAME=$X 
     fi 
done<<EOT 
`find -L $DIR -samefile $FILE` 
EOT 

    #echo $SONAME 
    cp -f $SONAME $OUT/ 
done 

# patch libs in out dir 
find "$OUT" -type f -name '*.so*' | while read FILE; do 

    # get file name without path 
    NAME=$(basename "$FILE") 

    # extract SONAME from shared lib 
    SONAME=`readelf -d $FILE | grep '(SONAME)' | grep -P '(?<=\[)(lib.*?)(?=\])' -o` 

    #echo "$NAME [$SONAME]" 

    # patch SONAME if required 
    if [ "$NAME" != "$SONAME" ]; then 
     L1=${#NAME} 
     L2=${#SONAME} 
     LDIFF=$((L2-L1)) 
     #echo "$NAME [$SONAME] ($LDIFF)" 

     if [ "$LDIFF" -gt "0" ]; then 
      SONEW=$NAME 
      for ((c=1; c<=$LDIFF; c++)); do 
       SONEW+="\x00" 
      done 
      echo "$NAME [$SONAME] -> $SONEW ($LDIFF)" 
      rpl -R -e "$SONAME" "$SONEW" $OUT 
     fi 
    fi 
done 

cd $CWD 
+0

no funcionó para mí ... lo ejecuté en el directorio de origen de openssl, con los binarios compilados y la salida del directorio 'unver' es exactamente la misma que la del original binario libcrypto.so – Giovani

+0

Puede descomentar #echo en script y ver dónde algo va mal. – sviborg

+0

O use [patchelf] (https://www.mankier.com/1/patchelf) para solucionarlo. –

4

Tuve el mismo problema al construir libwebsockets para Android, que necesita vincularse con OpenSSL. Yo uso libssl.so como ejemplo. Debería hacer lo mismo con los archivos .so relacionados.

Before: 
 
[email protected]:~$ objdump -p libssl.so | grep so 
 
libssl.so:  file format elf32-little 
 
    NEEDED    libcrypto.so.1.0.0 
 
    NEEDED    libdl.so 
 
    NEEDED    libc.so 
 
    SONAME    libssl.so.1.0.0 
 

 
After 
 
[email protected]:~$ rpl -R -e .so.1.0.0 "_1_0_0.so" libssl.so 
 
Replacing ".so.1.0.0" with "_1_0_0.so" (case sensitive) (partial words matched) 
 
. 
 
A Total of 2 matches replaced in 1 file searched. 
 
[email protected]:~$ objdump -p libssl.so | grep so 
 
libssl.so:  file format elf32-little 
 
    NEEDED    libcrypto_1_0_0.so 
 
    NEEDED    libdl.so 
 
    NEEDED    libc.so 
 
    SONAME    libssl_1_0_0.so 
 

 
And don't forget to change file name "libssl.so" to "libssl_1_0_0.so".

Las obras de hackers. Tengo una aplicación de Android para probarlo. Vea mi despotricar al http://computervisionandjava.blogspot.com/2015/05/trouble-with-versioned-shared-libraries.html.

+0

No pude hacer que rpl trabaje con los archivos .so, pero pude editar el archivo con VIM y reemplazarlo allí. Gran truco. ¡Gracias! – Xample

Cuestiones relacionadas