diff options
author | Doug Nazar <nazard@nazar.ca> | 2019-09-04 23:36:06 -0400 |
---|---|---|
committer | Dave Watson <dade.watson@gmail.com> | 2019-10-03 08:18:57 -0700 |
commit | a36ec8cfdb8764e4f8bf6b16a149a60ea6ad038d (patch) | |
tree | fbdf99561b77a53abef97428e6e60a842405b967 | |
parent | b316234d63c7ff6fcfac6d72e0f27394fe86af80 (diff) | |
download | libunwind-a36ec8cfdb8764e4f8bf6b16a149a60ea6ad038d.tar.gz |
Add support for zlib compressed elf .debug_frame sections
In case zlib support is not available, fail to load instead of
crashing while trying to read invalid data.
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/dwarf/Gfind_proc_info-lsb.c | 50 | ||||
-rw-r--r-- | src/unwind/libunwind.pc.in | 2 |
4 files changed, 67 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac index 8e62b8bd..11aeb2d2 100644 --- a/configure.ac +++ b/configure.ac @@ -302,6 +302,23 @@ fi AC_SUBST([LIBLZMA]) AM_CONDITIONAL(HAVE_LZMA, test x$enable_minidebuginfo = xyes) +LIBZ= +AC_MSG_CHECKING([whether to support ZLIB-compressed symbol tables]) +AC_ARG_ENABLE(zlibdebuginfo, +AS_HELP_STRING([--enable-zlibdebuginfo], [Enables support for ZLIB-compressed symbol tables]),, [enable_zlibdebuginfo=auto]) +AC_MSG_RESULT([$enable_zlibdebuginfo]) +if test x$enable_zlibdebuginfo != xno; then + AC_CHECK_LIB([z], [uncompress], + [LIBZ=-lz + AC_DEFINE([HAVE_ZLIB], [1], [Define if you have libz]) + enable_zlibdebuginfo=yes], + [if test x$enable_zlibdebuginfo = xyes; then + AC_MSG_FAILURE([libz not found]) + fi]) +fi +AC_SUBST([LIBZ]) +AM_CONDITIONAL(HAVE_ZLIB, test x$enable_zlibdebuginfo = xyes) + AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD]) AC_ARG_ENABLE([per-thread-cache], AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)])) diff --git a/src/Makefile.am b/src/Makefile.am index bc37b123..ff977446 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,7 +68,7 @@ libunwind_coredump_la_SOURCES = \ coredump/_UPT_resume.c libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ -version-info $(COREDUMP_SO_VERSION) -libunwind_coredump_la_LIBADD = $(LIBLZMA) +libunwind_coredump_la_LIBADD = $(LIBLZMA) $(LIBZ) noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h ### libunwind-setjmp: @@ -183,9 +183,9 @@ noinst_HEADERS += elf32.h elf64.h elfxx.h libunwind_elf32_la_SOURCES = elf32.c libunwind_elf64_la_SOURCES = elf64.c libunwind_elfxx_la_SOURCES = elfxx.c -libunwind_elf32_la_LIBADD = $(LIBLZMA) -libunwind_elf64_la_LIBADD = $(LIBLZMA) -libunwind_elfxx_la_LIBADD = $(LIBLZMA) +libunwind_elf32_la_LIBADD = $(LIBLZMA) $(LIBZ) +libunwind_elf64_la_LIBADD = $(LIBLZMA) $(LIBZ) +libunwind_elfxx_la_LIBADD = $(LIBLZMA) $(LIBZ) noinst_LTLIBRARIES += $(LIBUNWIND_ELF) libunwind_la_LIBADD += $(LIBUNWIND_ELF) @@ -732,7 +732,7 @@ endif libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -XCClinker -nostdlib \ $(LDFLAGS_STATIC_LIBCXA) -version-info $(SOVERSION) libunwind_la_LIBADD += -lc $(LIBCRTS) -libunwind_la_LIBADD += $(LIBLZMA) +libunwind_la_LIBADD += $(LIBLZMA) $(LIBZ) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I. AM_CCASFLAGS = $(AM_CPPFLAGS) diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 7d0c70f2..678c80bf 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -34,6 +34,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "dwarf-eh.h" #include "libunwind_i.h" +#ifdef HAVE_ZLIB +#include <zlib.h> +#endif /* HAVE_ZLIB */ + struct table_entry { int32_t start_ip_offset; @@ -123,14 +127,48 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) return 1; } - *bufsize = shdr->sh_size; - GET_MEMORY(*buf, *bufsize); - - memcpy(*buf, shdr->sh_offset + ei.image, *bufsize); + if (shdr->sh_flags & SHF_COMPRESSED) + { + unsigned long destSize; + Elf_W (Chdr) *chdr = (shdr->sh_offset + ei.image); +#ifdef HAVE_ZLIB + if (chdr->ch_type == ELFCOMPRESS_ZLIB) + { + *bufsize = destSize = chdr->ch_size; + GET_MEMORY(*buf, *bufsize); + ret = uncompress((unsigned char *)*buf, &destSize, + shdr->sh_offset + ei.image + sizeof(*chdr), + shdr->sh_size - sizeof(*chdr)); + if (ret != Z_OK) + { + Debug (2, "failed to decompress zlib .debug_frame, skipping\n"); + munmap(*buf, *bufsize); + munmap(ei.image, ei.size); + return 1; + } + + Debug (4, "read %zd->%zd bytes of .debug_frame from offset %zd\n", + shdr->sh_size, *bufsize, shdr->sh_offset); + } + else +#endif /* HAVE_ZLIB */ + { + Debug (2, "unknown compression type %d, skipping\n", + chdr->ch_type); + munmap(ei.image, ei.size); + return 1; + } + } + else + { + *bufsize = shdr->sh_size; + GET_MEMORY(*buf, *bufsize); - Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", - *bufsize, shdr->sh_offset); + memcpy(*buf, shdr->sh_offset + ei.image, *bufsize); + Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", + *bufsize, shdr->sh_offset); + } munmap(ei.image, ei.size); return 0; } diff --git a/src/unwind/libunwind.pc.in b/src/unwind/libunwind.pc.in index 1505c5d6..9a65faf3 100644 --- a/src/unwind/libunwind.pc.in +++ b/src/unwind/libunwind.pc.in @@ -7,5 +7,5 @@ Name: libunwind Description: libunwind base library Version: @VERSION@ Libs: -L${libdir} -lunwind -Libs.private: @LIBLZMA@ +Libs.private: @LIBLZMA@ @LIBZ@ Cflags: -I${includedir} |