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>
This commit is contained in:
Ian McKellar 2023-07-26 18:55:57 +00:00 committed by Joshua Peraza
parent 7a1a190f4f
commit 9ea5b228f5
6 changed files with 134 additions and 11 deletions

View file

@ -694,9 +694,11 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/linux/safe_readlink.cc \ src/common/linux/safe_readlink.cc \
src/tools/linux/dump_syms/dump_syms.cc src/tools/linux/dump_syms/dump_syms.cc
src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \ src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
$(RUSTC_DEMANGLE_CFLAGS) $(RUSTC_DEMANGLE_CFLAGS) \
$(ZSTD_CFLAGS)
src_tools_linux_dump_syms_dump_syms_LDADD = \ src_tools_linux_dump_syms_dump_syms_LDADD = \
$(RUSTC_DEMANGLE_LIBS) \ $(RUSTC_DEMANGLE_LIBS) \
$(ZSTD_CFLAGS) \
-lz -lz
src_tools_linux_md2core_minidump_2_core_SOURCES = \ src_tools_linux_md2core_minidump_2_core_SOURCES = \
@ -821,11 +823,13 @@ src_common_dumper_unittest_SOURCES = \
src_common_dumper_unittest_CPPFLAGS = \ src_common_dumper_unittest_CPPFLAGS = \
$(AM_CPPFLAGS) $(TEST_CFLAGS) \ $(AM_CPPFLAGS) $(TEST_CFLAGS) \
$(RUSTC_DEMANGLE_CFLAGS) \ $(RUSTC_DEMANGLE_CFLAGS) \
$(PTHREAD_CFLAGS) $(PTHREAD_CFLAGS) \
$(ZSTD_CFLAGS)
src_common_dumper_unittest_LDADD = \ src_common_dumper_unittest_LDADD = \
$(TEST_LIBS) \ $(TEST_LIBS) \
$(RUSTC_DEMANGLE_LIBS) \ $(RUSTC_DEMANGLE_LIBS) \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
$(ZSTD_LIBS) \
-lz -lz
src_common_mac_macho_reader_unittest_SOURCES = \ src_common_mac_macho_reader_unittest_SOURCES = \

View file

@ -2695,7 +2695,7 @@ src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
src_tools_linux_dump_syms_dump_syms_LDADD = \ src_tools_linux_dump_syms_dump_syms_LDADD = \
$(RUSTC_DEMANGLE_LIBS) \ $(RUSTC_DEMANGLE_LIBS) \
-lz -lz -lzstd
src_tools_linux_md2core_minidump_2_core_SOURCES = \ src_tools_linux_md2core_minidump_2_core_SOURCES = \
src/common/linux/memory_mapped_file.cc \ src/common/linux/memory_mapped_file.cc \
@ -2828,7 +2828,7 @@ src_common_dumper_unittest_LDADD = \
$(TEST_LIBS) \ $(TEST_LIBS) \
$(RUSTC_DEMANGLE_LIBS) \ $(RUSTC_DEMANGLE_LIBS) \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
-lz -lz -lzstd
src_common_mac_macho_reader_unittest_SOURCES = \ src_common_mac_macho_reader_unittest_SOURCES = \
src/common/dwarf_cfi_to_module.cc \ src/common/dwarf_cfi_to_module.cc \

74
configure vendored
View file

@ -810,6 +810,7 @@ enable_system_test_libs
enable_selftest enable_selftest
with_rustc_demangle with_rustc_demangle
enable_system_rustc_demangle enable_system_rustc_demangle
enable_zstd
with_tests_as_root with_tests_as_root
' '
ac_precious_vars='build_alias ac_precious_vars='build_alias
@ -1483,6 +1484,7 @@ Optional Features:
is no). This assumes that rustc-demangle is is no). This assumes that rustc-demangle is
installed in your sysroot, and all headers from it installed in your sysroot, and all headers from it
are available in your standard include path are available in your standard include path
--enable-zstd Enable decompression of ELF sections with zstd
Optional Packages: Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@ -6594,11 +6596,11 @@ if test x$ac_prog_cxx_stdcxx = xno
then : then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 { 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; } 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 : then :
printf %s "(cached) " >&6 printf %s "(cached) " >&6
else $as_nop else $as_nop
ac_cv_prog_cxx_11=no ac_cv_prog_cxx_cxx11=no
ac_save_CXX=$CXX ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* end confdefs.h. */
@ -6640,11 +6642,11 @@ if test x$ac_prog_cxx_stdcxx = xno
then : then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 { 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; } 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 : then :
printf %s "(cached) " >&6 printf %s "(cached) " >&6
else $as_nop else $as_nop
ac_cv_prog_cxx_98=no ac_cv_prog_cxx_cxx98=no
ac_save_CXX=$CXX ac_save_CXX=$CXX
cat confdefs.h - <<_ACEOF >conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */ /* 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. # Check whether --with-tests-as-root was given.
if test ${with_tests_as_root+y} if test ${with_tests_as_root+y}

View file

@ -212,6 +212,17 @@ fi
AC_ARG_VAR([RUSTC_DEMANGLE_CFLAGS], [Compiler flags for rustc-demangle]) AC_ARG_VAR([RUSTC_DEMANGLE_CFLAGS], [Compiler flags for rustc-demangle])
AC_ARG_VAR([RUSTC_DEMANGLE_LIBS], [Linker 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, AC_ARG_WITH(tests-as-root,
AS_HELP_STRING([--with-tests-as-root], AS_HELP_STRING([--with-tests-as-root],
[Run the tests as root. Use this on platforms] [Run the tests as root. Use this on platforms]

View file

@ -51,6 +51,9 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <zlib.h> #include <zlib.h>
#ifdef HAVE_LIBZSTD
#include <zstd.h>
#endif
#include <set> #include <set>
#include <string> #include <string>
@ -108,6 +111,11 @@ using google_breakpad::wasteful_vector;
#define EM_AARCH64 183 #define EM_AARCH64 183
#endif #endif
// Define ZStd compression if host machine does not include this define.
#ifndef ELFCOMPRESS_ZSTD
#define ELFCOMPRESS_ZSTD 2
#endif
// //
// FDWrapper // FDWrapper
// //
@ -305,7 +313,7 @@ uint32_t GetCompressionHeader(
return sizeof (*header); 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) { const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) {
z_stream stream; z_stream stream;
memset(&stream, 0, sizeof 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); : 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, void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
Module* module, Module* module,
google_breakpad::Endianness endianness, google_breakpad::Endianness endianness,
@ -437,7 +476,7 @@ bool LoadDwarf(const string& dwarf_filename,
size -= compression_header_size; size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed = 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) { if (uncompressed.first != nullptr && uncompressed.second != 0) {
file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second); file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second);
@ -587,7 +626,7 @@ bool LoadDwarfCFI(const string& dwarf_filename,
cfi_size -= compression_header_size; cfi_size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed = 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) { if (uncompressed.first == nullptr || uncompressed.second == 0) {
fprintf(stderr, "%s: decompression failed\n", dwarf_filename.c_str()); fprintf(stderr, "%s: decompression failed\n", dwarf_filename.c_str());

View file

@ -21,6 +21,9 @@
/* Define to 1 if you have the `rustc_demangle' library (-lrustc_demangle). */ /* Define to 1 if you have the `rustc_demangle' library (-lrustc_demangle). */
#undef HAVE_LIBRUSTC_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. */ /* Define to 1 if you have the `memfd_create' function. */
#undef HAVE_MEMFD_CREATE #undef HAVE_MEMFD_CREATE