在.so中混合使用c / c ++和汇编时避免文本重定位

我试图从混合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中看到文本重定位,这是通过scanelfreadelf可见的。 api模式23中的Android L加载器将拒绝加载这样的.so。

问题: – 这个问题值得期待吗? – 是否在C或asm方面使用了一些特殊声明以确保没有文本重定位?

编辑 :最小的例子会有用吗?

感谢所有评论。 因此,为了总结其他人与Android M的斗争,我们能够解决一些问题。 我现在的理解如下,如果我错了,请纠正我:

1)我无法直接指向外部全局变量(即ldr)而不会导致文本重定位。

2)即使不是全局的,我也无法在asm中引用数据部分中包含的符号,因为在汇编时,文本到数据的相对地址是未知的。 为什么.so链接器在链接时无法解决这个问题我不确定,但我只能假设相对地址太远或者本质上是PIC的数据/文本的相对地址在运行时是不知道的(?) 。

所以我们的修复是:

1)预生成数组并添加到文本部分,尽可能接近使用它的代码(相对指令的距离有限)。 我们发现将表放在离代码太远的地方使用它失败了。

2)当从标签加载时,’adr’的使用优先于’ldr’,因为它似乎确保您从当前部分加载并帮助我们避免一些文本重定位

幸运的是,我们的数组虽然是在运行时生成的静态数据,但可以在汇编时转换为const。 但是对于数组或内存是动态的并且必须从C传递给asm的那些,我看不出其他任何选择将其作为参数传递给汇编代码,如评论中的几个人所建议的那样。

一个有用的读物​​是: ARM – 将地址加载到寄存器中