Blob Blame History Raw
commit 5e681c46b3893d87e3156a0a6c2783de5fa41c94
Author: Mark Wielaard <mjw@redhat.com>
Date:   Wed Aug 12 00:11:26 2015 +0200

    elflint: Add gnuld check when a NOBITS section falls inside a segment.
    
    gnuld has a really bad bug where it can place a NOBITS section inside
    a PT_LOAD segment. Normally that would not work. But it also makes sure
    that the contents of the file is all zeros. So in practice it is actually
    a PROGBITS section with all zero data. Except that other tools will think
    there is an unused gap in the ELF file after the NOBITS section.
    
    Recognize and check this pattern in elflint when --gnu is given.
    
    Signed-off-by: Mark Wielaard <mjw@redhat.com>

diff --git a/src/elflint.c b/src/elflint.c
index a916886..0d5f34d 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3978,9 +3978,39 @@ section [%2zu] '%s' not fully contained in segment of program header entry %d\n"
 		  {
 		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
 			&& !is_debuginfo)
-		      ERROR (gettext ("\
+		      {
+			if (!gnuld)
+			  ERROR (gettext ("\
 section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
-			 cnt, section_name (ebl, cnt), pcnt);
+				 cnt, section_name (ebl, cnt), pcnt);
+			else
+			  {
+			    /* This is truly horrible. GNU ld might put a
+			       NOBITS section in the middle of a PT_LOAD
+			       segment, assuming the next gap in the file
+			       actually consists of zero bits...
+			       So it really is like a PROGBITS section
+			       where the data is all zeros.  Check those
+			       zero bytes are really there.  */
+			    bool bad;
+			    Elf_Data *databits;
+			    databits = elf_getdata_rawchunk (ebl->elf,
+							     shdr->sh_offset,
+							     shdr->sh_size,
+							     ELF_T_BYTE);
+			    bad = (databits == NULL
+				   || databits->d_size != shdr->sh_size);
+			    for (size_t idx = 0;
+				 idx < databits->d_size && ! bad;
+				 idx++)
+			      bad = ((char *) databits->d_buf)[idx] != 0;
+
+			    if (bad)
+			      ERROR (gettext ("\
+section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d and file contents is non-zero\n"),
+				     cnt, section_name (ebl, cnt), pcnt);
+			  }
+		      }
 		  }
 		else
 		  {