When I run native code on Android L (Nexus 5), I get the error.
<error: only position independent executables (PIE) are supported.
The Chromium project released a wrapper that allows PIE binaries to run on pre-JB Android releases. Note that your PIE executable requires a few extra flags to make this work:
CFLAGS += -fvisibility=default -fPIE
LDFLAGS += -rdynamic -fPIE -pie
In my case, I was shipping ~2MB binaries for 3 architectures and did not want to add 6MB of uncompressed data to the APK just to continue supporting ICS. run_pie
is extremely tiny (6-7kB) so it fit the bill.
run_pie
should not be built with the PIE flags, and it should not be executed on Android 5.0+ (because, of course, non-PIE binaries are banned). Unfortunately it cannot be built statically because it needs to be linked with -ldl
and NDK only provides a shared version of that library.
The Java side could look something like:
String dir = mContext.getFilesDir().getPath();
String command = dir + "/busybox netstat";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
command = dir + "/run_pie " + command;
}
where busybox
is a PIE executable and lives in the app's private files directory.
See also: earlier discussions of this topic here and here.
Edit JFDee: In my case, I kept getting the error "dlopen() failed: Cannot load library" when running run_pie with my PIE executable. I had to explicitly set LD_LIBRARY_PATH to the directory the executable resided in, i.e. the current path.
In that case the amended example code line of the "run_pie" call would look like this:
...
command = "LD_LIBRARY_PATH=. " + dir + "/run_pie " + command;
...