]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwelf: Make dwelf_elf_begin return NULL only when there is an error.
authorMark Wielaard <mark@klomp.org>
Sun, 11 Aug 2019 22:43:22 +0000 (00:43 +0200)
committerMark Wielaard <mark@klomp.org>
Tue, 13 Aug 2019 10:16:18 +0000 (12:16 +0200)
dwelf_elf_begin was slightly different from elf_begin in case the file
turned out to not be an ELF file. elf_begin would return an Elf handle
with ELF_K_NONE. But dwelf_elf_begin would return NULL. This made it
impossible to tell the difference between a file or decompression error
and a (decompressed) file not being an ELF file.

Since dwelf_elf_begin could still return different kinds of ELF files
(ELF_K_ELF or ELF_K_AR - and theoretically ELF_K_COFF) this was not
really useful anyway. So make it so that dwelf_elf_begin always returns
an Elf handle unless there was a real error reading or decompressing
the file. Otherwise return NULL to make clear there was a real error.

Make sure that the decompression function returns DWFL_E_BADELF only
when the file isn't compressed. In which case the Elf handle won't
be replaced and can be returned (as ELF_K_NONE).

Add a new version to dwelf_elf_begin so programs can rely on it
returning NULL only for real errors.

Signed-off-by: Mark Wielaard <mark@klomp.org>
libdw/ChangeLog
libdw/libdw.map
libdwelf/ChangeLog
libdwelf/dwelf_elf_begin.c
libdwelf/libdwelf.h
libdwfl/ChangeLog
libdwfl/gzip.c
libdwfl/open.c

index 6b779e7778621929bf71d7ad0f852aff39aa9ee6..bf1f4857e3ed3f663e8b85d30380b94d04c8cfe6 100644 (file)
@@ -1,3 +1,7 @@
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+       * libdw.map (ELFUTILS_0.177): Add new version of dwelf_elf_begin.
+
 2019-06-28  Mark Wielaard  <mark@klomp.org>
 
        * libdw.map (ELFUTILS_0.177): New section. Add
index 2e1c0e9eedfd9b2a6a130936250e47c06c7d0bff..decac05c7c973237a4856553f55b3fef07d22d9b 100644 (file)
@@ -365,4 +365,8 @@ ELFUTILS_0.175 {
 ELFUTILS_0.177 {
   global:
     dwelf_elf_e_machine_string;
+    # Replaced ELFUTILS_0.175 versions.  Both versions point to the
+    # same implementation, but users of the new symbol version can
+    # presume that NULL is only returned on error (otherwise ELF_K_NONE).
+    dwelf_elf_begin;
 } ELFUTILS_0.175;
index 29f9a509e13003b19ec454ae7f9c562468982ce1..5b48ed8f6e044528b71550d77c8aa2282455fb15 100644 (file)
@@ -1,3 +1,9 @@
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+       * libdwelf.h (dwelf_elf_begin): Update documentation.
+       * dwelf_elf_begin.c (dwelf_elf_begin): Don't suppress ELF_K_NONE.
+       Mark old and new version.
+
 2019-06-28  Mark Wielaard  <mark@klomp.org>
 
        * Makefile.am (libdwelf_a_SOURCES): Add dwelf_elf_e_machine_string.c.
index 79825338300af883cb6eb7af7ddcd409b090bca5..c7d63a1c214ea029fa14adbe05931fb4fcb4129a 100644 (file)
@@ -41,13 +41,13 @@ 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)
+  if (e == DWFL_E_NOERROR)
     return elf;
 
-  /* Elf wasn't usable.  Make sure there is a proper elf error message.  */
-
-  if (elf != NULL)
-    elf_end (elf);
+  /* Elf wasn't usable.  Make sure there is a proper elf error
+     message.  This is probably not the real error, because there is
+     no good way to propagate errnos or decompression errors, but
+     better than nothing.  */
 
   if (e != DWFL_E_LIBELF)
     {
@@ -60,3 +60,5 @@ dwelf_elf_begin (int fd)
 
   return NULL;
 }
