views:

159

answers:

3

I have a similar problem to this question, but slightly different. I have compiled a .so library to use with JNI. Because it is large (15 MB), I am putting it on the SDCard instead of in the standard application place.

The file is called libSample.so and it's located at /data/library/libSample.so

I load it in a static initialization block:

try {
        File sdcard = Environment.getExternalStorageDirectory();
        File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample.so");
        Log.i("Library", "Does the library exist?" + libraryLoc.exists());

        System.load(libraryLoc.getAbsolutePath());
    }
    catch (UnsatisfiedLinkError e) {
        Log.e("Translator", e.getMessage());
        Log.e("Translator", e.toString());
    }

Here's the relevant logcat output:

09-02 16:42:58.882: DEBUG/dalvikvm(4185): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:42:58.892: DEBUG/dalvikvm(4185): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:42:58.892: DEBUG/dalvikvm(4185): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:42:58.892: INFO/Library(4185): Library exists: true
09-02 16:42:58.902: INFO/Library(4185): Library can be read: true
09-02 16:42:58.902: DEBUG/dalvikvm(4185): Trying to load lib /sdcard/library/libSample.so 0x434fb6f8
09-02 16:42:58.902: INFO/dalvikvm(4185): Unable to dlopen(/sdcard/library/libSample.so): Cannot find library
09-02 16:42:58.912: ERROR/Translator(4185): Library /sdcard/library/libSample.so not found
09-02 16:42:58.912: ERROR/Translator(4185): java.lang.UnsatisfiedLinkError: Library /sdcard/library/libSample.so not found

Any idea what's wrong?

I read the post about can android load dll's from sdcard in native mode which said that the sdcard cannot be used to load libraries, so I moved the .so into /data/data/com.example.hellojni/lib/libSample.so (the private app data storage location). No change:

09-02 16:53:18.332: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:53:18.342: DEBUG/dalvikvm(4515): Added shared lib /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:53:18.342: DEBUG/dalvikvm(4515): No JNI_OnLoad found in /data/data/com.example.hellojni/lib/libhello-jni.so 0x434fb6f8
09-02 16:53:18.352: INFO/Library(4515): Library exists: true
09-02 16:53:18.352: INFO/Library(4515): Library can be read: true
09-02 16:53:18.352: DEBUG/dalvikvm(4515): Trying to load lib /data/data/com.example.hellojni/lib/libSample.so 0x434fb6f8
09-02 16:53:18.482: INFO/dalvikvm(4515): Unable to dlopen(/data/data/com.example.hellojni/lib/libSample.so): Cannot find library
09-02 16:53:18.492: ERROR/Translator(4515): Library /data/data/com.example.hellojni/lib/libSample.so not found
09-02 16:53:18.492: ERROR/Translator(4515): java.lang.UnsatisfiedLinkError: Library /data/data/com.example.hellojni/lib/libSample.so not found

What I don't understand is that clearly the library exists, and the OS is trying to load it ... so what would make it fail?

Following the advice of one of the commentors, I tried attaching via strace to get more detailed error information. The log can be found as a github gist.

The error appears to be on lines 47-51:

mprotect(0x4235d000, 4096, PROT_READ)   = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbeb58080) = -1 ENOTTY (Not a typewriter)
write(1, "bionic/linker/linker.c:1243| ERROR:    34 unknown reloc type 3 @ 0x811a854c (2441)\n", 83) = 83
write(1, "bionic/linker/linker.c:1641| ERROR: failed to link /data/data/com.example.hellojni/lib/libSample.so\n", 100) = 100
munmap(0x81000000, 8839168)             = 0

Here's the readelf of the library:

arm-eabi-readelf -d libSample.so 

Dynamic section at offset 0x80b648 contains 17 entries:
  Tag        Type                         Name/Value
 0x00000019 (INIT_ARRAY)                 0x7ff234
 0x0000001b (INIT_ARRAYSZ)               76 (bytes)
 0x00000004 (HASH)                       0xd4
 0x00000005 (STRTAB)                     0x7f41c
 0x00000006 (SYMTAB)                     0x2650c
 0x0000000a (STRSZ)                      1197287 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000003 (PLTGOT)                     0x80c6f0
 0x00000002 (PLTRELSZ)                   76480 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x1ccb84
 0x00000011 (REL)                        0x1a3904
 0x00000012 (RELSZ)                      168576 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x00000016 (TEXTREL)                    0x0
 0x6ffffffa (RELCOUNT)                   2412
 0x00000000 (NULL)                       0x0
+1  A: 

I think it may be more likely that a library that your .so depends upon is not being found. But that is only if .so files can be loaded from an SDCard in the first place.

Mondain
As I mentioned towards the end, I placed it in the app local storage space as well and got same error.I've had problems with unresolved links before and got a much different error (or at least, more informative text)
I82Much
I hear you, JNI is always so much fun
Mondain
+1  A: 

Please try following guidelines I have provided for the problem you were refering to in the beginning of your question (I mean here). Good luck!

Maciej Pigulski
You gave me some more information (namely attaching via strace). Could you please read the updated information I gave about the strace log and see if you know anything about this? "unknown reloc type 3"
I82Much
I havent seen this kind of error in my libraries. After some digging I have found that this reloc type 3 is R_ARM_REL32 defined in elf.h. I have looked up about this in google and this conversation came out: http://groups.google.com/group/android-ndk/browse_thread/thread/db718cceaded89dc/a601f3ecdcf070a7?#a601f3ecdcf070a7 It mentions that R_ARM_REL32 is not a valid relocation in dynamic executables. I am not a C/C++ expert so I can't help you with the exact explenation, but maybe this will tell you more then it tells me.
Maciej Pigulski
Maciej may be on to something. How about making a simpler library (a renamed copy of libhello-jni?) and trying to load it via the same method. Then try making cut down versions of your library.
Chris Stratton
+1  A: 

Ok, i never used Android before, so its may be a stupid comment, but in JavaSE it will not work too, because your library file is "wrong". See, you write a program in java, so you dont know in what SO it will run, right? How could you know if the lib you want to load is in file myLib.so or myLib.dll or myLib.32TestNotHackerSufix? Well... you dont! It's java! It will solve the sufix of the lib for you based on your SO.

Try use

  File libraryLoc = new File(sdcard.getAbsolutePath() + "/library/libSample");

without ".so".

(I suppose you dont have something like "LIBRARY_PATH" in Android, so it will load your lib from the path you tell him.... If such thing exists in Android you shoul load your lib like

System.load("libSampe"); 

and put your directory in LIBRARY_PATH before start your app)

Plínio Pantaleão
Thanks but that was not the problem. If the library is correctly built, and in libs/armeabi , it will be copied to the device and in a path that the android device knows about.
I82Much