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] Fail on erroneous linker script


Hello,

The attached patch fixes a linker problem that may cause the linker to accept an erroneous linker script and produce a broken binary.

The essence of the problem is that any PROGBITS section that follows a NOBITS section in a PT_LOAD segment will end up at the wrong offset when loaded into memory.

In most valid cases NOBITS sections (.bss, usually) are placed at the end of the loaded segments. However, if a user provides a custom linker scripts which puts, a .bss section in the middle of the data segment, the linker will produce a broken binary. The proper behavior for linker is to fail with appropriate error message.

One exception to the above rule is a .tbss section in a PT_LOAD segment, such a section doesn't take space in neither file nor the memory segment, so it is OK.

To fix the problem the patch places the sanity check into the code that assigns file offsets to the LOAD sections: when a NOBITS section is seen, the file offset is assumed to be invalid for any subsequent PROGBITS section within the current segment. The error is then thrown if an attempt to use the invalid offset is made.

This patch was tested on i686-linux-gnu with no fails. Also, it fixes the motivating case which is building 2.6.23 version of the linux kernel for ColdFire.

OK for mainline?

Regards,

--
Maxim Kuvyrkov
CodeSourcery
maxim@codesourcery.com
(650) 331-3385 x724
2009-12-04  Maxim Kuvyrkov  <maxim@codesourcery.com>

	bfd/
	* elf.c (assign_file_positions_for_load_sections): Issue an error
	if a NOBITS section is followed by a PROGBITS section.

	ld/testsuite/
	* ld-i386/alloc.d: Expect a new error message.
Index: ld/testsuite/ld-i386/alloc.d
===================================================================
--- ld/testsuite/ld-i386/alloc.d	(revision 270208)
+++ ld/testsuite/ld-i386/alloc.d	(working copy)
@@ -1,4 +1,4 @@
 #name: Invalid allocated section
 #as: --32
 #ld: -melf_i386 -T alloc.t
-#error: .*section `.foo' can't be allocated in segment 0.*
+#error: .*PROGBITS section .foo cannot follow NOBITS section .bss in ELF segment 0.*
Index: bfd/elf.c
===================================================================
--- bfd/elf.c	(revision 270208)
+++ bfd/elf.c	(working copy)
@@ -4211,6 +4211,7 @@ assign_file_positions_for_load_sections 
       asection **secpp;
       bfd_vma off_adjust;
       bfd_boolean no_contents;
+      asection *last_nobits_section;
 
       /* If elf_segment_map is not from map_sections_to_segments, the
 	 sections may not be correctly ordered.  NOTE: sorting should
@@ -4413,6 +4414,8 @@ assign_file_positions_for_load_sections 
 	    }
 	}
 
+      last_nobits_section = NULL;
+
       /* Set up p_filesz, p_memsz, p_align and p_flags from the section
 	 maps.  Set filepos for sections in PT_LOAD segments, and in
 	 core files, for sections in PT_NOTE segments.
@@ -4448,6 +4451,20 @@ assign_file_positions_for_load_sections 
 
 	      if (this_hdr->sh_type != SHT_NOBITS)
 		{
+		  if (last_nobits_section != NULL)
+		    /* The offset within binary (OFF) is no longer correct
+		       after processing a NOBITS section in any given
+		       segment.  That is because a NOBITS section doesn't
+		       take space in the binary, but is allocated in
+		       the memory.  */
+		    {
+		      (*_bfd_error_handler)
+			(_("%B: PROGBITS section %A cannot follow "
+			   "NOBITS section %A in ELF segment %u"),
+			 abfd, sec, last_nobits_section, j);
+		      return FALSE;
+		    }
+
 		  off += adjust;
 		  p->p_filesz += adjust;
 		}
@@ -4481,6 +4498,11 @@ assign_file_positions_for_load_sections 
 		  this_hdr->sh_offset = sec->filepos = off;
 		  if (this_hdr->sh_type != SHT_NOBITS)
 		    off += this_hdr->sh_size;
+		  else if ((this_hdr->sh_flags & SHF_ALLOC) != 0
+			   /* .tbss is special.  It doesn't contribute to
+			      p_memsz of normal segments.  */
+			   && (this_hdr->sh_flags & SHF_TLS) == 0)
+		    last_nobits_section = sec;
 		}
 
 	      if (this_hdr->sh_type != SHT_NOBITS)

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