【问题标题】:gcc-4.1 -> gcc-4.8 linker error. New ".text.unlikely" section overlap ".text" sectiongcc-4.1 -> gcc-4.8 链接器错误。新的“.text.unlikely”部分与“.text”部分重叠
【发布时间】:2015-07-27 11:04:04
【问题描述】:

我正在尝试使用更新版本的 gcc 构建克伦威尔(原始 Xbox 合法固件替换),但在稍微更改项目编译设置后,ld 抛出以下错误:

ld:在 [0000000000000000,0000000000000669] 加载的部分 .text.unlikely 与在 [0000000000000000,0000000000021515] 加载的部分 .text 重叠

如果你想看看,你可以从这里克隆项目:https://github.com/not404/cromwell

首先,我想提一下,我能够在 x32 linux VM 上使用 gcc-3.3 和在 cygwin x86 上使用 gcc-4.1 成功构建和运行这个项目(在我的 Xbox 上)(为目标 i686-linux 构建 gcc -gnu)。我必须在主 Makefile 中删除 -Werror cflag 才能在 gcc-3.3 中成功构建它。在修改 makefile 后尝试在 x32 VM 上使用 gcc-4.8.2 构建它会导致上述错误。

为了到达那里,我修改了项目根目录中 Makefile 中的 CFLAGS。我仍然从 CLAGS 中删除了 -Werror。我必须在CFLAGSETH_CFLAGS 中添加-fno-stack-protector 标志才能通过undefined reference to '__stack_chk_fail' 错误。我认为这种解决方法是无害的。较旧的 gcc 版本不支持这种堆栈粉碎保护机制,因此禁用它应该不会造成问题。

在对 Makefile 进行修改后,我会看到有关部分重叠的链接器错误。我读到 .text.unlikely 部分是在 gcc 4.6 周围添加的,所以显然在克伦威尔项目积极开发时没有考虑到它!

所以,为了克服这个错误,我尝试在“ldscript-crom.ld”链接器脚本中明确定义.text.unlikely 部分。最初,脚本包含以下内容:

.text LOW_ROM : AT ( 0 ){
    _start_low_rom = . ;
    *(.text);
    _end_low_rom = . ;
}

我改成:

    .text LOW_ROM : AT ( 0 ){
    _start_low_rom = . ;
    *(.text);
    *(.text.unlikely);
    _end_low_rom = . ;
}

在这个改变之后,我又得到一个错误:

ld:在 [0000000000000000,00000000000062b3] 加载的 .eh_frame 节与在 [0000000000000000,0000000000021b7f] 加载的 .text 节重叠

根据我在网上看到的内容,.eh_frame 部分仅与异常处理有关,并针对 C++ 捕获异常。

我可以通过将以下标志添加到主 Makefile 中的 CFLAGS 和 EHT_CFLAGS 来解决此问题:

-fno-reorder-functions -fno-unwind-tables -fno-asynchronous-unwind-tables 

在这之后,我终于得到了一个输出文件。不幸的是,执行中有错误。它似乎开始很好,但我没有视频,并且执行似乎在某些时候崩溃。

我尝试打印链接文件的地图,但没有看到任何相关信息。我不会在这里发布两张地图(使用 gcc-3.3 和使用 gcc-4.8,相同的 ld),因为它们非常大。这是包含 .text.unlikely 部分定义的地图部分(来自 gcc-4.8):

                0x0000000003a216f0                disable
 *fill*         0x0000000003a2170e        0x2 
 .text          0x0000000003a21710      0x165 /home/cromwelldev/workspace/cromwell/obj/xbox_main.o
                0x0000000003a21710                loadkernel
                0x0000000003a21870                cleanup
 *fill*         0x0000000003a21875        0xb 
 .text          0x0000000003a21880      0x2b5 /home/cromwelldev/workspace/cromwell/obj/elf.o
                0x0000000003a21880                prepare_boot_params
                0x0000000003a21b20                elf_start
 *fill*         0x0000000003a21b35        0xb 
 .text          0x0000000003a21b40       0x46 /home/cromwelldev/workspace/cromwell/obj/exec_elf.o
                0x0000000003a21b40                try_elf_boot
 *(.text.unlikely)
                0x0000000003a21b86                _end_low_rom = .

