I'm trying to debug my Android app (I'm using the libdash library through NDK) as a native application, and I'm having this error:
Error while mapping shared library sections:
`/usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/libjpeg.so': not in executable format: File format not recognized
warning: Could not load shared library symbols for 92 libraries, e.g. /system/bin/linker.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
warning: Unable to find dynamic linker breakpoint function.
GDB will retry eventurally. Meanwhile, it is likely
that GDB is unable to debug shared library initializers
or resolve pending breakpoints after dlopen().
this is the library that i'm trying to use
http://www.bitmovin.net/libdash/
http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/
Follow these directions. You need to take the library and put it somewhere special.
Your issue appears to be that you are cross compiling for Android, yet you haven't set your shared library lookup path. The result is that gdb is looking in your host system path to find the shared libraries instead.
Your host system is the system you run the build of your code on (your PC probably). Your target system is the system you're going to run the resulting "executable" on (some Android device). That's why it's called cross compiling. Since the two systems aren't the same, you need to make sure you're using a cross compiled version of gdb (one that knows your target and host types), which was probably provided with the Android SDK, and you also need to make sure you set the search path for the shared libraries.
You should check the general GDB documentation for details, but the method I prefer for setting my cross-compiled library paths is to set the solib-absolute-path. You can do that by running the following from within GDB:
(gdb) set solib-absolute-path <path to root directory all Android shared libraries are under>
This requires that you have the same directory structure as your Android file system with regard to library paths somewhere on your PC.
An alternate and more portable way of doing it is to set the solib-search-path so it will search the Android library locations within the SDK on your PC rather than your PC's default library search path, but for details on that you'll have to read the GDB documentation since I don't use it often enough to help much more.
Related
I build a native executable, that runs inference using gpu delegation. This executable relies on the libtensorflowlite_gpu_delegate.so that I copied to the same directory. However, when I run it, I got error saying that this shared lib is not found, so apparently, I need to set the RPATH to ./, and the executable is able to find this shared lib.
But then I ran into another error saying: "libOpenCL.so not found". I found this shared lib in /system/vendor/lib64, so I copied it to the same directory, and everything works.
However, I dont want to duplicate this shared lib if system already have it, so I add RPATH of /system/vendor/lib64 to my executable, and I confirmed with readelf:
Dynamic section at offset 0x9fc0058 contains 40 entries:
Tag Type Name/Value
0x000000000000001d (RUNPATH) Library runpath: [/system/vendor/lib64/:./]
However, with this new RPATH, I still get error saying "libOpenCL.so not found". Not sure if that is access constrain, but I am under adb shell with su enabled. and that file has accesibility of -rw-r--r--
My question is:
why setting RPATH here does not work?
I feel this may not be the best way to let my native app to find the native libs under system folder, I have another non-native app that can use GPU delegate. I read docs saying any native shared library is accessible regardless of whether it is an NDK library at least for the API_LEVEL I have. So I just wonder if there is away to add access for natively built apps?
Because apps are not allowed to access vendor libraries: https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#private-api-enforced-for-api-level-24
If android installed at below path:
/system/product/priv-app/mynative/app-debug.apk
And this apk contains a jni library:
app-debug/lib/arm64-v8a/libnative-lib.so
Where is the path android to load the library libnative-lib.so? I search device and never find that so file.
The answer might be: "it never was on the filesystem to begin with".
Modern Android build infrastructure sets extractNativeLibraries=false by default. This keeps the .so in the APK instead of having a copy linger on your device.
EDIT: I did some source digging, the Android runtime linker can open libraries directly from zip files if the filename contains !/. I think this would just show up as another mapping of the APK in /proc/pid/maps, but I did not investigate beyond that (eg how relocation is done in this case or what namespaces have to do with it).
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.
Can somebody help me write Android.mk for LibXtract or point me in correct directoin?
Here is source for lib - https://github.com/jamiebullock/LibXtract.git
Or mayby there is a way to use linux generated shared objects in Android?
Especially for bigger established projects, crafting Android.mk files is quite an effort. More so, if you are not familiar with Android NDK build architecture whose understanding requires digging deep into the documentation and Android NDK make files. I would suggest trying to use existing make files by setting CC to point to your NDK tool chain, and CFLAGS += -sysroot $(SYSROOT) where SYSROOT=${NDK_INSTALL_DIR}/platforms/android-<level>/arch-<arch>/ (depending on targeted Android API version and architecture). Even without knowing about your library, I would bet you should have good chance of success this way. Android NDK documentation (${NDK_INSTALL_DIR}/doc/STANDALONE-TOOLCHAIN.html) details the use of independent tool chain and also instructs how to create a standalone tool chain that will not require the use of -sysroot argument to xxx-gcc.
If you decide to use Android.mk instead, you might check existing projects -CSipSimple comes to my mind (PJSIP converted from standard form GNU make files).
Important is to create the shared objects using Android tool chains. It is possible to build them outside of your application source tree, and then just copy the shared objects into the package source libs/<architecture>/ directory.
Integration with your build system depends on details that are not known (including how smooth you desire this whole integration to be e.g. because of other people working with the same project). If you are creating an application from command line, the easiest would be to have GNU make file or shell script in the package root directory ensure libXtract.so and your application package is up-to-date by calling libXtract make file and ant to build and pack your Java application. If you are using ant there should be a way to specify using make to take care of libXtract.so. I am not sure if eclipse is completely relying on ant for building an application to know if this would be enough for enabling complete build by clicking mouse buttons from within eclipse, too.
The answer to this question says you could use cmake script to build Android.mk files - I have not tried this approach.
I wish to back port the Android RTP APIs introduced in version 3.1(Honeycomb) to earlier versions. I downloaded the source of version 4.0 and found that it these APIs had both java and native code. In order to build the native code with the NDK, certain shared libraries are required.
According the Android.mk file, these are libnativehelper, libcutils, libutils, and libmedia. Though the source of all of these are present in the source code, building them was difficult. Each required many other shared libraries. For eg, libmedia requires these shared libraries: libui, libcutils, libutils, libbinder, libsonivox, libicuuc, libexpat, libcamera_client, libstagefright_foundation, libgui and libdl.
So my question is, is there some way of obtaining the original 4 shared libs? Does it involve building the entire source?
Say I need to build a piece of native code which is going to use standard Android shared libraries such as libutils, libcutlis, libmedia. I would perform following steps:
Install AOSP repository with target version.
Add my source code to appropriate directories under ./frameworks/base. In your case it might be easier to create a separate folder and put proper Android.mk of course.
You might get compile errors if required functions from those standard shared libraries are not present in the previous version.
When you build the code as part of AOSP it will build required libraries and link them for you automatically.
P.S. To accomplish that you're better to use a Linux-based build host.
using cygwin terminal, build native part i.e. jni folder. To build using cygwin, goto jni folder using cygdrive command. Then type ndk-build. After successful completion, shared libraries i.e. .so files will be created in libs folder.
I can understand your problem, you can pull the libraries from /system/lib of device or emulator. But you need a system permission. But you can do it by installing application.
Otherwise build your source code on linux platfor. Building process is very easy, just using 2 or 3 command. First time it is needed long time to build. After that you need very short time to build, it will build only according to the timestamp of modified code.
Please have a look here