On Tue, Jul 17, 2012 at 05:50:28PM +0200, Mark Wielaard wrote:
> The asserts seem too aggressive/wrong in this case. The following
> comment in elf32_getshdr.c (load_shdr_wrlock) explains them:
> 
>       /* All the data is already mapped.  If we could use it
>          directly this would already have happened.  */
> 
> But in the case of elf_cntl (ELF_CREAD) this has not yet happened,
> unless you already accessed the shdrs before that call.

I think the best solution is to just adjust the asserts to take this
into account. Which is what the attached patch does. It also includes
a testcase. Comments?

Thanks,

Mark
>From c82168e41ec929e42653b7d1b465b79ae6451174 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <[email protected]>
Date: Wed, 18 Jul 2012 13:14:30 +0200
Subject: [PATCH] elf_getshdr should work for elf->flags & ELF_F_MALLOCED.

Reported-by: Nick Alcock <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
---
 libelf/ChangeLog                   |    5 ++
 libelf/elf32_getshdr.c             |    9 ++-
 tests/ChangeLog                    |    8 +++
 tests/Makefile.am                  |    6 ++-
 tests/run-elf_cntl_gelf_getshdr.sh |   30 +++++++++++
 tests/test-elf_cntl_gelf_getshdr.c |  102 ++++++++++++++++++++++++++++++++++++
 6 files changed, 155 insertions(+), 5 deletions(-)
 create mode 100755 tests/run-elf_cntl_gelf_getshdr.sh
 create mode 100644 tests/test-elf_cntl_gelf_getshdr.c

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 89dd35f..1c1f7c8 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-19  Mark Wielaard  <[email protected]>
+
+       * elf32_getshdr.c (load_shdr_wrlock): Add elf->flags & ELF_F_MALLOCED
+       to asserts.
+
 2012-04-02  Mark Wielaard  <[email protected]>
 
        * elf32_offscn.c: Do not match SHT_NOBITS sections at OFFSET unless
diff --git a/libelf/elf32_getshdr.c b/libelf/elf32_getshdr.c
index f0319cb..6bd065b 100644
--- a/libelf/elf32_getshdr.c
+++ b/libelf/elf32_getshdr.c
@@ -80,11 +80,14 @@ load_shdr_wrlock (Elf_Scn *scn)
       ElfW2(LIBELFBITS,Shdr) *notcvt;
 
       /* All the data is already mapped.  If we could use it
-        directly this would already have happened.  */
+        directly this would already have happened.  Unless
+        we allocated the memory ourselves and the ELF_F_MALLOCED
+        flag is set.  */
       void *file_shdr = ((char *) elf->map_address
                         + elf->start_offset + ehdr->e_shoff);
 
