2012-07-15 4 views
6

Sto cercando di caricare due librerie condivise nella mia applicazione Android attraverso la chiamata loadLibrary:Collegamento con libreria condivisa con versione in Android NDK

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

Continuo a correre di prendere il `UnsatisfiedLinkError. Ecco una versione più dettagliata dell'errore.

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) 

Qualche idea?

Dopo aver trascorso un po 'di tempo, ho scoperto che Android non supporta le librerie con versione. Qualcuno ha affrontato lo stesso problema?

risposta

2

Sembra che Android abbia un problema con il caricamento delle librerie con versione. Il problema in questione era dovuto alla libreria so-name nel mio caso libcrypto.so.1.0.0. Anche se si rinomina la libreria e si prova a caricarla come libreria condivisa precompilata in un file make di Android, fallisce. (Deve essere perché il nome della libreria è in qualche modo incorporato nel file. E qualsiasi libreria che si collega con essa si aspetta di essere collegato con una libreria con lo stesso nome)

Spero che ci siano altri modi per gestire le librerie con i nomi delle versioni in Android.

Per ora sto evadendo il problema tutti insieme utilizzando librerie statiche di openssl e collegandole con la mia libreria condivisa.

2

Anno 2014 e ancora nessun supporto per le librerie condivise con versione. Così ho creato uno script per applicare la patch a SONAME. Basta puntare lo script alla directory di input dove sono posizionate tutte le librerie con versione. Quindi controlla l'output dir "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

non ha funzionato per me ... mi sono imbattuto su dir fonte OpenSSL, con i binari compilati e 'unver' uscita dir è exactaly lo stesso del binario originale libcrypto.so – Giovani

+0

È possibile rimuovere il commento #echo nello script e vedi dove qualcosa va storto. – sviborg

+0

Oppure utilizzare [patchelf] (https://www.mankier.com/1/patchelf) per risolvere il problema. –

4

Ho avuto lo stesso problema sulla creazione di libwebsockets per Android, che deve essere collegato a OpenSSL. Io uso libssl.so come esempio. Si dovrebbe fare lo stesso per i file .so correlati.

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".

Le opere hack. Ho un'applicazione Android per dimostrarlo. Vedi il mio rant a http://computervisionandjava.blogspot.com/2015/05/trouble-with-versioned-shared-libraries.html.

+0

Non sono riuscito a ottenere rpl per lavorare con i file .so, ma sono stato in grado di modificare il file con VIM e sostituire la stringa lì. Grande hack. Grazie! – Xample