.iplt           0x0000000000000000        0x0
 .iplt          0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o

.rel.dyn        0x0000000000000000        0x0
 .rel.iplt      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o
 .rel.text      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o
 .rel.data      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o

.rodata         0x0000000003a21b86    0x108b1 load address 0x0000000000021b86
 *(.rodata)
 *fill*         0x0000000003a21b86        0x2 

这是来自 gcc-3.3 的相同部分:

                    0x0000000003a1f7a0                disable
     *fill*         0x0000000003a1f7c2        0xe 
     .text          0x0000000003a1f7d0      0x165 /home/cromwelldev/workspace/cromwell/obj/xbox_main.o
                    0x0000000003a1f7d0                loadkernel
                    0x0000000003a1f930                cleanup
     *fill*         0x0000000003a1f935        0xb 
     .text          0x0000000003a1f940      0x2b6 /home/cromwelldev/workspace/cromwell/obj/elf.o
                    0x0000000003a1f940                prepare_boot_params
                    0x0000000003a1fbe0                elf_start
     *fill*         0x0000000003a1fbf6        0xa 
     .text          0x0000000003a1fc00       0x33 /home/cromwelldev/workspace/cromwell/obj/exec_elf.o
                    0x0000000003a1fc00                try_elf_boot
                    0x0000000003a1fc33                _end_low_rom = .

    .iplt           0x0000000000000000        0x0
     .iplt          0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o

    .rel.dyn        0x0000000000000000        0x0
     .rel.iplt      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o
     .rel.text      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o
     .rel.data      0x0000000000000000        0x0 /home/cromwelldev/workspace/cromwell/obj/BootStartup.o

    .rodata         0x0000000003a1fc33    0x11024 load address 0x000000000001fc33
     *(.rodata)

我认为问题在于我放入链接器脚本的.text.unlikely 部分。我必须说我在这里迷路了。我对链接器脚本不太熟悉,所以我真的不知道该怎么做。

有没有办法在不将.text.unlikely 部分与.text 部分的其余部分分开的情况下构建项目?这样可以解决我的问题吗?

我也认为-fno-reorder-functions -fno-unwind-tables -fno-asynchronous-unwind-tables 标志不能解决我的问题。在这样的项目中,有些元素需要位于特定的内存位置,我担心这些标志确实会以不好的方式移动东西!

提前谢谢你!

【问题讨论】:

    标签: gcc makefile linker linker-errors linker-scripts


    【解决方案1】:

    根据GCC docs,如果激活选项-freorder-functions(在优化级别-O2、-O3、-Os 下是默认设置),链接器可能会选择将内容放入.text.hot.text.unlikely 部分。 取决于它是否“认为”一个函数被经常调用。如果您的硬件具有快速和慢速内存区域之类的东西,我想这可能会给您一些优化潜力。
    如果不是 - 只需将这些部分添加到 .text 就可以了。

    【讨论】:

      【解决方案2】:

      您为修复有关 .text.unlikely 重叠 .text 的错误所做的操作实际上是正确的 - 链接器错误是由链接器“平底船”在加载地址 0 处开始 .text.unlikely 部分引起的,因为链接器脚本确实没有指定它去哪里。对.eh_frame 部分重复链接描述文件更改并删除-fno-reorder-functions -fno-unwind-tables -fno-asynchronous-unwind-tables 编译器标志应该可以更正有关.eh_frame 重叠.text 的错误,而不会在下游造成进一步的麻烦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-27
        • 2014-05-16
        • 2015-11-29
        • 2015-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多