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

6yoyoihd  于 2022-12-15  发布在  C/C++
关注(0)|答案(2)|浏览(166)

我正在尝试从an中删除所有的文本重定位。这样就混合了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中看到文本重定位,这可以通过scanelfreadelf看到。API模式23下的Android L加载器将断然拒绝加载这样的. so。
问题:-这个问题是可以预料的吗?-在C或asm端是否有一些特殊的声明来确保没有文本重定位?

  • Edit*:一个最小的例子有用吗?
relj7zay

relj7zay1#

感谢所有的评论。所以总结一下,为了其他人与Android M战斗的好,我们能够解决我们的一些问题。我现在的理解如下,请纠正我,如果我错了:
1)我无法在asm中直接指向外部全局变量(即ldr)而不引起文本重定位。
2)我无法在asm中引用数据节中包含的符号,即使不是全局符号,因为在汇编时,从文本到数据的相对地址是未知的。为什么.so链接器无法在链接时解决这个问题,我不确定,但我只能假设相对地址太远,或者由于PIC的性质,数据/文本的相对地址在运行时是未知的(?)。
所以我们的解决方案是:
1)预先生成数组并添加到文本部分,尽可能靠近使用它的代码(相对指令的距离有限)。我们发现将表放置得离使用它的代码太远会失败。
2)当从标签加载时,使用“adr”比“ldr”更可取,因为它似乎可以确保您从当前部分加载,并帮助我们避免一些文本重定位
幸运的是,我们的数组是静态数据,虽然是在运行时生成的,但可以在汇编时转换为常量。但是对于那些数组或内存是动态的,必须从C传递到asm的情况,我看不出有其他选择,可以像一些人在评论中建议的那样,将其作为参数传递到汇编代码。
一个有用的读物是:ARM - Loading addresses into registers

u5rb5r59

u5rb5r592#

你可以试试下面的代码,它为我工作
//=======================================================
文件: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 = %d\n", globalInt);
    asm_test();
    printf("globalInt = %d\n", globalInt);
}

相关问题