ocaml-cross / opam-cross-android

An OCaml cross-toolchain for Android and several useful libraries
104 stars 14 forks source link

Recent Android versions only support PIE executables #7

Closed bacam closed 8 years ago

bacam commented 9 years ago

In Android 5.0 Google removed linker support for non-PIE (position independent executables) binaries. This causes both bytecode and native ocaml programs to fail:

root@generic:/data # ./helloworld.byte                                         
error: only position independent executables (PIE) are supported.
1|root@generic:/data # ./helloworld.native                                     
error: only position independent executables (PIE) are supported.

That was generated on a standard Google 5.0.1 image for armeabi-v7a, but the same thing happens on a Nexus 5.

A little searching around suggests that it can be tricky to support both recent and older versions of Android simultaneously because older versions don't directly support PIE, but recent versions require it. Apparently Chromium has a wrapper executable to work around this, while other people generate different executables for different versions of Android.

whitequark commented 9 years ago

That's problematic. I don't think there is a "nice" way to solve this within opam-android; what you can do is to pass -fPIE to ocamlopt manually. This will require some custom ocamlbuild rules...

avsm commented 9 years ago

you could perhaps pass this in with the CAMLPARAM env var that appends compiler flags.

On 27 Sep 2015, at 12:14, whitequark notifications@github.com wrote:

That's problematic. I don't think there is a "nice" way to solve this within opam-android; what you can do is to pass -fPIE to ocamlopt manually. This will require some custom ocamlbuild rules...

— Reply to this email directly or view it on GitHub https://github.com/whitequark/opam-android/issues/7#issuecomment-143543748.

whitequark commented 9 years ago

@avsm, that would conflict with ocamlbuild's caching. The build product would be different but ocamlbuild does not know that as it does not observe the value of CAMLPARAM. (Maybe it should.)

whitequark commented 9 years ago

I filed a bug: http://caml.inria.fr/mantis/view.php?id=6999

whitequark commented 8 years ago

@bacam Does the newer toolchain default to passing -fPIE itself, or do you have to do it manually even with r11c, level 24, etc?

bacam commented 8 years ago

I just gave it a fresh try and still generates non-PIE executables. I don't know a lot about the NDK, but from what I've seen I think it adds the options in their build setup rather than the actual tools. I suspect that the same tools also support pre-PIE Android. I forgot to mention this before, but I did manage to get it working before by adding -fPIE -pie to BYTECC in config/Makefile and managed to build unison. Both bytecode and native run, although native produces the warning

WARNING: linker: ./unison has text relocations. This is wasting memory and prevents security hardening. Please fix.

and I'm not sure if ocamlopt's code generator is actually sufficiently position independent (I recall seeing some PIE patches for iOS) so I've been using the bytecode version.

whitequark commented 8 years ago

@bacam Yeah, that's what I eventually found out as well. What I suggest doing is building your executable using OCAMLPARAM=cclib=-fPIE,-pie, which requires no changes to ocaml-cross-android and allows to reuse the same toolchain for different Android versions.

Re: ocamlopt's code generator. It is not. But I don't think that using bytecode is a correct response to this; if your executable is in OCaml then memory safety bugs aren't nearly as pressing...

whitequark commented 8 years ago

Closing with the recommendation to use export OCAMLPARAM=cclib=-fPIE,-pie rather than changing the embedded build flags. Please reopen if you think this is wrong.

jaredly commented 6 years ago

For the record, you can also add -ccopt -fPIE -ccopt -pie to your ocamlopt arguments, and it will generate the PIE executable, such that it will run on armv7 android. However, it still prints the error xyz has text relocations, and if you try to run the binary on an arm64 device, it refuses to run, with the error: CANNOT LINK EXECUTABLE "/data/local/tmp/helloworld.native": /data/local/tmp/helloworld.native: has text relocations

whitequark commented 6 years ago

I believe this is something that can only be fixed upstream.

yunxing commented 6 years ago

Try compile every single object files with -fpic, including ocaml objects when you build ocaml. This make sure no text allocation is needed at runtime.

@whiteshark, why do you say that? Is it because we have some hand written asm in ocaml?(GC for example)

whitequark commented 6 years ago

Try compile every single object files with -fpic, including ocaml objects when you build ocaml.

This is already done as per https://github.com/ocaml-cross/opam-cross-android/issues/7#issuecomment-212638955. However, the code that ocamlopt generates itself still has text relocations.

jaredly commented 6 years ago

Turns out you can sidestep the problem by either