我正在使用Android r10e NDK为Android构建Unison(文件同步可执行文件),但这不是Android问题。
Android> 5.0(SDK 21)要求可执行文件与位置无关。所以我 在编译时将-pie传递给arm-linux-androideabi-gcc,其工作原理如下:
% hardening-check ./unison
./unison:
Position Independent Executable: yes
...
这在Android 5.0设备上运行良好。
Android> 6.0(SDK 21)仍然要求可执行文件与位置无关, 但还要求在没有文本重定位的情况下构建可执行文件。所以我 在编译时将-fPIC传递给arm-linux-androideabi-gcc,它似乎可以构建 没有文本重定位的二进制文件:
% arm-linux-androideabi-readelf -a ./unison |& grep TEXTREL
(no output is shown)
问题是,我一次只能满足一个要求。如果我使用-pie和 -fPIC在一起,生成的可执行文件与位置无关(yay!),但是 还有文本重定位(嘘!):
% hardening-check ./unison
./unison:
Position Independent Executable: yes
...
% arm-linux-androideabi-readelf -a ./unison |& grep TEXTREL
0x00000016 (TEXTREL) 0x0
0x0000001e (FLAGS) TEXTREL BIND_NOW
...并且Android 6.0设备拒绝运行它:
% adb push unison /data/local/tmp
% adb shell '/data/local/tmp/unison -version'
WARNING: linker: /data/local/tmp/unison has text relocations. This is wasting memory and prevents security hardening. Please fix.
CANNOT LINK EXECUTABLE: can't protect segments for "/data/local/tmp/unison": Permission denied
让这些旗帜一起工作所需的特殊酱汁是什么?要么, 或者,我错过了什么? PIC和PIE是互斥的吗?
谢谢!
修改
我正在手动浏览OPAM repo所经历的相同过程来构建Unison for Android。即:
构建ocaml交叉编译器。
拉下Unison来源。
应用补丁:
--- pty.c~ 2010-04-15 19:29:31.000000000 +0200
+++ pty.c 2013-01-16 19:28:56.258812188 +0100
@@ -10,7 +10,7 @@
extern void uerror (char * cmdname, value arg) Noreturn;
// openpty
-#if defined(__linux)
+#if defined(__linux) && !defined(__ANDROID__)
#include <pty.h>
#define HAS_OPENPTY 1
#endif
--- Makefile.OCaml~ 2013-01-16 19:27:10.686807807 +0100
+++ Makefile.OCaml 2013-01-16 19:29:46.814814286 +0100
@@ -136,7 +136,9 @@
# openpty is in the libutil library
ifneq ($(OSARCH),solaris)
ifneq ($(OSARCH),osx)
- CLIBS+=-cclib -lutil
+ ifneq ($(OSCOMP),android)
+ CLIBS+=-cclib -lutil
+ endif
endif
endif
buildexecutable::
构建:
% make \
UISTYLE=text \
OCAMLOPT="arm-linux-androideabi-ocamlopt -verbose -ccopt '-fPIC -pie'" \
OSCOMP=android
上面的过程构建了一个在Android 5上运行良好的PIE可执行文件,但在Android 6上运行失败,因为它有文本重定位。删除上面的“-pie”构建没有文本重定位的二进制文件,但不是PIE可执行文件,因此它不能在Android 5或6上运行。
答案 0 :(得分:1)
只是为了一些人看到这个问题,认为它完全符合他们的问题,
text relocations despite -fPIC?
将是正确的答案。简而言之,在仔细检查了所有的&#34; C&#34;代码设置,不要忘记汇编代码问题。
答案 1 :(得分:0)
Lollipop发布后,我被类似的东西困住了。从那时起,为了确保更好的ASLR,必须使用PIE可执行文件。
如果您只能使用4.1 + 支持,则只需设置一个简单的解决方案foldr
即可。
通过这样做,编译器将在某个阶段激活-fPIE标志。
这可能是您的Application.mk看起来很简单的一个非常简单的例子。
APP_PLATFORM := android-16
答案 2 :(得分:0)
您使用的标志应该是正确的,尽管我还没有尝试使用ocaml(交叉)编译器。在一个大的纯C代码库上,我设法在没有文本重定位的情况下构建PIE可执行文件,在编译期间传递-fPIC
,在链接期间传递-fPIE -pie
。
你描述标志互相覆盖的方式听起来很怪异。我的猜测是它以某种方式来自ocaml前端如何通过-ccopt
参数将它们传递给后端工具。 -pie
标志是链接器标志,因此根本不需要将其传递给编译步骤。如果它没有传递给编译步骤,生成的代码应该与之前相同,它只是应该改变的链接步骤,对吧?
您可以检查哪些目标文件实际包含文本重定位,以及它们构建的编译器选项是什么? (我不确定这在任何地方是否可见,我认为它是由ocamlopt
在内部调用的。)如果没有一个单独的目标文件包含文本重定位,看起来它们会来自某些链接的ocaml特定目标文件?