生成常量数据的%pc相对地址

8

有没有办法让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();
}
1个回答

1

嗯,也许你需要将其编译为-fPIC以获得PIC。或者简单地用汇编语言编写,汇编语言比你正在编写的C要容易得多。

00000000:
   0:e59f300c    ldr r3,[pc,#12]   ; 14 
   4:e59f000c    ldr r0,[pc,#12]   ; 18 
   8:e08f3003    add r3,pc,r3
   c:e0830000    add r0,r3,r0
  10:e12fff1e    bx  lr
  14:00000004    andeq   r0,r0,r4
  18:00000000    andeq   r0,r0,r0
0000001c: 1c:66676f6c strbtvs r6,[r7],-ip,ror #30 20:00656c69 rsbeq r6,r5,r9,ror #24

你是否收到了和我一样的警告?

/tmp/ccySyaUE.s:汇编器消息: /tmp/ccySyaUE.s:35:警告:忽略更改的 .text 节属性。

是的,我也收到了相同的警告。 最简单的解决方法是添加一个虚假的换行符和注释:__attribute __((section(“.text \ n#”)))。由于ROM中有在显式地址处的函数,因此无法使用-fPIC进行编译。 对我来说,汇编是可以的,但对系统的其他用户来说不行... - Hudson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接