summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-10-21 23:41:32 +0200
committerMark Wielaard <mark@klomp.org>2018-11-09 18:11:48 +0100
commitecbe3120cddb1b9597a19a68c4265e4f2c530444 (patch)
tree40f6549cda3aa5bff3df983f15ac88d0da597b72
parent4b0342b85b5b1a3d3636e06e3b5320954828dfb1 (diff)
libdwelf: New function dwelf_elf_begin.
This introduces a new function dwelf_elf_begin which creates a (read-only) ELF handle from a possibly compressed file handle or a file that start with a linux kernel header. This can be used in eu-readelf to (re)open a (pure) ELF. eu-readelf uses libdwfl to relocate addresses in the original file in case it is ET_REL. But to show the "raw" data it might need to (re)open the file. Which could fail if the file was compressed. And produced an obscure error message: "cannot create EBL handle". This rewrites __libdw_open_file a little so that the given file handle will never be closed (whether on success or failure) and introduces a new internal function __libdw_open_elf that dwelf_elf_begin wraps. Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r--libdw/ChangeLog4
-rw-r--r--libdw/libdw.map5
-rw-r--r--libdwelf/ChangeLog8
-rw-r--r--libdwelf/Makefile.am2
-rw-r--r--libdwelf/dwelf_elf_begin.c62
-rw-r--r--libdwelf/libdwelf.h10
-rw-r--r--libdwfl/ChangeLog8
-rw-r--r--libdwfl/libdwflP.h4
-rw-r--r--libdwfl/open.c30
-rw-r--r--src/ChangeLog7
-rw-r--r--src/readelf.c8
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/run-readelf-compressed.sh34
14 files changed, 174 insertions, 16 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 627fddeb..7caa2234 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-20 Mark Wielaard <mark@klomp.org>
+
+ * libdw.map (ELFUTILS_0.175): New section. Add dwelf_elf_begin.
+
2018-10-29 Milian Wolff <milian.wolff@kdab.com>
* dwarf_getcfi_elf.c (getcfi_shdr): Check sh_type != SHT_NOBITS.
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 3fef2ede..55482d58 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -356,3 +356,8 @@ ELFUTILS_0.173 {
global:
dwarf_next_lines;
} ELFUTILS_0.171;
+
+ELFUTILS_0.175 {
+ global:
+ dwelf_elf_begin;
+} ELFUTILS_0.173; \ No newline at end of file
diff --git a/libdwelf/ChangeLog b/libdwelf/ChangeLog
index ba921347..88be3421 100644
--- a/libdwelf/ChangeLog
+++ b/libdwelf/ChangeLog
@@ -1,9 +1,15 @@
+2018-10-21 Mark Wielaard <mark@klomp.org>
+
+ * libdwelf.h (dwelf_elf_begin): Add function declaration.
+ * dwelf_elf_begin.c: New file.
+ * Makefile.am (libdwelf_a_SOURCES): Add dwelf_elf_begin.c.
+
2018-10-18 Mark Wielaard <mark@klomp.org>
* dwelf_elf_gnu_build_id.c (find_elf_build_id): Check p_align to
set ELF type.
-2015-10-11 Akihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
+2016-10-11 Akihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
* dwelf_strtab.c: Remove sys/param.h include.
(MIN): Remove definition.
diff --git a/libdwelf/Makefile.am b/libdwelf/Makefile.am
index 7ca767a9..a7933fda 100644
--- a/libdwelf/Makefile.am
+++ b/libdwelf/Makefile.am
@@ -41,7 +41,7 @@ noinst_HEADERS = libdwelfP.h
libdwelf_a_SOURCES = dwelf_elf_gnu_debuglink.c dwelf_dwarf_gnu_debugaltlink.c \
dwelf_elf_gnu_build_id.c dwelf_scn_gnu_compressed_size.c \
- dwelf_strtab.c
+ dwelf_strtab.c dwelf_elf_begin.c
libdwelf = $(libdw)
diff --git a/libdwelf/dwelf_elf_begin.c b/libdwelf/dwelf_elf_begin.c
new file mode 100644
index 00000000..79825338
--- /dev/null
+++ b/libdwelf/dwelf_elf_begin.c
@@ -0,0 +1,62 @@
+/* Creates an ELF handle from a possibly compressed file descriptor.
+ Copyright (C) 2018 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 either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ 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 copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+#include "libdwflP.h"
+#include "libelfP.h"
+
+#include <unistd.h>
+
+Elf *
+dwelf_elf_begin (int fd)
+{
+ Elf *elf = NULL;
+ Dwfl_Error e = __libdw_open_elf (fd, &elf);
+ if (elf != NULL && elf_kind (elf) != ELF_K_NONE)
+ return elf;
+
+ /* Elf wasn't usable. Make sure there is a proper elf error message. */
+
+ if (elf != NULL)
+ elf_end (elf);
+
+ if (e != DWFL_E_LIBELF)
+ {
+ /* Force a bad ELF error. */
+ char badelf[EI_NIDENT] = { };
+ Elf *belf = elf_memory (badelf, EI_NIDENT);
+ elf32_getehdr (belf);
+ elf_end (belf);
+ }
+
+ return NULL;
+}
diff --git a/libdwelf/libdwelf.h b/libdwelf/libdwelf.h
index 72089dbf..6d491847 100644
--- a/libdwelf/libdwelf.h
+++ b/libdwelf/libdwelf.h
@@ -1,5 +1,5 @@
/* Interfaces for libdwelf. DWARF ELF Low-level Functions.
- Copyright (C) 2014, 2015, 2016 Red Hat, Inc.
+ Copyright (C) 2014, 2015, 2016, 2018 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -125,6 +125,14 @@ extern const char *dwelf_strent_str (Dwelf_Strent *se)
extern void dwelf_strtab_free (Dwelf_Strtab *st)
__nonnull_attribute__ (1);
+/* Creates a read-only Elf handle from the given file handle. The
+ file may be compressed and/or contain a linux kernel image header,
+ in which case it is eagerly decompressed in full and the Elf handle
+ is created as if created with elf_memory (). On error NULL is
+ returned. The Elf handle should be closed with elf_end (). The
+ file handle will not be closed. Does not return ELF_K_NONE handles. */
+extern Elf *dwelf_elf_begin (int fd);
+
#ifdef __cplusplus
}
#endif
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 9e7bb316..45cc1b4e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,11 @@
+2018-10-20 Mark Wielaard <mark@klomp.org>
+
+ * libdwflP.h (__libdw_open_elf): New internal function declaration.
+ * open.c (what_kind): Rename close_fd to may_close_fd.
+ (__libdw_open_file): Replaced (and renamed) by a call to ...
+ (libdw_open_elf): this. And add never_close_fd argument.
+ (__libdw_open_elf): New function that calls libdw_open_elf.
+
2018-10-18 Mark Wielaard <mark@klomp.org>
* dwfl_segment_report_module.c (consider_note): Take align as new
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 31e6e190..941a8b66 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -626,6 +626,10 @@ extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
bool close_on_fail, bool archive_ok)
internal_function;
+/* Same as __libdw_open_file, but never closes the given file
+ descriptor and ELF_K_AR is always an acceptable type. */
+extern Dwfl_Error __libdw_open_elf (int fd, Elf **elfp) internal_function;
+
/* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP. Return success.
*VADDRP is not modified if the function fails. */
extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
diff --git a/libdwfl/open.c b/libdwfl/open.c
index 4e0461bd..74367359 100644
--- a/libdwfl/open.c
+++ b/libdwfl/open.c
@@ -95,7 +95,7 @@ decompress (int fd __attribute__ ((unused)), Elf **elf)
}
static Dwfl_Error
-what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *close_fd)
+what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *may_close_fd)
{
Dwfl_Error error = DWFL_E_NOERROR;
*kind = elf_kind (*elfp);
@@ -108,7 +108,7 @@ what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *close_fd)
error = decompress (fd, elfp);
if (error == DWFL_E_NOERROR)
{
- *close_fd = true;
+ *may_close_fd = true;
*kind = elf_kind (*elfp);
}
}
@@ -116,15 +116,16 @@ what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *close_fd)
return error;
}
-Dwfl_Error internal_function
-__libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
+static Dwfl_Error
+libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
+ bool never_close_fd)
{
- bool close_fd = false;
+ bool may_close_fd = false;
Elf *elf = elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL);
Elf_Kind kind;
- Dwfl_Error error = what_kind (*fdp, &elf, &kind, &close_fd);
+ Dwfl_Error error = what_kind (*fdp, &elf, &kind, &may_close_fd);
if (error == DWFL_E_BADELF)
{
/* It's not an ELF file or a compressed file.
@@ -153,7 +154,7 @@ __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
elf->flags &= ~(ELF_F_MMAPPED | ELF_F_MALLOCED);
elf_end (elf);
elf = subelf;
- error = what_kind (*fdp, &elf, &kind, &close_fd);
+ error = what_kind (*fdp, &elf, &kind, &may_close_fd);
}
}
}
@@ -169,7 +170,8 @@ __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
elf = NULL;
}
- if (error == DWFL_E_NOERROR ? close_fd : close_on_fail)
+ if (! never_close_fd
+ && error == DWFL_E_NOERROR ? may_close_fd : close_on_fail)
{
close (*fdp);
*fdp = -1;
@@ -178,3 +180,15 @@ __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
*elfp = elf;
return error;
}
+
+Dwfl_Error internal_function
+__libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
+{
+ return libdw_open_elf (fdp, elfp, close_on_fail, archive_ok, false);
+}
+
+Dwfl_Error internal_function
+__libdw_open_elf (int fd, Elf **elfp)
+{
+ return libdw_open_elf (&fd, elfp, false, true, true);
+}
diff --git a/src/ChangeLog b/src/ChangeLog
index 79e6872a..f1a35798 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-20 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (process_elf_file): Use dwelf_elf_begin to open pure_elf.
+
2018-10-26 Mark Wielaard <mark@klomp.org>
* strip.c (OPT_RELOC_DEBUG_ONLY): New define.
@@ -93,11 +97,10 @@
* findtextrel.c (process_file): Check that sh_entsize is not zero.
-2018-09-13 Mark Wielaard <mark@klomp.org>
+2018-10-13 Mark Wielaard <mark@klomp.org>
* readelf.c (print_debug_macro_section): Use elf_getdata. Print
decoded flag string.
-2018-09-13 Mark Wielaard <mark@klomp.org>
2018-10-19 Mark Wielaard <mark@klomp.org>
diff --git a/src/readelf.c b/src/readelf.c
index ccd07eb7..c6c3fb32 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -905,7 +905,6 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
if (ehdr == NULL)
{
- elf_error:
error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
return;
}
@@ -948,7 +947,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
{
/* Read the file afresh. */
off_t aroff = elf_getaroff (elf);
- pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+ pure_elf = dwelf_elf_begin (fd);
if (aroff > 0)
{
/* Archive member. */
@@ -958,7 +957,10 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
pure_elf = armem;
}
if (pure_elf == NULL)
- goto elf_error;
+ {
+ error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
+ return;
+ }
pure_ebl = ebl_openbackend (pure_elf);
if (pure_ebl == NULL)
goto ebl_error;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 7ce39808..b0da4c79 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2018-10-20 Mark Wielaard <mark@klomp.org>
+
+ * run-readelf-compressed.sh: New test.
+ * Makefile.am (TESTS): Add run-readelf-compressed.sh.
+ (EXTRA_DIST): Likewise.
+
2018-11-09 Mark Wielaard <mark@klomp.org>
* testfile-debug-rel-ppc64-g.o.bz2: New test file.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d3ac345d..ac467d93 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -100,6 +100,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
run-find-prologues.sh run-allregs.sh run-addrcfi.sh \
run-dwarfcfi.sh \
run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
+ run-readelf-compressed.sh \
run-readelf-const-values.sh \
run-varlocs-self.sh run-exprlocs-self.sh \
run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
@@ -216,6 +217,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
+ run-readelf-compressed.sh \
run-readelf-const-values.sh testfile-const-values.debug.bz2 \
run-addrcfi.sh run-dwarfcfi.sh \
testfile11-debugframe.bz2 testfile12-debugframe.bz2 \
diff --git a/tests/run-readelf-compressed.sh b/tests/run-readelf-compressed.sh
new file mode 100755
index 00000000..a2a04a2a
--- /dev/null
+++ b/tests/run-readelf-compressed.sh
@@ -0,0 +1,34 @@
+#! /bin/sh
+# Copyright (C) 2018 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
+
+# See run-strip-reloc.sh
+testfiles hello_i386.ko
+
+tempfiles hello_i386.ko.bz2 readelf.out.1 readelf.out.2
+
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko > readelf.out.1
+bzip2 hello_i386.ko
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko.bz2 > readelf.out.2
+
+diff -u readelf.out.1 readelf.out.2
+if [ $? != 0 ]; then
+ exit 1;
+fi
+
+exit 0