This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: The current linker failed to generate working Linux kernel


On Wed, Aug 16, 2006 at 10:16:12AM -0700, H. J. Lu wrote:
> On Wed, Aug 16, 2006 at 06:00:17PM +0930, Alan Modra wrote:
> > On Tue, Aug 15, 2006 at 06:10:42PM -0700, H. J. Lu wrote:
> > > FYI, I opened a linker bug
> > > 
> > > http://sources.redhat.com/bugzilla/show_bug.cgi?id=3052
> > > 
> > > The current linker failed to generate working Linux 2.6 x86-64 kernel.
> > > There is a small testcase in the bug report.
> > 
> > The kernel script is invalid because it moves dot backwards.  Sigh.
> > 
> > This patch moves the code the sets section lmas from lang_do_assignments
> > to lang_size_sections, which I think is a more natural place to do
> > this.  I've also tweaked the lma code to fall back to lma == vma if dot
> > moves backwards, for compatibility with buggy ld scripts.
> > 
> 
> I don't think this fix is complete. Here is a patch with 2 testcases.
> The first one moves dot backwards similar to Linux kernel and the
> second doesn't. The issue here is
> 
>  .bar XXX : AT (YYY)
>  . = LOADADDR(.bar) + ZZZ;
>  .data : { *(.data) }
> 
> For .bar, lma != vma. But we can't assume it is also true for .data.
> 

Here is the updated patch with a fix.


H.J.
----
ld/

2006-08-16  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/3052
	* ldlang.c (lang_size_sections_1): Don't change lma unless the
	current vma overlaps the previous section.

ld/testsuite/

2006-08-16  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/3052
	* ld-elf/loadaddr.s: New file.
	* ld-elf/loadaddr1.d: Likewise.
	* ld-elf/loadaddr1.t: Likewise.
	* ld-elf/loadaddr2.d: Likewise.
	* ld-elf/loadaddr2.t: Likewise.

--- ld/ldlang.c.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/ldlang.c	2006-08-16 11:20:53.000000000 -0700
@@ -4405,30 +4405,19 @@ lang_size_sections_1
 	      }
 	    else if (r->last_os != NULL)
 	      {
-		bfd_vma lma;
 		asection *last;
 
 		last = r->last_os->output_section_statement.bfd_section;
-		/* If dot moved backwards (which is invalid according
-		   to ld docs) then leave lma equal to vma.  This
-		   keeps users of buggy ld scripts happy.  */
-		if (dot >= last->vma)
+		/* lvm should be the same as vma.  But if the current vma
+		   overlaps the previous section, then set the current lma
+		   to that at the end of the previous section.  The
+		   previous section was probably an overlay.  */
+		if ((dot >= last->vma
+		     && dot < last->vma + last->size)
+		    || (last->vma >= dot
+			&& last->vma < dot + os->bfd_section->size))
 		  {
-		    /* If the current vma overlaps the previous section,
-		       then set the current lma to that at the end of
-		       the previous section.  The previous section was
-		       probably an overlay.  */
-		    if ((dot >= last->vma
-			 && dot < last->vma + last->size)
-			|| (last->vma >= dot
-			    && last->vma < dot + os->bfd_section->size))
-		      lma = last->lma + last->size;
-
-		    /* Otherwise, keep the same lma to vma relationship
-		       as the previous section.  */
-		    else
-		      lma = dot + last->lma - last->vma;
-
+		    bfd_vma lma = last->lma + last->size;
 		    if (os->section_alignment != -1)
 		      lma = align_power (lma, os->section_alignment);
 		    os->bfd_section->lma = lma;
--- ld/testsuite/ld-elf/loadaddr.s.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/testsuite/ld-elf/loadaddr.s	2006-08-16 10:08:02.000000000 -0700
@@ -0,0 +1,16 @@
+	.text
+	.globl main
+	.globl start
+	.globl _start
+	.globl __start
+main:
+start:
+_start:
+__start:
+	.byte 0
+	.section .bar,"ax","progbits"
+	.byte 0
+	.section .foo,"aw","progbits"
+	.byte 0
+	.data
+	.byte 0
--- ld/testsuite/ld-elf/loadaddr1.d.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/testsuite/ld-elf/loadaddr1.d	2006-08-16 10:08:02.000000000 -0700
@@ -0,0 +1,10 @@
+#source: loadaddr.s
+#ld: -T loadaddr1.t -z max-page-size=0x200000
+#readelf: -l --wide
+#target: *-*-linux*
+
+#...
+  LOAD +0x000000 0xf*80000000 0xf*80000000 0x100041 0x100041 RWE 0x200000
+  LOAD +0x200000 0xf*ff600000 0xf*80101000 0x0*1 0x0*1 R E 0x200000
+  LOAD +0x302000 0xf*80102000 0xf*80102000 0x0*1 0x0*1 RW  0x200000
+#pass
--- ld/testsuite/ld-elf/loadaddr1.t.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/testsuite/ld-elf/loadaddr1.t	2006-08-16 10:08:02.000000000 -0700
@@ -0,0 +1,13 @@
+SECTIONS
+{
+  . = -0x7ff00000;
+  .text : {*(.text .text.*)}
+  . = ALIGN(64);
+  .foo : { *(.foo) }
+  .bar -0xa00000 : AT ((LOADADDR(.foo) + SIZEOF(.foo) + 4095) & ~(4095))
+    { *(.bar) }
+  . = LOADADDR(.bar) + 4096;
+  . = ALIGN(8192);
+  .data : { *(.data) }
+  /DISCARD/ : { *(.*) }
+}
--- ld/testsuite/ld-elf/loadaddr2.d.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/testsuite/ld-elf/loadaddr2.d	2006-08-16 10:08:02.000000000 -0700
@@ -0,0 +1,10 @@
+#source: loadaddr.s
+#ld: -T loadaddr2.t -z max-page-size=0x200000
+#readelf: -l --wide
+#target: *-*-linux*
+
+#...
+  LOAD +0x000000 0xf*80000000 0xf*80000000 0x100041 0x100041 RWE 0x200000
+  LOAD +0x110000 0xf*80110000 0xf*80101000 0x0*1 0x0*1 R E 0x200000
+  LOAD +0x302000 0xf*80302000 0xf*80302000 0x0*1 0x0*1 RW  0x200000
+#pass
--- ld/testsuite/ld-elf/loadaddr2.t.loadaddr	2006-08-16 10:08:02.000000000 -0700
+++ ld/testsuite/ld-elf/loadaddr2.t	2006-08-16 10:08:02.000000000 -0700
@@ -0,0 +1,13 @@
+SECTIONS
+{
+  . = -0x7ff00000;
+  .text : {*(.text .text.*)}
+  . = ALIGN(64);
+  .foo : { *(.foo) }
+  .bar -0x7fef0000 : AT ((LOADADDR(.foo) + SIZEOF(.foo) + 4095) & ~(4095))
+    { *(.bar) }
+  . = LOADADDR(.bar) + 0x200000;
+  . = ALIGN(8192);
+  .data : { *(.data) }
+  /DISCARD/ : { *(.*) }
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]