有没有办法让gcc生成常量的%pc
相对地址?即使字符串出现在文本段中,arm-elf-gcc也会生成一个指向数据的常量指针,通过%pc
相对地址加载指针的地址,然后解引用它。由于各种原因,我需要跳过中间步骤。例如,这个简单的函数:
const char * filename(void)
{
static const char _filename[]
__attribute__((section(".text")))
= "logfile";
return _filename;
}
使用 arm-elf-gcc-4.3.2 -nostdlib -c -O3 -W -Wall logfile.c
编译时会生成以下文件:
00000000 <filename>:
0: e59f0000 ldr r0, [pc, #0] ; 8 <filename+0x8>
4: e12fff1e bx lr
8: 0000000c .word 0x0000000c
0000000c <_filename.1175>:
c: 66676f6c .word 0x66676f6c
10: 00656c69 .word 0x00656c69
我本以为它会生成更像这样的内容:
filename:
add r0, pc, #0
bx lr
_filename.1175:
.ascii "logfile\000"
需要注意的是,代码需要部分位置独立,因为它将在加载时在内存中重新定位,但也需要与未使用 -fPIC
编译的代码集成,因此没有全局偏移表。
我的临时解决方案是调用非内联函数(通过 %pc
相对地址实现),类似于 -fPIC
代码工作原理的技术,从编译位置找到偏移量:
static intptr_t
__attribute__((noinline))
find_offset( void )
{
uintptr_t pc;
asm __volatile__ (
"mov %0, %%pc" : "=&r"(pc)
);
return pc - 8 - (uintptr_t) find_offset;
}
但是这种技术需要手动修复所有数据引用,因此上面例子中的
filename()
函数将变成:const char * filename(void)
{
static const char _filename[]
__attribute__((section(".text")))
= "logfile";
return _filename + find_offset();
}