From bcf8f79d6d2bec986e0a530e2f9b66efccf9bf83 Mon Sep 17 00:00:00 2001 From: naruse Date: Mon, 13 Aug 2018 06:20:12 +0000 Subject: [PATCH] support compressed debug_line re-commit r64328 https://blogs.oracle.com/solaris/elf_section_compression-v2 https://gnu.wildebeest.org/blog/mjw/2016/01/13/elf-libelf-compressed-sections-and-elfutils/ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64331 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- addr2line.c | 65 +++++++++++++++++++++++++++++++++++++++++++++------- configure.ac | 11 +++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/addr2line.c b/addr2line.c index fbe64758bc..eb15ef0bfc 100644 --- a/addr2line.c +++ b/addr2line.c @@ -101,8 +101,12 @@ void *alloca(); #define PATH_MAX 4096 #endif -#ifndef SHF_COMPRESSED /* compatibility with glibc < 2.22 */ -#define SHF_COMPRESSED 0 +#ifdef SHF_COMPRESSED +# ifdef HAVE_LIBZ +# include +# endif +#else /* compatibility with glibc < 2.22 */ +# define SHF_COMPRESSED 0 #endif PRINTF_ARGS(static int kprintf(const char *fmt, ...), 1, 2); @@ -478,6 +482,41 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces, fill_lines(num_traces, traces, 0, objp, lines, offset); } +static int +parse_compressed_debug_line(int num_traces, void **traces, + char *debug_line, unsigned long size, + obj_info_t *obj, line_info_t *lines, int offset) +{ + void *uncompressed_debug_line; + ElfW(Chdr) *chdr = (ElfW(Chdr) *)debug_line; + unsigned long destsize = chdr->ch_size; + int ret = 0; + + if (chdr->ch_type != ELFCOMPRESS_ZLIB) { + /* unsupported compression type */ + return -1; + } + + uncompressed_debug_line = malloc(destsize); + if (!uncompressed_debug_line) return -1; + ret = uncompress(uncompressed_debug_line, &destsize, + (const Bytef *)debug_line + sizeof(ElfW(Chdr)), size-sizeof(ElfW(Chdr))); + if (ret != Z_OK) { /* Z_OK = 0 */ + goto finish; + } + ret = parse_debug_line(num_traces, traces, + uncompressed_debug_line, + destsize, + obj, lines, offset); + if (ret) { + goto finish; + } + +finish: + free(uncompressed_debug_line); + return ret ? -1 : 0; +} + /* read file and fill lines */ static uintptr_t fill_lines(int num_traces, void **traces, int check_debuglink, @@ -644,12 +683,22 @@ fill_lines(int num_traces, void **traces, int check_debuglink, goto finish; } - if (!compressed_p && - parse_debug_line(num_traces, traces, - file + debug_line_shdr->sh_offset, - debug_line_shdr->sh_size, - obj, lines, offset)) - goto fail; + if (compressed_p) { +#ifdef HAVE_LIBZ + int r = parse_compressed_debug_line(num_traces, traces, + file + debug_line_shdr->sh_offset, + debug_line_shdr->sh_size, + obj, lines, offset); + if (r) goto fail; +#endif + } + else { + int r = parse_debug_line(num_traces, traces, + file + debug_line_shdr->sh_offset, + debug_line_shdr->sh_size, + obj, lines, offset); + if (r) goto fail; + } finish: return dladdr_fbase; fail: diff --git a/configure.ac b/configure.ac index c5baa8c980..30d6afa9ce 100644 --- a/configure.ac +++ b/configure.ac @@ -2451,6 +2451,9 @@ AS_IF([test "$rb_cv_binary_elf" = yes], [ AC_CHECK_HEADERS([elf.h elf_abi.h]) AS_IF([test $ac_cv_header_elf_h = yes -o $ac_cv_header_elf_abi_h = yes], [ AC_LIBOBJ([addr2line]) + AS_IF([test "x$compress_debug_sections" = xzlib], [ + AC_CHECK_LIB([z], [uncompress]) + ]) ]) ]) @@ -3067,7 +3070,11 @@ AS_CASE("$enable_shared", [yes], [ LIBRUBY_SO='lib$(RUBY_SO_NAME).$(SOEXT).$(MAJOR)' LIBRUBY_SONAME='lib$(RUBY_SO_NAME).$(SOEXT).$(RUBY_PROGRAM_VERSION)' LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)' - RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)']) + AS_IF([test "$GCC" = yes], [ + LIBRUBY_DLDFLAGS="$DLDFLAGS "'-Wl,-h,$(@F)' + ], [ + LIBRUBY_DLDFLAGS="$DLDFLAGS "'-h $(@F)' + ]) XLDFLAGS="$XLDFLAGS "'-R${libdir}' ], [hpux*], [ @@ -3314,7 +3321,7 @@ AS_CASE(["$target_os"], ]) ], [cygwin*|mingw*], [ - LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)' + LIBRUBY_DLDFLAGS="${DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)' AS_CASE(["$target_os"], [cygwin*], [ AS_IF([test x"$enable_shared" = xyes], [