The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=dbf05458e3bd8c46f5e49918593557293a29d41a

commit dbf05458e3bd8c46f5e49918593557293a29d41a
Author:     Mark Johnston <[email protected]>
AuthorDate: 2021-12-06 15:37:49 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2021-12-06 15:37:49 +0000

    libdwarf: Support consumption of compressed ELF sections
    
    Automatically decompress zlib-compressed debug sections when loading
    them.  This lets ctfcovert work on userland code after commit
    c910570e7573 ("Use compressed debug in standalone userland debug files
    by default").
    
    Reported by:    avg
    Reviewed by:    avg, emaste
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D33139
---
 contrib/elftoolchain/libdwarf/_libdwarf.h         |  5 +-
 contrib/elftoolchain/libdwarf/libdwarf.h          |  1 +
 contrib/elftoolchain/libdwarf/libdwarf_elf_init.c | 87 +++++++++++++++++++----
 lib/libdwarf/Makefile                             |  2 +-
 share/mk/src.libnames.mk                          |  2 +-
 5 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/contrib/elftoolchain/libdwarf/_libdwarf.h 
b/contrib/elftoolchain/libdwarf/_libdwarf.h
index 6658d2d2f6f4..68a4c61522fa 100644
--- a/contrib/elftoolchain/libdwarf/_libdwarf.h
+++ b/contrib/elftoolchain/libdwarf/_libdwarf.h
@@ -379,8 +379,9 @@ typedef struct _Dwarf_Rel_Section {
 } *Dwarf_Rel_Section;
 
 typedef struct {
-       Elf_Data *ed_data;
-       void *ed_alloc;
+       Elf_Data        *ed_data;
+       void            *ed_alloc;
+       size_t          ed_size;        /* Uncompressed size. */
 } Dwarf_Elf_Data;
 
 typedef struct {
diff --git a/contrib/elftoolchain/libdwarf/libdwarf.h 
b/contrib/elftoolchain/libdwarf/libdwarf.h
index 6ec8f99c56a1..b1f9e0c8abc7 100644
--- a/contrib/elftoolchain/libdwarf/libdwarf.h
+++ b/contrib/elftoolchain/libdwarf/libdwarf.h
@@ -335,6 +335,7 @@ enum {
        DW_DLE_ARANGE_OFFSET_BAD,       /* Invalid arange offset. */
        DW_DLE_DEBUG_MACRO_INCONSISTENT,/* Invalid macinfo data. */
        DW_DLE_ELF_SECT_ERR,            /* Application callback failed. */
+       DW_DLE_COMPRESSION,             /* Section decompression error. */
        DW_DLE_NUM                      /* Max error number. */
 };
 
diff --git a/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c 
b/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c
index e304ef164157..c9b6ae601e0e 100644
--- a/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c
+++ b/contrib/elftoolchain/libdwarf/libdwarf_elf_init.c
@@ -25,6 +25,7 @@
  */
 
 #include "_libdwarf.h"
+#include <zlib.h>
 
 ELFTC_VCSID("$Id: libdwarf_elf_init.c 3475 2016-05-18 18:11:26Z emaste $");
 
@@ -168,21 +169,28 @@ _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, 
Dwarf_Elf_Data *ed, size_t shndx,
                                        return (DW_DLE_NONE);
                        }
 
-                       ed->ed_alloc = malloc(ed->ed_data->d_size);
+                       /*
+                        * A copy may already have been created if the section
+                        * is compressed.
+                        */
                        if (ed->ed_alloc == NULL) {
-                               DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
-                               return (DW_DLE_MEMORY);
+                               ed->ed_alloc = malloc(ed->ed_size);
+                               if (ed->ed_alloc == NULL) {
+                                       DWARF_SET_ERROR(dbg, error,
+                                           DW_DLE_MEMORY);
+                                       return (DW_DLE_MEMORY);
+                               }
+                               memcpy(ed->ed_alloc, ed->ed_data->d_buf,
+                                   ed->ed_size);
                        }
-                       memcpy(ed->ed_alloc, ed->ed_data->d_buf,
-                           ed->ed_data->d_size);
                        if (sh.sh_type == SHT_REL)
                                _dwarf_elf_apply_rel_reloc(dbg,
-                                   ed->ed_alloc, ed->ed_data->d_size,
+                                   ed->ed_alloc, ed->ed_size,
                                    rel, symtab_data, eh.e_ident[EI_DATA]);
                        else
                                _dwarf_elf_apply_rela_reloc(dbg,
-                                   ed->ed_alloc, ed->ed_data->d_size,
-                                   rel, symtab_data, eh.e_ident[EI_DATA]);
+                                   ed->ed_alloc, ed->ed_size, rel, symtab_data,
+                                   eh.e_ident[EI_DATA]);
 
                        return (DW_DLE_NONE);
                }
@@ -196,13 +204,58 @@ _dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, 
Dwarf_Elf_Data *ed, size_t shndx,
        return (DW_DLE_NONE);
 }
 
