aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McKellar <ianloic@google.com>2023-07-26 18:55:57 +0000
committerJoshua Peraza <jperaza@chromium.org>2023-07-27 18:14:10 +0000
commit9ea5b228f560580f85df895c2f117d7e43340935 (patch)
tree81a2f61f7dfa065319fccd3b4424ab62c95d826d
parent7a1a190f4f68e8a3e06788498f50a4d5520a69f3 (diff)
downloadgoogle-breakpad-9ea5b228f560580f85df895c2f117d7e43340935.tar.gz
Add support for zstd compressed sections to dump_syms
Support for zstd must be enabled by passing --enable-zstd to configure. Change-Id: I57d0196552284de86575d979d673ac20a3fc4d64 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4722191 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
-rw-r--r--Makefile.am8
-rw-r--r--Makefile.in4
-rwxr-xr-xconfigure74
-rw-r--r--configure.ac11
-rw-r--r--src/common/linux/dump_symbols.cc45
-rw-r--r--src/config.h.in3
6 files changed, 134 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am
index 58e41483..06f34ce8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -694,9 +694,11 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/linux/safe_readlink.cc \
src/tools/linux/dump_syms/dump_syms.cc
src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
- $(RUSTC_DEMANGLE_CFLAGS)
+ $(RUSTC_DEMANGLE_CFLAGS) \
+ $(ZSTD_CFLAGS)
src_tools_linux_dump_syms_dump_syms_LDADD = \
$(RUSTC_DEMANGLE_LIBS) \
+ $(ZSTD_CFLAGS) \
-lz
src_tools_linux_md2core_minidump_2_core_SOURCES = \
@@ -821,11 +823,13 @@ src_common_dumper_unittest_SOURCES = \
src_common_dumper_unittest_CPPFLAGS = \
$(AM_CPPFLAGS) $(TEST_CFLAGS) \
$(RUSTC_DEMANGLE_CFLAGS) \
- $(PTHREAD_CFLAGS)
+ $(PTHREAD_CFLAGS) \
+ $(ZSTD_CFLAGS)
src_common_dumper_unittest_LDADD = \
$(TEST_LIBS) \
$(RUSTC_DEMANGLE_LIBS) \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
+ $(ZSTD_LIBS) \
-lz
src_common_mac_macho_reader_unittest_SOURCES = \
diff --git a/Makefile.in b/Makefile.in
index 641226a0..0c47bf87 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2695,7 +2695,7 @@ src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
src_tools_linux_dump_syms_dump_syms_LDADD = \
$(RUSTC_DEMANGLE_LIBS) \
- -lz
+ -lz -lzstd
src_tools_linux_md2core_minidump_2_core_SOURCES = \
src/common/linux/memory_mapped_file.cc \
@@ -2828,7 +2828,7 @@ src_common_dumper_unittest_LDADD = \
$(TEST_LIBS) \
$(RUSTC_DEMANGLE_LIBS) \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
- -lz
+ -lz -lzstd
src_common_mac_macho_reader_unittest_SOURCES = \
src/common/dwarf_cfi_to_module.cc \
diff --git a/configure b/configure
index fb84fb0d..3442e796 100755
--- a/configure
+++ b/configure
@@ -810,6 +810,7 @@ enable_system_test_libs
enable_selftest
with_rustc_demangle
enable_system_rustc_demangle
+enable_zstd
with_tests_as_root
'
ac_precious_vars='build_alias
@@ -1483,6 +1484,7 @@ Optional Features:
is no). This assumes that rustc-demangle is
installed in your sysroot, and all headers from it
are available in your standard include path
+ --enable-zstd Enable decompression of ELF sections with zstd
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -6594,11 +6596,11 @@ if test x$ac_prog_cxx_stdcxx = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
printf %s "checking for $CXX option to enable C++11 features... " >&6; }
-if test ${ac_cv_prog_cxx_11+y}
+if test ${ac_cv_prog_cxx_cxx11+y}
then :
printf %s "(cached) " >&6
else $as_nop
- ac_cv_prog_cxx_11=no
+ ac_cv_prog_cxx_cxx11=no
ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -6640,11 +6642,11 @@ if test x$ac_prog_cxx_stdcxx = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
printf %s "checking for $CXX option to enable C++98 features... " >&6; }
-if test ${ac_cv_prog_cxx_98+y}
+if test ${ac_cv_prog_cxx_cxx98+y}
then :
printf %s "(cached) " >&6
else $as_nop
- ac_cv_prog_cxx_98=no
+ ac_cv_prog_cxx_cxx98=no
ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10504,6 +10506,70 @@ fi
+# Check whether --enable-zstd was given.
+if test ${enable_zstd+y}
+then :
+ enableval=$enable_zstd;
+else $as_nop
+ enable_zstd=no
+fi
+
+if test "x${enable_zstd}" != xno; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ZSTD_decompress in -lzstd" >&5
+printf %s "checking for ZSTD_decompress in -lzstd... " >&6; }
+if test ${ac_cv_lib_zstd_ZSTD_decompress+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lzstd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char ZSTD_decompress ();
+int
+main (void)
+{
+return ZSTD_decompress ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_zstd_ZSTD_decompress=yes
+else $as_nop
+ ac_cv_lib_zstd_ZSTD_decompress=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zstd_ZSTD_decompress" >&5
+printf "%s\n" "$ac_cv_lib_zstd_ZSTD_decompress" >&6; }
+if test "x$ac_cv_lib_zstd_ZSTD_decompress" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBZSTD 1" >>confdefs.h
+
+ LIBS="-lzstd $LIBS"
+
+else $as_nop
+ as_fn_error $? "zstd library not found." "$LINENO" 5
+fi
+
+ ac_fn_c_check_header_compile "$LINENO" "zstd.h" "ac_cv_header_zstd_h" "$ac_includes_default"
+if test "x$ac_cv_header_zstd_h" = xyes
+then :
+
+else $as_nop
+ as_fn_error $? "zstd header not found." "$LINENO" 5
+fi
+
+fi
+
# Check whether --with-tests-as-root was given.
if test ${with_tests_as_root+y}
diff --git a/configure.ac b/configure.ac
index 1d53bc61..bfee372a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -212,6 +212,17 @@ fi
AC_ARG_VAR([RUSTC_DEMANGLE_CFLAGS], [Compiler flags for rustc-demangle])
AC_ARG_VAR([RUSTC_DEMANGLE_LIBS], [Linker flags for rustc-demangle])
+AC_ARG_ENABLE(zstd,
+ AS_HELP_STRING([--enable-zstd],
+ [Enable decompression of ELF sections with zstd]),,
+ [enable_zstd=no])
+if test "x${enable_zstd}" != xno; then
+ AC_CHECK_LIB(zstd, ZSTD_decompress, [],
+ [AC_MSG_ERROR([zstd library not found.])])
+ AC_CHECK_HEADER(zstd.h, [],
+ [AC_MSG_ERROR([zstd header not found.])])
+fi
+
AC_ARG_WITH(tests-as-root,
AS_HELP_STRING([--with-tests-as-root],
[Run the tests as root. Use this on platforms]
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index 86c948d9..b693fc9e 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -51,6 +51,9 @@
#include <sys/stat.h>
#include <unistd.h>
#include <zlib.h>
+#ifdef HAVE_LIBZSTD
+#include <zstd.h>
+#endif
#include <set>
#include <string>
@@ -108,6 +111,11 @@ using google_breakpad::wasteful_vector;
#define EM_AARCH64 183
#endif
+// Define ZStd compression if host machine does not include this define.
+#ifndef ELFCOMPRESS_ZSTD
+#define ELFCOMPRESS_ZSTD 2
+#endif
+
//
// FDWrapper
//
@@ -305,7 +313,7 @@ uint32_t GetCompressionHeader(
return sizeof (*header);
}
-std::pair<uint8_t *, uint64_t> UncompressSectionContents(
+std::pair<uint8_t *, uint64_t> UncompressZlibSectionContents(
const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) {
z_stream stream;
memset(&stream, 0, sizeof stream);
@@ -334,6 +342,37 @@ std::pair<uint8_t *, uint64_t> UncompressSectionContents(
: std::make_pair(uncompressed_buffer.release(), uncompressed_size);
}
+#ifdef HAVE_LIBZSTD
+std::pair<uint8_t *, uint64_t> UncompressZstdSectionContents(
+ const uint8_t* compressed_buffer, uint64_t compressed_size,uint64_t uncompressed_size) {
+
+ google_breakpad::scoped_array<uint8_t> uncompressed_buffer(new uint8_t[uncompressed_size]);
+ size_t out_size = ZSTD_decompress(uncompressed_buffer.get(), uncompressed_size,
+ compressed_buffer, compressed_size);
+ if (ZSTD_isError(out_size)) {
+ return std::make_pair(nullptr, 0);
+ }
+ assert(out_size == uncompressed_size);
+ return std::make_pair(uncompressed_buffer.release(), uncompressed_size);
+}
+#endif
+
+std::pair<uint8_t *, uint64_t> UncompressSectionContents(
+ uint64_t compression_type, const uint8_t* compressed_buffer,
+ uint64_t compressed_size, uint64_t uncompressed_size) {
+ if (compression_type == ELFCOMPRESS_ZLIB) {
+ return UncompressZlibSectionContents(compressed_buffer, compressed_size, uncompressed_size);
+ }
+
+#ifdef HAVE_LIBZSTD
+ if (compression_type == ELFCOMPRESS_ZSTD) {
+ return UncompressZstdSectionContents(compressed_buffer, compressed_size, uncompressed_size);
+ }
+#endif
+
+ return std::make_pair(nullptr, 0);
+}
+
void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
Module* module,
google_breakpad::Endianness endianness,
@@ -437,7 +476,7 @@ bool LoadDwarf(const string& dwarf_filename,
size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed =
- UncompressSectionContents(contents, size, chdr.ch_size);
+ UncompressSectionContents(chdr.ch_type, contents, size, chdr.ch_size);
if (uncompressed.first != nullptr && uncompressed.second != 0) {
file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second);
@@ -587,7 +626,7 @@ bool LoadDwarfCFI(const string& dwarf_filename,
cfi_size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed =
- UncompressSectionContents(cfi, cfi_size, chdr.ch_size);
+ UncompressSectionContents(chdr.ch_type, cfi, cfi_size, chdr.ch_size);
if (uncompressed.first == nullptr || uncompressed.second == 0) {
fprintf(stderr, "%s: decompression failed\n", dwarf_filename.c_str());
diff --git a/src/config.h.in b/src/config.h.in
index 8fd7b0aa..9a4eb0de 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -21,6 +21,9 @@
/* Define to 1 if you have the `rustc_demangle' library (-lrustc_demangle). */
#undef HAVE_LIBRUSTC_DEMANGLE
+/* Define to 1 if you have the `zstd' library (-lzstd). */
+#undef HAVE_LIBZSTD
+
/* Define to 1 if you have the `memfd_create' function. */
#undef HAVE_MEMFD_CREATE