Bug 20062 - Gold2.26 fail to link Uefi firmware with internal error in do_layout, but ld works
Summary: Gold2.26 fail to link Uefi firmware with internal error in do_layout, but ld ...
Status: ASSIGNED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.26
: P2 critical
Target Milestone: ---
Assignee: Cary Coutant
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-09 05:25 UTC by Steven Shi
Modified: 2017-12-12 03:04 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Uefi hello example with pre-built libraires to link (355.64 KB, application/x-tar)
2016-05-09 05:25 UTC, Steven Shi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steven Shi 2016-05-09 05:25:13 UTC
Created attachment 9242 [details]
Uefi hello example with pre-built libraires to link

Uefi standard (http://www.uefi.org/) firmware (https://github.com/tianocore/edk2) can build with ld, but cannot build with gold linker. When link a uefi module, the gold will report internal error in do_layout as blew.

ld-new: internal error in do_layout, at ../../binutils-2.26/gold/object.cc:1819

Attachment is a Uefi hello example with pre-built libraires, you can direclty extract it and link them with ld and ld-new:

gold 2.26 will fail as below:
"ld-new" -o Hello.dll -nostdlib -n -q --gc-sections -z common-page-size=0x40 --entry _ModuleEntryPoint -u _ModuleEntryPoint -Map Hello.map -melf_x86_64 --oformat=elf64-x86-64 --start-group  @static_library_files.lst --end-group --defsym=PECOFF_HEADER_SIZE=0x228 --script=GccBase.lds
ld-new: internal error in do_layout, at ../../binutils-2.26/gold/object.cc:1819


but ld 2.26 will succeed:
"ld" -o Hello.dll -nostdlib -n -q --gc-sections -z common-page-size=0x40 --entry _ModuleEntryPoint -u _ModuleEntryPoint -Map Hello.map -melf_x86_64 --oformat=elf64-x86-64 --start-group  @static_library_files.lst --end-group --defsym=PECOFF_HEADER_SIZE=0x228 --script=GccBase.lds

BTW, this folder example libraries are abstracted from Uefi Hello module build as below. If you need, you can build them by yourself
1. Setup EDK2 build environment as steps in the link: https://github.com/tianocore/tianocore.github.io/wiki/Using-EDK-II-with-Native-GCC 
2. git clone https://github.com/tianocore/edk2 (e.g. ~/edk2)
3. cd ~/edk2
4. make -C BaseTools
5. source edksetup.sh
6. build -t GCC49 -a X64 -p AppPkg/AppPkg.dsc -m AppPkg/Applications/Hello/Hello.inf

After build, you can find all intermediate files in below folder
~/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Hello/Hello
Comment 1 Steven Shi 2016-05-14 14:46:09 UTC
Hello,
How's the issue going on? Please let me know if you need other more information. Thanks!
Comment 2 Steven Shi 2016-05-18 09:30:40 UTC
Hello,
I'm sorry, but how's the issue going on? I really hope to try the gold linker for my LTO build.
Comment 3 Cary Coutant 2016-05-20 01:17:59 UTC
Gold does not currently support the combination of --gc-sections with either -r or --emit-relocs. Unfortunately, we only diagnose with -r, and hit an internal error if --emit-relocs is used.

If you remove --gc-sections from the link, we hit another internal error, which is the result of trying to layout the .rela.* sections according to the linker script. It turns out that Gnu ld ignores the .rela directives in the SECTIONS clause, instead writing the output relocations as orphan sections. Gold should do the same.

If you also remove the .rela directive from the SECTIONS clause, gold will link successfully, and it makes no difference to Gnu ld.
Comment 4 Steven Shi 2017-12-12 03:04:48 UTC
Thanks. With below build option update, the Uefi GCC5 tool chain can use ld.gold  build OVMF and boot on Qemu.

$ git diff master
diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
index 98ab6dd..919c1b4 100755
--- a/BaseTools/Conf/tools_def.template
+++ b/BaseTools/Conf/tools_def.template
@@ -4584,14 +4584,14 @@ DEFINE GCC48_AARCH64_DLINK2_FLAGS    = DEF(GCC47_AARCH64_DLINK2_FLAGS)
 DEFINE GCC48_ARM_ASLDLINK_FLAGS      = DEF(GCC47_ARM_ASLDLINK_FLAGS)
 DEFINE GCC48_AARCH64_ASLDLINK_FLAGS  = DEF(GCC47_AARCH64_ASLDLINK_FLAGS)

-DEFINE GCC49_IA32_CC_FLAGS           = DEF(GCC48_IA32_CC_FLAGS)
-DEFINE GCC49_X64_CC_FLAGS            = DEF(GCC48_X64_CC_FLAGS)
+DEFINE GCC49_IA32_CC_FLAGS           = DEF(GCC48_IA32_CC_FLAGS) -fuse-ld=gold
+DEFINE GCC49_X64_CC_FLAGS            = DEF(GCC48_X64_CC_FLAGS) -fuse-ld=gold -mcmodel=large -fno-pie
 DEFINE GCC49_IA32_X64_DLINK_COMMON   = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x40
 DEFINE GCC49_IA32_X64_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_DLINK_COMMON) -Wl,--entry,ReferenceAcpiTable -u ReferenceAcpiTable
 DEFINE GCC49_IA32_X64_DLINK_FLAGS    = DEF(GCC49_IA32_X64_DLINK_COMMON) -Wl,--entry,$(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Wl,-Map,$(DEST_DIR_DEBUG)/$(BASE_NAME).map,--whole-archive
-DEFINE GCC49_IA32_DLINK2_FLAGS       = DEF(GCC48_IA32_DLINK2_FLAGS)
+DEFINE GCC49_IA32_DLINK2_FLAGS       = DEF(GCC48_IA32_DLINK2_FLAGS) -fuse-ld=gold -Wl,--no-gc-sections
 DEFINE GCC49_X64_DLINK_FLAGS         = DEF(GCC49_IA32_X64_DLINK_FLAGS) -Wl,-melf_x86_64,--oformat=elf64-x86-64,-pie
-DEFINE GCC49_X64_DLINK2_FLAGS        = DEF(GCC48_X64_DLINK2_FLAGS)
+DEFINE GCC49_X64_DLINK2_FLAGS        = DEF(GCC48_X64_DLINK2_FLAGS) -fuse-ld=gold -Wl,-no-pie,--no-gc-sections
 DEFINE GCC49_ASM_FLAGS               = DEF(GCC48_ASM_FLAGS)
 DEFINE GCC49_ARM_ASM_FLAGS           = DEF(GCC48_ARM_ASM_FLAGS)
 DEFINE GCC49_AARCH64_ASM_FLAGS       = DEF(GCC48_AARCH64_ASM_FLAGS)
diff --git a/BaseTools/Scripts/GccBase.lds b/BaseTools/Scripts/GccBase.lds
old mode 100644
new mode 100755
index a43e007..7e2f5a7
--- a/BaseTools/Scripts/GccBase.lds
+++ b/BaseTools/Scripts/GccBase.lds
@@ -57,10 +57,6 @@ SECTIONS {
     KEEP (*(.eh_frame))
   }

-  .rela (INFO) : {
-    *(.rela .rela.*)
-  }
-
   .hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
     KEEP (*(.hii))
   }
@@ -69,7 +65,6 @@ SECTIONS {
    * Retain the GNU build id but in a non-allocatable section so GenFw
    * does not copy it into the PE/COFF image.
    */
-  .build-id (INFO) : { *(.note.gnu.build-id) }

   /DISCARD/ : {
     *(.note.GNU-stack)