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

时间:2010-05-30 21:24:28

标签: gcc arm fpic relative-addressing

有没有办法让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 个答案:

答案 0 :(得分: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: Assembler messages:
/tmp/ccySyaUE.s:35: Warning: ignoring changed section attributes for .text