ARM + gcc:不要使用一个大的 .rodata 部分 [英] ARM + gcc: don't use one big .rodata section

查看:47
本文介绍了ARM + gcc:不要使用一个大的 .rodata 部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 gcc 编译一个程序,并为 ARM 处理器进行链接时间优化.当我在没有 LTO 的情况下编译时,系统会被编译.当我启用 LTO(使用 -flto),我收到以下汇编错误:

I want to compile a program with gcc with link time optimization for an ARM processor. When I compile without LTO, the system gets compiled. When I enable LTO (with -flto), I get the following assembler-error:

错误:文字常量无效:池需要更近

Error: invalid literal constant: pool needs to be closer

上网查了一下,发现这与我系统中的常量有关,它们被放置在一个名为 .rodata 的特殊部分中,该部分称为常量池,并位于 .text 部分之后我的系统.似乎在使用 LTO 进行编译时,由于内联和其他优化,此 .rodata 部分与指令的距离太远,因此无法再对常量进行寻址.是否可以将常量放在使用它们的函数之后?或者是否可以使用另一种寻址模式以便仍然可以寻址 .rodata 部分?谢谢.

Looking around the web I found out that this has something to do with the constants in my system, which are placed in a special section called .rodata, which is called a constant pool and is placed right after the .text section in my system. It seems that when compiling with LTO because of inlining and other optimizations this .rodata section gets too far away from the instructions, so that the addressing of the constants is not possible anymore. Is it possible to place the constants right after the function that uses them? Or is it possible to use another addressing mode so the .rodata section can still be addressed? Thanks.

推荐答案

这是一个汇编器消息,而不是一个链接器消息,所以这发生在节生成之前.

This is an assembler message, not a linker message, so this happens before sections are generated.

汇编程序有一条伪指令用于将常量加载到寄存器中:

The assembler has a pseudo instruction for loading constants into registers:

    ldr r0, =0x12345678

这被扩展为

    ldr r0, [constant_12345678, r15]
    ...
    bx lr
constant_12345678:
    dw 0x12345678

常量池通常跟在返回指令之后.使用函数内联,函数可以得到足够长的返回指令太远;不幸的是,编译器不知道内存地址之间的距离,而汇编器除了流不会超出返回指令之外,所以在这里发出常量池是安全的"之外,也不知道控制流.

The constant pool usually follows the return instruction. With function inlining, the function can get long enough that the return instruction is too far away; unfortunately, the compiler has no idea of the distance between memory addresses, and the assembler has no idea of control flow other than "flow does not pass beyond the return instruction, so it is safe to emit the constant pool here".

很遗憾,目前没有好的解决方案.

Unfortunately, there is no good solution at the moment.

你可以尝试一个包含

    b 1f
    .ltorg
1:

这将在此时强制发出常量池,代价是额外的分支指令.

This will force-emit the constant pool at this point, at the cost of an extra branch instruction.

如果常量池为空,可能会指示汇编器省略分支,但我目前无法测试,所以这可能无效:

It may be possible to instruct the assembler to omit the branch if the constant pool is empty, but I cannot test that at the moment, so this is probably not valid:

    .if (2f - 1f)
    .b 2f
    .endif
1:
    .ltorg
2:

这篇关于ARM + gcc:不要使用一个大的 .rodata 部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