kern build: Tweak ldscripts for gold linker
authorJohn Marino <draco@marino.st>
Thu, 23 Feb 2012 18:03:04 +0000 (19:03 +0100)
committerJohn Marino <draco@marino.st>
Fri, 24 Feb 2012 06:51:44 +0000 (07:51 +0100)
The gold linker v2.21 was able to link a working kernel although its
modules were unloadable.  The gold linker v2.22 could build loadable
modules, but the kernel wouldn't boot!  It's not clear why the modules
started to work -- my guess is that the ancient ldscripts used during
the 2.21 trial were the culprit.

The gold linker changed its ELF program header handling defaults for
version 2.22, and this resulted in an extra LOAD segment reserved only
for the program headers.  The DragonFly loader wasn't expecting that
and instantly rebooted when trying to load a gold kernel.

The solution was to add a PHDRS section to the ldscripts to specify
exactly the section to segment mapping, and prevent gold from putting
the elf headers in their own load segment.  Now gold matches gnu ld
linker in having only two LOAD segments, text and data.

As a curiousity, gold sets the LOAD segment alignment value at 0x1000
for both i386 and x86_64, where gnu ld sets the segment alignment at
0x1000 for i386 and 0x200000 for x86_64.  This seems to have no impact
on the loading of the kernel.

sys/platform/pc32/conf/ldscript.i386
sys/platform/pc64/conf/ldscript.x86_64
sys/platform/vkernel/conf/ldscript.i386
sys/platform/vkernel64/conf/ldscript.x86_64

index e9a6732..a0db817 100644 (file)
@@ -4,6 +4,16 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 OUTPUT_ARCH(i386)
 ENTRY(btext)
 SEARCH_DIR(/usr/lib);
+
+PHDRS
+{
+  headers PT_PHDR PHDRS ;
+  interp PT_INTERP ;
+  text PT_LOAD FILEHDR PHDRS ;
+  data PT_LOAD ;
+  dynamic PT_DYNAMIC ;
+}
+
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
@@ -11,8 +21,8 @@ SECTIONS
   kernmxps = CONSTANT (MAXPAGESIZE);
   kernpage = CONSTANT (COMMONPAGESIZE);
   . = kernbase + kernphys + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .interp         : { *(.interp) } :text :interp
+  .note.gnu.build-id : { *(.note.gnu.build-id) } :text
   .hash           : { *(.hash) }
   .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
@@ -136,9 +146,9 @@ SECTIONS
     KEEP (*(.dtors))
   }
   .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got) *(.igot) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } :data
+  .dynamic        : { *(.dynamic) } :data :dynamic
+  .got            : { *(.got) *(.igot) } :data
   . = DATA_SEGMENT_RELRO_END (12, .);
   .got.plt        : { *(.got.plt)  *(.igot.plt) }
   .data           :
index 890086a..8216b0a 100644 (file)
@@ -4,6 +4,16 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(btext)
 SEARCH_DIR("/usr/lib");
+
+PHDRS
+{
+  headers PT_PHDR PHDRS ;
+  interp PT_INTERP ;
+  text PT_LOAD FILEHDR PHDRS ;
+  data PT_LOAD ;
+  dynamic PT_DYNAMIC ;
+}
+
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
@@ -11,8 +21,8 @@ SECTIONS
   kernmxps = CONSTANT (MAXPAGESIZE);
   kernpage = CONSTANT (COMMONPAGESIZE);
   . = kernbase + kernphys + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .interp         : { *(.interp) } :text :interp
+  .note.gnu.build-id : { *(.note.gnu.build-id) } :text
   .hash           : { *(.hash) }
   .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
@@ -139,9 +149,9 @@ SECTIONS
     KEEP (*(.dtors))
   }
   .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got) *(.igot) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } :data
+  .dynamic        : { *(.dynamic) } :data :dynamic
+  .got            : { *(.got) *(.igot) } :data
   . = DATA_SEGMENT_RELRO_END (24, .);
   .got.plt        : { *(.got.plt)  *(.igot.plt) }
   .data           :
index e9a6732..a0db817 100644 (file)
@@ -4,6 +4,16 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 OUTPUT_ARCH(i386)
 ENTRY(btext)
 SEARCH_DIR(/usr/lib);
+
+PHDRS
+{
+  headers PT_PHDR PHDRS ;
+  interp PT_INTERP ;
+  text PT_LOAD FILEHDR PHDRS ;
+  data PT_LOAD ;
+  dynamic PT_DYNAMIC ;
+}
+
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
@@ -11,8 +21,8 @@ SECTIONS
   kernmxps = CONSTANT (MAXPAGESIZE);
   kernpage = CONSTANT (COMMONPAGESIZE);
   . = kernbase + kernphys + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .interp         : { *(.interp) } :text :interp
+  .note.gnu.build-id : { *(.note.gnu.build-id) } :text
   .hash           : { *(.hash) }
   .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
@@ -136,9 +146,9 @@ SECTIONS
     KEEP (*(.dtors))
   }
   .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got) *(.igot) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } :data
+  .dynamic        : { *(.dynamic) } :data :dynamic
+  .got            : { *(.got) *(.igot) } :data
   . = DATA_SEGMENT_RELRO_END (12, .);
   .got.plt        : { *(.got.plt)  *(.igot.plt) }
   .data           :
index 890086a..8216b0a 100644 (file)
@@ -4,6 +4,16 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(btext)
 SEARCH_DIR("/usr/lib");
+
+PHDRS
+{
+  headers PT_PHDR PHDRS ;
+  interp PT_INTERP ;
+  text PT_LOAD FILEHDR PHDRS ;
+  data PT_LOAD ;
+  dynamic PT_DYNAMIC ;
+}
+
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
@@ -11,8 +21,8 @@ SECTIONS
   kernmxps = CONSTANT (MAXPAGESIZE);
   kernpage = CONSTANT (COMMONPAGESIZE);
   . = kernbase + kernphys + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .interp         : { *(.interp) } :text :interp
+  .note.gnu.build-id : { *(.note.gnu.build-id) } :text
   .hash           : { *(.hash) }
   .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
@@ -139,9 +149,9 @@ SECTIONS
     KEEP (*(.dtors))
   }
   .jcr            : { KEEP (*(.jcr)) }
-  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
-  .dynamic        : { *(.dynamic) }
-  .got            : { *(.got) *(.igot) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } :data
+  .dynamic        : { *(.dynamic) } :data :dynamic
+  .got            : { *(.got) *(.igot) } :data
   . = DATA_SEGMENT_RELRO_END (24, .);
   .got.plt        : { *(.got.plt)  *(.igot.plt) }
   .data           :