How to get dependencies list for .so file? - android

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.

Related

Compiling native_app_glue.c results in an invalid library file

I'm cross-compiling a C++ library to Android. I'm using CMake as my build generator and I'm using the toolchain file provided in the NDK (called android.toolchain.cmake). Note, I'm on Windows.
I'd like to compile the android_native_app_glue.c source - also provided by the NDK - to a static library so I can later link it to my final application. After having an error, that said I'm missing the symbol ANativeActivity_onCreate, I've started investigating. ANativeActivity_onCreate is a function defined in android_native_app_glue.c, so I've looked at the compiled library using nm -o libnative_glue.a and it was quite surprising to see this:
libnative_glue.a:android_native_app_glue.c.o:0000000000000000 T ANativeActivity_onCreate
libnative_glue.a:android_native_app_glue.c.o:0000000000000000 t android_app_create
libnative_glue.a:android_native_app_glue.c.o:0000000000000000 t android_app_destroy
libnative_glue.a:android_native_app_glue.c.o:0000000000000000 t android_app_entry
libnative_glue.a:android_native_app_glue.c.o:0000000000000000 t android_app_free
...
Basically my functions are "there", but are zero-sized. I'm assuming they are thrown away at the next link, since they are not valid - looking at the next artifact with nm confirmed that.
The CMake snippet to compile the library is fairly trivial, but I'll provide it for completeness's sake:
add_library(native_glue STATIC "${CMAKE_ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c")
I have two pre-defined cache-entries for CMake, ANDROID_ABI=arm64-v8a and ANDROID_PLATFORM=24.
What could cause this invalid library compilation?
Building a NativeActivity is usually done via libnative_app_glue.a, see https://developer.android.com/ndk/samples/sample_na.
Unfortunately, the instructions there have never been updated for CMake, so it could be easier to add the android_native_app_glue.c file to your shared lib.
The linker attempts to prune any unused symbols that come from non-whole static libraries, and ANativeActivity is not used directory but rather is intended for re-export.
You can either link libnative_app_glue as a whole archive, or use -u to prevent the symbol from being dropped.
With -u:
target_link_libraries(mylib -u ANativeActivity_onCreate native_app_glue)
With whole archives:
target_link_libraries(mylib -Wl,--whole-archive native_app_glue -Wl,--no-whole-archive)
I haven't actually tested either of these with CMake. The ndk-build equivalents are known to work though.
You might also be able to use an object library, which is the CMake flavor of whole archives.

How to determine which dependency causes Google Play OpenSSL warning?

I'm currently working on a big legacy project and trying to fix the OpenSSL vulnerability issue as explained at How to address OpenSSL vulnerabilities in your apps.
The problem is, there are lot of dependencies, some are open source (I updated all that didn't break the compatibility) added as Gradle import, some are custom/closed source provided by partners and contractors of the company I work for and attached to the project as JARs.
Is there any way to pinpoint specific library that has this vulnerability? I used the bash script provided at Google Play and OpenSSL warning message and it points to one native dependency (actually the .so file). Is there any option to pinpoint actual dependency from there?
Is there any option to pinpoint actual dependency from there?
Yes, but you need to know the offending OpenSSL version and you need grep. Windows find won't do.
First, take note of the offending OpenSSL version. For sake of argument, say its due to OpenSSL 1.0.1h.
Next, gather a list of your dependencies and their top level folders. For sake of argument, say its $HOME/Desktop/aosp-app, $HOME/sdk-a, /usr/local/sdk-b and /opt/local/sdk-c.
Finally, for the top level directories:
grep -R '1.0.1h' "$HOME/Desktop/aosp-app"
grep -R '1.0.1h' "$HOME/sdk-a"
grep -R '1.0.1h' /usr/local/sdk-b
grep -R '1.0.1h' /opt/local/sdk-c
You don't need grep -iR, which is a case insensitive (-i) recursive (-R) search. You also don't need grep -IR, which is a recursive (-R) search that skips binary files (-I).
All of this works because OpenSSL library embeds its version in the data section as a string. Eventually, you will hit on the culprit, which is probably an SDK that comes pre-built as a shared object but includes OpenSSL as a static library. One SDK seems to be identified frequently, and it uses cURL which is built against a static OpenSSL library.
If you have JAR files and suspect them, then you can perform the following as a quick test:
find <dir> -name '*.jar' -exec grep -R '1.0.1h' {} \;
The command will look in the directory <dir> and its subdirectories. It will search for files with the *.jar extension. When it finds one, it will run grep on it looking for the string. find will do it for every *.jar it finds.

Using OpenCv contrib modules for android

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.

Checking for missing shared libraries (.so) from another shared library

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.

Setting up an Android build environment for JNI applications

I've got a hold of a proprietary JNI application which I need to build for a MIPS device. I've read "Initializing a Build Environment", parts of the NDK docs, some Google Groups threads and numerous StackOverflow questions, but I'm still short of my answer.
So far, I've checked out the Android source using Google's repo script and have it under ~/AndroidSource. I've also separately downloaded the SDK under ~/AndroidSDK and the NDK under ~/AndroidNDK. The code I'm trying to build is in a separate location. The SDK and NDK binaries are in my path. For building, I tried to use two different versions of the NDK as well as the one under the Android source tree, and experienced different sets of problems. My current setup uses NDK r8b, downloaded separately from the Android source.
The application has its Android.mk and jni/Android.mk. However, several directives in the latter point to paths such as
frameworks/base/include
system/core/include
with no prefixes. I thought these were meant to point to the respective directories in the Android source, so I symlinked them to the current directory. After some more symlinking and makefile and source hacking, I got the application to compile, but am currently stuck on the linking phase with lots of references to missing method bodies. During the whole time I knew I was doing something wrong.
I'm on a Linux x86_64 host, if it is of any concern.
So my question is:
What is the proper method to set up a build environment for JNI applications? What environment variables, symlinks and/or path expansions should I set up? Do I need to call any scripts once or before each ndk-build invocation?
Also, I'd be happy if you corrected me on any concepts or terminology I've gotten wrong.
Your approach wiyh symlinking the AOSP tree for system headers is correct. What you need now are the system libraries compiled for MIPS. The easiest way to get them is to adb pull them from a target device (or emulator image). But you can also build these libraries yourself, as part of the AOSP build (see build instructions for the source tree you downloaded).
If you still have any problems remaining, run your ndk-build with parameter V=1 and publish the link command and its results.
I use the following in my build (YMMV).
Explicitly invoke arm-linux-androideabi-gcc as your compiler or linker (should be in PATH).
NDK_PLATFORM=/path/to/android-ndk-r*/platforms/android-14
Pass -I"$(NDK_PLATFORM)/arch-arm/usr/include" to the compiler
Pass -nostdlib -L"$(NDK_PLATFORM)/arch-arm/usr/lib/" -lgcc -lc -lm to the linker

Categories

Resources