【发布时间】: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。我必须在CFLAGS 和ETH_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