This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils 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] gelf_offscn vs SHT_NOBITS


Hi,

While coming up with a test case for rhbz#807823 "elflint doesn't
recognize SHF_INFO_LINK on relocation sections", I came across another
issue. Not just with elflint, but also with readelf -d. If there is a
SHT_NOBITS section before the .dynamic section then gelf_offscn will
miss it. The solution is similar to commit e9c4e8 (Do not match empty
sections at OFFSET), skip SHT_NOBITS sections too if there is a "real"
section at the same offset that does have content. Does the solution
look sane?

The test binary is a testcase for both this issue and the original
rhbz#807823. Both tests fail before and succeed after the fixes.

Patch attached and in git on the mjw/offscn_nobits branch for those that
want to check out the test binary.

Cheers,

Mark

commit 191d1f0b9163593eee8c4f5cbe3e95cabf6ae9a9
Author: Mark Wielaard <mjw@redhat.com>
Date:   Mon Apr 2 17:11:25 2012 +0200

    elf32_offscn.c: Do not match SHT_NOBITS sections at OFFSET.
    
    readelf -d doesn't work if a SHT_NOBITS section is right before the actual
    .dynamic section at the same offset. elflint also fails on such binaries.
    So skip SHT_NOBITS sections at the same offset in [g]elf[32|64]_offscn().

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 19b76e8..89dd35f 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2012-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_offscn.c: Do not match SHT_NOBITS sections at OFFSET unless
+	there are no nonempty sections at that offset.
+
 2012-03-21  Roland McGrath  <roland@hack.frob.com>
 
 	* elf-knowledge.h (SECTION_STRIP_P): Remove < SHT_NUM check.
diff --git a/libelf/elf32_offscn.c b/libelf/elf32_offscn.c
index 86eff8b..5dcfc4a 100644
--- a/libelf/elf32_offscn.c
+++ b/libelf/elf32_offscn.c
@@ -101,7 +101,8 @@ elfw2(LIBELFBITS,offscn) (elf, offset)
 	    /* If this section is empty, the following one has the same
 	       sh_offset.  We presume the caller is looking for a nonempty
 	       section, so keep looking if this one is empty.  */
-	    if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_size != 0)
+	    if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_size != 0
+		&& runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_type != SHT_NOBITS)
 	      goto out;
 	  }
 
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 8d2b83f..6f6c592 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2012-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-readelf-d.sh.
+	(EXTRA_DIST): Add testlib_dynseg.so.bz2 and run-readelf-d.sh.
+	* run-readelf-d.sh: New test.
+	* run-elflint-test.sh: Check new testfile.
+
 2012-03-21  Tom Tromey  <tromey@redhat.com>
 
 	* typeiter.c: New file.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f2c211b..980aa12 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -86,7 +86,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-disasm-x86.sh run-disasm-x86-64.sh \
 	run-early-offscn.sh run-dwarf-getmacros.sh \
 	run-test-flag-nobits.sh run-prelink-addr-test.sh \
-	run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh
+	run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh \
+	run-readelf-d.sh
 # run-show-ciefde.sh
 
 if !STANDALONE
@@ -162,7 +163,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     testfile55-32.prelink.bz2 testfile55-64.bz2 \
 	     testfile55-64.debug.bz2 testfile55-64.prelink.bz2 \
 	     testfile56.bz2 testfile57.bz2 testfile58.bz2 \
-	     run-typeiter.sh testfile59.bz2
+	     run-typeiter.sh testfile59.bz2 \
+	     run-readelf-d.sh testlib_dynseg.so.bz2
 
 installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \
 			      bindir=$(DESTDIR)$(bindir) \
diff --git a/tests/run-elflint-test.sh b/tests/run-elflint-test.sh
index e0e1c54..0c872fe 100755
--- a/tests/run-elflint-test.sh
+++ b/tests/run-elflint-test.sh
@@ -44,4 +44,8 @@ testrun ../src/elflint -q --gnu-ld testfile42
 testfiles testfile46
 testrun ../src/elflint -q testfile46
 
+# see also run-readelf-d.sh
+testfiles testlib_dynseg.so
+testrun ../src/elflint -q --gnu-ld testlib_dynseg.so
+
 exit 0
diff --git a/tests/run-readelf-d.sh b/tests/run-readelf-d.sh
new file mode 100755
index 0000000..9022e70
--- /dev/null
+++ b/tests/run-readelf-d.sh
@@ -0,0 +1,78 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of Red Hat elfutils.
+#
+# Red Hat elfutils is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# Red Hat elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with Red Hat elfutils; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+#
+# Red Hat elfutils is an included package of the Open Invention Network.
+# An included package of the Open Invention Network is a package for which
+# Open Invention Network licensees cross-license their patents.  No patent
+# license is granted, either expressly or impliedly, by designation as an
+# included package.  Should you wish to participate in the Open Invention
+# Network licensing program, please visit www.openinventionnetwork.com
+# <http://www.openinventionnetwork.com>.
+
+. $srcdir/test-subr.sh
+
+# #include <stdio.h>
+# 
+# __thread int i;
+# 
+# void print_i ()
+# {
+#   printf("%d\n", i);
+# }
+#
+# gcc -fPIC -shared -o testlib_dynseg.so testlib_dynseg.c
+# With ld --version
+# GNU gold (GNU Binutils 2.22.52.20120402) 1.11
+
+testfiles testlib_dynseg.so
+
+testrun_compare ../src/readelf -d testlib_dynseg.so <<\EOF
+
+Dynamic segment contains 28 entries:
+ Addr: 0x00000000000017e0  Offset: 0x0007e0  Link to section: [ 3] '.dynstr'
+  Type              Value
+  PLTGOT            0x00000000000019c8
+  PLTRELSZ          72 (bytes)
+  JMPREL            0x0000000000000568
+  PLTREL            RELA
+  RELA              0x00000000000004d8
+  RELASZ            144 (bytes)
+  RELAENT           24 (bytes)
+  RELACOUNT         1
+  SYMTAB            0x0000000000000228
+  SYMENT            24 (bytes)
+  STRTAB            0x0000000000000360
+  STRSZ             190 (bytes)
+  GNU_HASH          0x0000000000000420
+  NEEDED            Shared library: [libc.so.6]
+  NEEDED            Shared library: [ld-linux-x86-64.so.2]
+  INIT              0x00000000000005b0
+  FINI              0x0000000000000748
+  VERSYM            0x0000000000000460
+  VERDEF            0x000000000000047c
+  VERDEFNUM         1
+  VERNEED           0x0000000000000498
+  VERNEEDNUM        2
+  NULL              
+  NULL              
+  NULL              
+  NULL              
+  NULL              
+  NULL              
+EOF
+
+exit 0
diff --git a/tests/testlib_dynseg.so.bz2 b/tests/testlib_dynseg.so.bz2
new file mode 100755
index 0000000..94296a4
Binary files /dev/null and b/tests/testlib_dynseg.so.bz2 differ

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