-      assert (ehdr->e_ident[EI_DATA] != MY_ELFDATA
+      assert (elf->flags & ELF_F_MALLOCED
+             || ehdr->e_ident[EI_DATA] != MY_ELFDATA
              || (! ALLOW_UNALIGNED
                  && ((uintptr_t) file_shdr
                      & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
@@ -92,7 +95,7 @@ load_shdr_wrlock (Elf_Scn *scn)
       /* Now copy the data and at the same time convert the byte order.  */
       if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
        {
-         assert (! ALLOW_UNALIGNED);
+         assert (elf->flags & ELF_F_MALLOCED || ! ALLOW_UNALIGNED);
          memcpy (shdr, file_shdr, size);
        }
       else
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9d17c7e..2b0e806 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2012-07-19  Mark Wielaard  <[email protected]>
+
+       * Makefile.am (check_PROGRAMS): Add test-elf_cntl_gelf_getshdr.
+       (TESTS): Add run-elf_cntl_gelf_getshdr.sh.
+       (test_elf_cntl_gelf_getshdr_LDADD): New.
+       test-elf_cntl_gelf_getshdr.c: New test program.
+       run-elf_cntl_gelf_getshdr.sh: New test script.
+
 2012-06-26  Mike Frysinger  <[email protected]>
 
        * Makefile.am (check_PROGRAMS): Rename from noinst_PROGRAMS.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ae9839f..cb3df9f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -50,7 +50,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames 
sectiondump \
                  dwfl-addr-sect dwfl-bug-report early-offscn \
                  dwfl-bug-getmodules dwarf-getmacros addrcfi \
                  test-flag-nobits dwarf-getstring rerequest_tag \
-                 alldts md5-sha1-test typeiter low_high_pc
+                 alldts md5-sha1-test typeiter low_high_pc \
+                 test-elf_cntl_gelf_getshdr
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
            asm-tst6 asm-tst7 asm-tst8 asm-tst9
 
@@ -80,7 +81,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
        run-test-flag-nobits.sh run-prelink-addr-test.sh \
        run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh \
        run-readelf-d.sh run-unstrip-n.sh run-low_high_pc.sh \
-       run-macro-test.sh
+       run-macro-test.sh run-elf_cntl_gelf_getshdr.sh
 
 if !STANDALONE
 check_PROGRAMS += msg_tst md5-sha1-test
@@ -259,6 +260,7 @@ alldts_LDADD = $(libebl) $(libelf) $(libmudflap)
 md5_sha1_test_LDADD = $(libeu)
 typeiter_LDADD = $(libdw) $(libelf) $(libmudflap)
 low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap)
+test_elf_cntl_gelf_getshdr_LDADD = $(libelf) $(libmudflap)
 
 if GCOV
 check: check-am coverage
diff --git a/tests/run-elf_cntl_gelf_getshdr.sh 
b/tests/run-elf_cntl_gelf_getshdr.sh
new file mode 100755
index 0000000..41a7d15
--- /dev/null
+++ b/tests/run-elf_cntl_gelf_getshdr.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file 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; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# However we open the elf file, the shdrs should be the same.
+testrun ./test-elf_cntl_gelf_getshdr READ test-elf_cntl_gelf_getshdr \
+  > test_shdr.out
+
+testrun_compare ./test-elf_cntl_gelf_getshdr MMAP test-elf_cntl_gelf_getshdr \
+  < test_shdr.out
+
+testrun_compare ./test-elf_cntl_gelf_getshdr FDREAD test-elf_cntl_gelf_getshdr 
\
+  < test_shdr.out
+
+rm -f test_shdr.out
diff --git a/tests/test-elf_cntl_gelf_getshdr.c 
b/tests/test-elf_cntl_gelf_getshdr.c
new file mode 100644
index 0000000..9e4b417
--- /dev/null
+++ b/tests/test-elf_cntl_gelf_getshdr.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file 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; either version 3 of the License, or
+   (at your option) any later version.
+
+   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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 3)
+    {
+      fprintf (stderr, "Needs two arguments.\n");
+      fprintf (stderr, "First needs to be 'READ', 'MMAP' or 'FDREAD'\n");
+      fprintf (stderr, "Second is the ELF file to read.\n");
+      exit (-1);
+    }
+
+  bool do_mmap = false;
+  bool close_fd = false;
+  if (strcmp (argv[1], "READ") == 0)
+    {
+      do_mmap = false;
+      close_fd = false;
+    }
+  else if (strcmp (argv[1], "MMAP") == 0)
+    {
+      do_mmap = true;
+      close_fd = false;
+    }
+  else if  (strcmp (argv[1], "FDREAD") == 0)
+    {
+      do_mmap = false;
+      close_fd = true;
+    }
+  else
+    {
+      fprintf (stderr, "First arg needs to be 'READ', 'MMAP' or 'FDREAD'\n");
+      exit (-1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  int fd;
+  if ((fd = open (argv[2], O_RDONLY)) < 0)
+    {
+      fprintf (stderr, "Cannot open input file %s: %s\n", argv[2],
+              strerror (errno));
+      exit (-1);
+    }
+
+  Elf *elf = elf_begin (fd, do_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      fprintf (stderr, "elf_begin failed for %s: %s\n", argv[2],
+              elf_errmsg (-1));
+      exit (-1);
+    }
+
+  if (! do_mmap && close_fd)
+    {
+      if (elf_cntl (elf, ELF_C_FDREAD) < 0)
+       {
+         fprintf (stderr, "elf_cntl failed for %s: %s\n", argv[2],
+                  elf_errmsg (-1));
+         exit (-1);
+       }
+      close (fd);
+    }
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      printf ("Section at offset %#0" PRIx64 "\n", shdr->sh_offset);
+    }
+
+  elf_end (elf);
+}
-- 
1.7.7.6

_______________________________________________
elfutils-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/elfutils-devel

Reply via email to