+OLD_VERSION (dwelf_elf_begin, ELFUTILS_0.175)
+NEW_VERSION (dwelf_elf_begin, ELFUTILS_0.177)
index cb7ea091d32e42834e0968de87f7b70ddd04fa7a..dbb8f08cf05403a4723b06e86298a67b5198b420 100644 (file)
@@ -128,9 +128,12 @@ extern void dwelf_strtab_free (Dwelf_Strtab *st)
 /* 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.  */
+   is created as if created with elf_memory ().  On decompression or
+   file errors NULL is returned (and elf_errno will be set).  If there
+   was no error, but the file is not an ELF file, then an ELF_K_NONE
+   Elf handle is returned (just like with elf_begin).  The Elf handle
+   should be closed with elf_end ().  The file handle will not be
+   closed.  */
 extern Elf *dwelf_elf_begin (int fd);
 
 /* Returns a human readable string for the given ELF header e_machine
index 8cbe90c95d00d470ac0b0acdecbbed404a590eae..04a39637e9a4b5dc925bf1551e9b8ae13fc16194 100644 (file)
@@ -1,3 +1,11 @@
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+       * gzip.c (open_stream): Return DWFL_E_ERRNO on bad file operation.
+       * open.c (libdw_open_elf): New argument bad_elf_ok. Check it and
+       return DWFL_E_NOERROR in case it is set and error was DWFL_E_BADELF.
+       (__libdw_open_file): Call libdw_open_elf with bad_elf_ok false.
+       (__libdw_open_elf): Call libdw_open_elf with bad_elf_ok true.
+
 2019-08-05  Omar Sandoval  <osandov@fb.com>
 
        * dwfl_segment_report_module.c (dwfl_segment_report_module): Assign
index c2c13bafb50fc1a1743e9591e282ae40e482ceb9..043d0b6ed5832c5e1b106dd93395f13d2a593981 100644 (file)
@@ -139,14 +139,14 @@ open_stream (int fd, off_t start_offset, struct unzip_state *state)
 {
     int d = dup (fd);
     if (unlikely (d < 0))
-      return DWFL_E_BADELF;
+      return DWFL_E_ERRNO;
     if (start_offset != 0)
       {
        off_t off = lseek (d, start_offset, SEEK_SET);
        if (off != start_offset)
          {
            close (d);
-           return DWFL_E_BADELF;
+           return DWFL_E_ERRNO;
          }
       }
     state->zf = gzdopen (d, "r");
@@ -288,6 +288,7 @@ unzip (int fd, off_t start_offset,
   if (result == DWFL_E_NOERROR && gzdirect (state.zf))
     {
       gzclose (state.zf);
+      /* Not a compressed stream after all.  */
       return fail (&state, DWFL_E_BADELF);
     }
 
index 74367359418ee33f72a3ba6f755f6d08d7fe31d9..35fc5283661a873d5e1b1eb0f201094c44e4a9a0 100644 (file)
@@ -118,7 +118,7 @@ what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *may_close_fd)
 
 static Dwfl_Error
 libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
-               bool never_close_fd)
+               bool never_close_fd, bool bad_elf_ok)
 {
   bool may_close_fd = false;
 
@@ -164,6 +164,10 @@ libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
       && !(archive_ok && kind == ELF_K_AR))
     error = DWFL_E_BADELF;
 
+  /* This basically means, we keep a ELF_K_NONE Elf handle and return it.  */
+  if (bad_elf_ok && error == DWFL_E_BADELF)
+    error = DWFL_E_NOERROR;
+
   if (error != DWFL_E_NOERROR)
     {
       elf_end (elf);
@@ -184,11 +188,11 @@ libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
 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);
+  return libdw_open_elf (fdp, elfp, close_on_fail, archive_ok, false, false);
 }
 
 Dwfl_Error internal_function
 __libdw_open_elf (int fd, Elf **elfp)
 {
-  return libdw_open_elf (&fd, elfp, false, true, true);
+  return libdw_open_elf (&fd, elfp, false, true, true, true);
 }