ARM + gcc: don't use one big .rodata section

对着背影说爱祢 提交于 2019-12-23 19:40:50

问题


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

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.


回答1:


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

this is expanded into

    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.

You could try an asm block containing

    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:



回答2:


"This is an assembler message, not a linker message, so this happens before sections are generated" - I am not sure but I think it is a little bit more complicated with LTO. Compiling (including assembling) of the individual c-files with LTO enabled works fine and does not cause any problems. The problem occurs when I try to link them together with LTO enabled. I don't know how LTO is exactly done, but apparently this also includes calling the assembler again and then I get this error message. When linking without LTO, everything is fine and when I look at the disassemly I can see that my constants are not placed after a function. Instead all constants are placed in the .rodata section. With LTO enabled because of inlining, my functions probably get to large to reach the constant pool...



来源:https://stackoverflow.com/questions/23014449/arm-gcc-dont-use-one-big-rodata-section

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!