在.so中混合使用c/c++和assembly时避免文本重定位
avoiding text relocations when mixing c/c++ and assembly in a .so
我正在尝试从.中删除所有文本重定位,以便混合c、c++和汇编。对于c/c++,fpic负责PIC。
在Android ARM目标上,我们能够从c/c++调用导出的asm函数,而不会导致文本重新定位。但在我们的实现中,我们有数据数组,这些数组必须可以从C++和汇编访问。在C++上,它是一个普通的旧数组,即extern "C" { __declspec(align(32)) int16_t myarray[256]; }
,而在asm端,我们使用.global myarray
。
第二次我们在asm端使用这样的符号时,我们会在final.so中看到文本重定位,这可以通过scanelf
和readelf
看到。api模式23下的安卓L加载程序将完全拒绝加载这样的.so.
问题:-这个问题是意料之中的事吗?-是否在C或asm端使用一些特殊声明来确保没有文本重定位?
编辑:一个最小的例子有用吗?
感谢所有的评论。因此,为了其他所有与安卓M作战的人的利益,我们能够解决我们的一些问题。我现在的理解如下,如果我错了,请纠正我:
1) 我无法在asm中直接指向外部全局变量(即ldr)而不引起文本重定位。
2) 即使不是全局的,我也无法在asm中引用数据节中包含的符号,因为在汇编时,从文本到数据的相对地址是未知的。为什么.so链接器不能在链接时解决这个问题我不确定,但我只能假设相对地址太远,或者根据PIC的性质,数据/文本的相对地址在运行时是未知的(?)。
所以我们的解决方案是:
1) 预生成数组并添加到文本部分,尽可能靠近使用它的代码(相对指令的距离有限)。我们发现,将表放在离使用它的代码太远的地方失败了。
2) 从标签加载时,首选使用"adr"而不是"ldr",因为这似乎可以确保您从当前部分加载,并帮助我们避免一些文本重定位
幸运的是,我们的数组是静态数据,尽管是在运行时生成的,并且可以在汇编时转换为常量。但是,对于那些数组或内存是动态的,必须从C传递到asm的情况,我看不出有其他选择可以将其作为参数传递给汇编代码,正如一些人在评论中所建议的那样。
一个有用的解读是:ARM-将地址加载到寄存器
您可以尝试下面的代码,它对我有效
//==============================================
文件:asm.s
.globl asm_test
.LglobalInt:
.int globalInt-.
asm_test:
push {LR}
// change the value of globalInt variable
LDR r1, .LglobalInt
adr r2, .LglobalInt
add r0, r1, r2
ldr r1, =123456789
STR r1, [r0]
pop {LR}
bx lr
//==============================================
文件:test.c
int globalInt = 0;
int main()
{
printf("globalInt = %dn", globalInt);
asm_test();
printf("globalInt = %dn", globalInt);
}
- 文本文件中的单词链表
- 从命令行c++发送文本文件名
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 2D数组来自文本输入,中间有空格
- 如何将内容数组写入文本文件?
- 无法通过空白将文本文件行分隔为矢量
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- C++将文本文件中的数据读取到结构数组中
- 在指针的帮助下,文本文件中单词的频率
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 将值从二维数组输出到文本文件
- 如何在c++中从文本文件中逐行读取整数
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 从文本文件中读取时钟时间和事件时间并进行处理
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 如何从文本文件中读取值和数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何根据单词在文本中出现的概率输出单词
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 在.so中混合使用c/c++和assembly时避免文本重定位