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

发布于 2024-09-03 16:54:17 字数 1562 浏览 11 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

于我来说 2024-09-10 16:54:17

嗯,也许你必须将其编译为 -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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文