【发布时间】:2014-02-26 23:38:05
【问题描述】:
我正在使用 GCC 在 ARM 上为 bada 构建一个 ELF SO。编译器选项包括 -fpic。然而在构建的文件中,当我执行readelf -r 时,有很多重定位记录,类型如下:
- R_ARM_RELATIVE
- R_ARM_REL32
- R_ARM_ABS32
- R_ARM_GLOB_DAT
- R_ARM_JUMP_SLOT
我在这里误会了什么?
编辑:据我所知,编译器中的 PIC 实现不使用 GOT。相反,它们使用 PC 相对寻址,其中存储的常量是从使用点到符号地址的偏移量;这由链接器解决。像这样,读取一个全局变量:
ldr r12, OffsetToVar
PointOfUse:
ldr r0, [r12, pc]
# r0 now has the value of MyVar
#...
# At function's end...
OffsetToVar:
.long MyVar-PointOfUse-8
# Compiler can't resolve this, since it doesn't know
# the address of MyVar, but linker can
跨模块函数调用的类似想法。但是,当一个项目混合了 ARM 和 Thumb 代码时,后者可能会失败。但我已经解决了这个问题。
【问题讨论】:
-
只是猜测,您访问全局数据吗?如果是这样,代码可能是 PIC,但数据仍绑定到可能更改的地址?
-
PIC 表示位置无关代码。选择指令以便该代码块即使加载到未链接的地址空间也能正确执行。
-
我会猜测你想要什么(但不是问题的答案)。请参阅
-fixed-REG、使用-msingle-pic-base和-mpic-register,您的调度程序必须将r9设置为指向全局数据。例如,如果没有 MMU,您可以运行多个代码实例并将r9替换为指向该任务/线程/进程的全局变量的指针。这是一种避免数据重定位的机制。此外,编译器/链接器通常会发出通常不需要的重定位。