开发者

Generating %pc relative address of constant data

Is there a way to have gcc generate %pc relative addresses of constants? Even when the string appears in the text segment, arm-elf-gcc will generate a constant pointer to the data, load the address of the pointer via a %pc relative address and then dereference it. For a variety of reasons, I need to skip the middle step. As an example, this simple function:

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename;
}

generates (when compiled with 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

I would have expected it to generate something more like:

filename:
    add r0, pc, #0
    bx lr
_filename.1175:
    .ascii "logfile\000"

The code in question needs to be partially position independent since it will be relocated in memory at load time, but also integrate with code that was not compiled -fPIC, so there is no global offset table.

My current work around is to call a non-inline function (which will be done via a %pc relative address) to find the offset from the compiled location in a technique similar to how -fPIC code works:

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;
}

But this technique requires that all data references be fixed up manually, so the filename() function in the above example would become:

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename + find_offset();
}


Hmmm, maybe you have to compile it as -fPIC to get PIC. Or simply write it in assembler, assembler is a lot easier than the C you are writing.

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

Are you getting the same warning I am getting?

/tmp/ccySyaUE.s: Assembler messages:
/tmp/ccySyaUE.s:35: Warning: ignoring changed section attributes for .text
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