+static int
+_dwarf_elf_decompress(Dwarf_Debug dbg, Dwarf_Elf_Object *e, Elf_Scn *scn,
+    Dwarf_Elf_Data *ed, GElf_Shdr *shdr, Dwarf_Error *error)
+{
+       GElf_Chdr chdr;
+       size_t hsize;
+       unsigned long csize;
+
+       if (gelf_getchdr(scn, &chdr) == NULL) {
+               DWARF_SET_ELF_ERROR(dbg, error);
+               return (DW_DLE_ELF);
+       }
+
+       if (chdr.ch_type != ELFCOMPRESS_ZLIB) {
+               DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
+               return (DW_DLE_COMPRESSION);
+       }
+
+       if ((ed->ed_alloc = malloc(chdr.ch_size)) == NULL) {
+               DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
+               return (DW_DLE_MEMORY);
+       }
+
+       csize = chdr.ch_size;
+       hsize = e->eo_ehdr.e_ident[EI_CLASS] == ELFCLASS64 ?
+           sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
+       if (uncompress(ed->ed_alloc, &csize, (char *)ed->ed_data->d_buf + hsize,
+           ed->ed_data->d_size - hsize) != Z_OK) {
+               DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
+               return (DW_DLE_COMPRESSION);
+       }
+       /* Sanity check. */
+       if (csize != chdr.ch_size) {
+               DWARF_SET_ERROR(dbg, error, DW_DLE_COMPRESSION);
+               return (DW_DLE_COMPRESSION);
+       }
+
+       ed->ed_size = chdr.ch_size;
+       shdr->sh_size = chdr.ch_size;
+       shdr->sh_addralign = chdr.ch_addralign;
+
+       return (DW_DLE_NONE);
+}
+
 int
 _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
 {
        Dwarf_Obj_Access_Interface *iface;
+       Dwarf_Elf_Data *ed;
        Dwarf_Elf_Object *e;
        const char *name;
-       GElf_Shdr sh;
+       GElf_Shdr *es, sh;
        Elf_Scn *scn;
        Elf_Data *symtab_data;
        size_t symtab_ndx;
@@ -319,8 +372,6 @@ _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error 
*error)
                if (sh.sh_type == SHT_NOBITS)
                        continue;
 
-               memcpy(&e->eo_shdr[j], &sh, sizeof(sh));
-
                if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
                    NULL) {
                        DWARF_SET_ELF_ERROR(dbg, error);
@@ -328,13 +379,15 @@ _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error 
*error)
                        goto fail_cleanup;
                }
 
+               ed = &e->eo_data[j];
+               es = &e->eo_shdr[j];
+               memcpy(es, &sh, sizeof(sh));
                for (i = 0; debug_name[i] != NULL; i++) {
                        if (strcmp(name, debug_name[i]))
                                continue;
 
                        (void) elf_errno();
-                       if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) ==
-                           NULL) {
+                       if ((ed->ed_data = elf_getdata(scn, NULL)) == NULL) {
                                elferr = elf_errno();
                                if (elferr != 0) {
                                        _DWARF_SET_ERROR(dbg, error,
@@ -344,6 +397,14 @@ _dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error 
*error)
                                }
                        }
 
+                       if ((sh.sh_flags & SHF_COMPRESSED) != 0) {
+                               if (_dwarf_elf_decompress(dbg, e, scn, ed,
+                                   es, error) != DW_DLE_NONE)
+                                       goto fail_cleanup;
+                       } else {
+                               ed->ed_size = ed->ed_data->d_size;
+                       }
+
                        if (_libdwarf.applyreloc) {
                                if (_dwarf_elf_relocate(dbg, elf,
                                    &e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
diff --git a/lib/libdwarf/Makefile b/lib/libdwarf/Makefile
index 03f40cdd85ee..a3ef95b2572a 100644
--- a/lib/libdwarf/Makefile
+++ b/lib/libdwarf/Makefile
@@ -98,7 +98,7 @@ sys/elf32.h sys/elf64.h sys/elf_common.h: 
${SRCTOP}/sys/${.TARGET} .NOMETA
        mkdir -p ${.OBJDIR}/sys
        ln -sf ${.ALLSRC} ${.TARGET}
 
-LIBADD+=       elf
+LIBADD+=       elf z
 
 SHLIB_MAJOR=   4
 
diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk
index bc3ad9c4bf40..23d09a434466 100644
--- a/share/mk/src.libnames.mk
+++ b/share/mk/src.libnames.mk
@@ -329,7 +329,7 @@ _DP_fetch=  ssl crypto
 _DP_fetch=     md
 .endif
 _DP_execinfo=  elf
-_DP_dwarf=     elf
+_DP_dwarf=     elf z
 _DP_dpv=       dialog figpar util tinfow ncursesw
 _DP_dialog=    tinfow ncursesw m
 _DP_cuse=      pthread

Reply via email to