我正在尝试从混合c,c ++和程序集的.so中删除所有文本重定位。对于c / c ++ -fpic负责PIC。
在Android ARM目标上,我们可以从c / c ++调用导出的asm函数,而不会导致文本重定位。但是在我们的实现中,我们有必须可以从C ++和程序集访问的数据数组。在C ++上,它是一个普通的旧数组,即extern "C" { __declspec(align(32)) int16_t myarray[256]; }
,在asm方面,我们使用.global myarray
。
第二个我们在asm侧使用这样的符号,我们在最终的.so中看到文本重定位,这可以通过scanelf
和readelf
看到。 api模式23下的Android L加载器将拒绝加载这样的.so。
问题: - 这个问题值得期待吗? - 是否在C或asm方面使用了一些特殊声明以确保没有文本重定位?
编辑:最小的例子会有用吗?
答案 0 :(得分:1)
感谢所有评论。因此,为了总结其他人与Android M的斗争,我们能够解决一些问题。我现在的理解如下,如果我错了,请纠正我:
1)我无法直接指向外部全局变量(即ldr)而不会导致文本重定位。
2)即使不是全局的,我也无法在asm中引用数据部分中包含的符号,因为在汇编时,文本到数据的相对地址是未知的。为什么.so链接器在链接时无法解决这个问题我不确定,但是我只能假设相对地址太远或者本质上是PIC的数据/文本的相对地址在运行时不知道(?)
所以我们的修复是:
1)预先生成数组并添加到文本部分,尽可能接近使用它的代码(相对指令的距离有限)。我们发现将表格放在离代码太远的地方使用它失败了。
2)从标签加载时,'adr'的使用优先于'ldr',因为它似乎确保您从当前部分加载并帮助我们避免一些文本重定位
幸运的是,我们的数组虽然是在运行时生成的静态数据,但可以在汇编时转换为const。但是对于数组或内存是动态的并且必须从C传递给asm的那些,我看到没有其他选择可以将它作为参数传递给汇编代码,如评论中的几个人所建议的那样。