I have a whole bunch of around 500 libraries each of them depending on one another(shared libraries)
The problem is one/few of them are failing to load due to a missing dependency library and I have no logs about which is failing due to what missing library. Due to the large number I cannot analyze it on y own with a hex editor. This scenario is from an android phone. So if I keep all of the .so libraries at one place, is there any way to write a script which analyzes each library for its dependencies and checks its existence in the given directory?
What approach should be followed to do this as AFAIK is possible to list shared libraries only of a dynamic executable using ldd.
I'm not entirely sure if I understood you correctly, but I hope my answer helps you anyway.
Normally any dynamic linked binary can be examined with "ldd". It basically shows you all libraries the dynamic linker had to load to in order to resolve all external symbols. This works on libraries, as well as on executables. If you use ldd's "-r" flag, ldd will try to resolve all external symbols, and it will report missing ones.
You can then easily feed the output of "ldd -r" to "grep" and check for missing symbols.
The bash script could then look like this:
find /lib /usr/lib /usr/local/lib -iname "*.so*" | while read lib_name; do
if ldd -r "$lib_name" 2>&1 | grep -qF "undefined symbol: "; then
echo "library \"$lib_name\" seems to be broken"
fi
done
I just wrote this out of my head, might contain minor synax/typing errors.
As I said earlier, this will also work on executables, in case you need it.
In case you need to extend your library search path, you can use the environment variable "LD_LIBRARY_PATH" for that. Just do:
export LD_LIBRARY_PATH=/path/to/my/libs
Since you specifically stated, that ldd will "only" work on dynamic libraries:
Well, a statically linked binary (lib or exe), has no dependencies on other binaries (except for the linux kernel). So I'm not sure what you are looking for in this case ... ?
ldd works for .so files as well
Try:
cd /usr/lib
ldd *
that will list all dynamic .so files used by the libraries, tries to resolv them, and show you anything that's missing.
Remove
<uses-library android:name="org.apache.commons.lang"/>
This is only for Android Project Libraries not a plain old Jar file. Jar files will have their classes extracted and put into your apk by just including them in the build path.
Related
Let's say i'm having libFoo.so compiled for android (arm). I'm not sure what STL implementation it was linked to (there are options). How can i get dependencies (as .so list) for it to understand what files i should provide and load using System.load(...)/loadLibrary(...)?
You can use the objdump tool and filter out the relevant part. In this case, e.g. arm-linux-androideabi-objdump -p libFoo.so | grep NEEDED.
The ldd tool as suggested normally also does this, but it tries to actually find all the files that would be loaded, and it is not always available in cross-compilation environments.
Is there a way to use opencv contrib modules in android ? I am specifically using text module. Is there a android lib for these modules. I have my code working on desktop and i m trying to migrate my codes to android. Any insight would be gr8.
I was having issues figuring out solutions to these problems as well. I thought I would find a relevant question out there and put a response in for the community in case others are also looking for solutions to a problem similar to this one and mine. Compilation was done on a Macbook Retina 13".
The instructions provided are somewhat incomplete and there are additional steps that will be needed to get to a final product.
At the start you will follow the standard procedure as outlined online
$ cd <opecv_directory>
$ mkdir build
$ cd <opencv_build_directory>
$ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules <opencv_source_directory>
$ make -j5
$ make install
In addition to this, you may run across an error or two. I needed to install some missing components in order to get past things that were missing but this may differ for you (I researched errors and understood that I needed additional components)
brew install ninja
brew install oxygen
brew install ant
I also ran into an error with one module requesting the need for the following declared in the source code (or with compiler flags):
#define SOLARIS_64BIT_ENABLED
Another thing you can do is remove other modules in the contrib folder you may not be interested in during compilation. Just include the modules you want and hopefully those ones are good. I did this simply by removing one or two from the /modules folder and then reran the python script.
A final python script was needed to run the build. I created a directory alongside the main source tree and contrib folder.
OpenCVSource
-> opencv
-> opencv_contrib
-> android_opencv_build
The call below was made from the directory where I want the build to be taking place from, so I changed to the directory The call was the following:
python ../opencv/platforms/android/build_sdk.py --extra_modules_path ../opencv_contrib/modules --ndk_path <your-path-to-ndk-top-level-folder> --sdk_path <your-path-to-sdk-top-level-folder> ./ ../opencv
This only builds the .so files that are necessary for using the library, but it doesn't build the .jar file that you will need to use the new binaries. In order to do that navigate to your build folder (mine as seen is in android_opencv_build/OpenCV-android-sdk)
Load this project into Eclipse in the standard manner with the import existing Android project into workspace. You really only need the /sdk project but feel free to load samples as well if desired. Then build the project. You may need to alter the target build to support the new Camera APIs for a successful build; in my case changing the target to API level 21.
You will then find the .jar file in the /bin directory of the project. The .jar and the .so files found in android_opencv_build/OpenCV-android-sdk/sdk/native/jni/ contain the necessary .so files that you will need to include in your projects /lib folder alongside this jar.
Now you should have everything that you need. Since we are working with contrib modules (or not if you are building it for other reasons), it is possible that you will run across other errors in the build process that are not quite stable and will need some attention. This cannot be helped but people can feel free to add comments to other peoples solutions and this post to aide them in resolving them if they have found a solution.
I have code I compiled already, and wonder if I can use the resulting executable, which is in elf format as a library in an APK and how please.
#Gabe Sechan; thanks. I did build a JNI project. I am having some issues importing the code from my other project into JNI. I wonder if you can suggest the best way to import it. I can post my Android.mk file if you like. Basically, it seems that project finds the first file, and an associated header file. That file, in turn uses variables, which are defined in another file. But there is no include statement.
You know? I figured if I can use a JAR file as a library, perhaps I could use an executable also. I need to learn more.
# Chris Straton - Thanks. I did edit my post with a comment to address the toolchain issue. But then, I modified it. Regardless, What I stated was if I use the toolchain that is recommended by my target platform, then I should be able to run it on my phone right?
Further; I re-read your comment about ABI and libc compatibility. The two devices are tegra t132 and Samsung S-N900P. So libc should not be an issue since both devices run Android; right? As far as I know both have an arm chip. Is there anything else I need to look into?
Elf is an executable, not a library. What you want to do is get a .so file and link to it via JNI.
You could possibly run it as a command line program and interact with it via its stdin and stdout, but that would be clunky when you can just use it as an actual library.
I want to make some changes to LatinIME. I got the code from git repository-
git clone https://android.googlesource.com/platform/packages/inputmethods/LatinIME
But I don't know how to build the apk file from the code. If anyone has build the LatinIME from the code, can you please share instructions.
Specifically I want to know how to build the dictionary tools (I guess I would need ndk), how to build the native code (again I guess it would required ndk) and finally how to build the java code by using the lib file from native code.
I tried creating Android app project in eclipse (using existing code option) by giving root directory as LatinIME/java I was able to compile but since it didn't have libjni_latinime.so, it crashed. I then got the .so file from emulator and put it in the libs/armeabi-v7a folder. Now I get this exception:
10-15 12:54:55.289: E/AndroidRuntime(32253): FATAL EXCEPTION: InitializeBinaryDictionary
10-15 12:54:55.289: E/AndroidRuntime(32253): android.content.res.Resources$NotFoundException: File res/raw/main_en.dict from drawable resource ID #0x7f070003
I think I may have solved this...
Having encountered a similar problem in another project where resources were being unnecessarily compressed due to their file extension I renamed the dictionaries (.dict) to .jet - an extension excluded from compression. Voila, dictionaries are now working. Not sure how good of a resolution that is seeing as the dictionaries are now uncompressed but it's a step in the right direction at least?
So far i have customised the LatinIME many times for different projects. I never faced this problem.
But i never used eclipse to create apks. I downloaded whole AOSP code onto my machine and compiled the modified source with AOSP. And mm creates the apk file in out folder, and can be installed with adb install -r latinime.apk
Here is how to download AOSP :http://source.android.com/source/downloading.html
And here is how to compile it initially : http://source.android.com/source/initializing.html and http://xda-university.com/as-a-developer/getting-started-building-android-from-source
And the LatinIME can be found in <android roo>/packages/inputmethods/LatinIME, Modify the code ther and cd to the same path and run mm (you need to do source build/envisetup.sh and lunch full-eng done in same terminal before doing mm)
First some background. As also suggested by the other answer issue seems to be related of .dict files being compressed. For example you can see how official Android builds solve this in project's tests for LatinIME
# Do not compress dictionary files to mmap dict data runtime
LOCAL_AAPT_FLAGS += -0 .dict
A quick searching the web reveals that to day this kind of directive or instructing aapt from Eclipse isn't trivial. You would probably end up creating a build.xml in case you want to handle don't-compress-dicts case properly.
One nice suggestion is this answer/question on how to instruct aapt to not to compress certain files.
If you want to build this from official git link you provide, you'll end up building whole Android repo, which you can by following building-running instructions.
If using gradle, add this
android {
aaptOptions {
noCompress 'dict'
}
I was able to follow directions in this question to build a shared lib of openssl for Android.
E.g.
cd openssl-fips-2.0/
./config
make
make install
And
cd openssl-1.0.1c/
./config fips --with-fipsdir=/usr/local/ssl/fips-2.0/ shared
make depend
make
This generates libcrypto.so.1.0.0 and libssl.so.1.0.0 with corresponding symbolic links to them as libcrypto.so and libssl.so.
Since the NDK build system doesn't support versioned shared libraries I had to use the symbolic links (with PREBUILT_SHARED_LIBRARY). However, with this, the libraries end up getting to the device as libcrypto.so and libssl.so instead of as libcrypto.so.1.0.0 and libssl.so.1.0.0 causing my library to fail to load as it is looking for the libraries with the version names.
The linked question mentions loading the libraries with System.load(libcrypto.so.1.0.0) instead of with System.loadLibrary() but I have not been able to get this to work even with full paths since as mentioned earlier, the file is copied to the device as libcrypto.so.
Anyone done this successfully?
Note: I've also tried modifying the openssl-1.0.1c config and makefiles to generate libcrypto.1.0.0.so (e.g. with the version number before the extension in the filename and soname) and this allowed me to get around the previous loading issue. However, with that I get an error when I try to turn on FIPS mode with FIPS_module_mode_set (FIPS_R_FINGERPRINT_DOES_NOT_MATCH).
I don't know yet why that is happening, but it could be due to NDK stripping of 'unneeded' stuff (see this question)... I'm still looking at this as well but if someone has some info on this as well it would be MUCH appreciated.
Let us identify the problem correctly. It's likely not the NDK build that causes problems, and definitely not the linker which strips away unused entries when it builds a shared lib from static lib.
First of all, I am not sure you can deliver FIPS mode in a usual APK, without rebuilding or at least rooting Android (see for example http://gcn.com/articles/2010/12/23/android-fips-security.aspx).
There is no problem for System.load() to load a versioned .so when you a) specify the full path correctly (e.g. System.load("/data/local/tmp/libssl.so.1.0.0")) and b) the file is delivered to that path. For the first tests, I would suggest to manually upload libcrypto.so.1.0.0 and libssl.so.1.0.0 to /sdcard/ and see if FIPS fingerprint becomes happier.
If the location on /sdcard/ causes any problem, you can try /data/local/ or /data/local/tmp/. You can also use /data/data/(your package)/files/. The latter has one advantage: it will be automatically deleted by the system when your app is uninstalled.
To make a versioned .so (like libcrypto.so.1.0.0) part of your APK, copy it to the assets folder of your project. It will be responsibility of your Java code to copy it from there to the designated location on disk. Make sure this Java code handles correctly upgrades and SD card swaps.