Android N限制共享库为PIC

    最近有位同事遇到个问题,他们的模块提供给产品的共享库是带有.text.rel段的,而android N的linker限制共享库不能有TEXTREL,导致加载失败。

    首先,该模块有大量的汇编代码,即使有编译开关-fPIC,生成的so仍然带有TEXTREL。

    其次,linker对so的这个限制只针对API level大于22,本来只需要修改AndroidManifest.xml中的target sdk version就可以解决,但是产品端比较强势,改不了。

    没有办法了,只能针对.text.rel中所有重定位符号,一个个修正,好在不多。

    但是遇到了个问题,有一个重定位符号,是一个段名,源码大概如此:

.section .rodata
.align 4
pmovmskb_byte:
.byte 1,2,4,8,16,32,64,128
.byte 1,2,4,8,16,32,64,128
...
.text
...
movrel      r1, pmovmskb_byte
...

movrel是自定义宏,定义为:
.macro  movrel rd, val
        ldr             \rd, =\val
.endm

最终利用了开源代码,将movrel修改为相对pc寻址来解决了。


至于原因,在arm官网貌似找到了答案:

https://community.arm.com/tools/f/discussions/532/problem-in-generating-position-independent-code-with-out-textrel


1. 当告诉armasm汇编器,增加pic开关‘--apcs /fpic',合理的情况下,RO sections会标记为PIC,这和C/C++编译器不同,增加'--apcs /fpic'会告诉编译器,必须把RO sections目标代码标记为PIC。汇编器不能增加相对PC来寻址的relocation,但编译器可以。

所以,如果是C/C++与arm指令混合编码,arm指令是否为PIC不受c/c++编译开关-fPIC的影响。

2. 汇编代码中使用了DCD or LDR rx,=等指令,会造成绝对寻址,汇编代码无法再被优化,只能在运行时重定位,所以增加了TEXTREL

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章