From 4d344934501cbcdf87c3532c5bf845290dbcc71e Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Tue, 20 Jun 2023 16:19:42 +0200 Subject: [PATCH 1/4] ci: fix indentation --- .github/workflows/cibuild.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cibuild.sh b/.github/workflows/cibuild.sh index 9b70dc36c..00fae0ab8 100755 --- a/.github/workflows/cibuild.sh +++ b/.github/workflows/cibuild.sh @@ -1,5 +1,5 @@ #!/bin/bash - + set -ex PHASES=(${@:-CONFIGURE MAKE INSTALL CHECK DISTCHECK}) @@ -104,9 +104,9 @@ for phase in "${PHASES[@]}"; do CXXFLAGS+=(-shared-libasan) fi - if [[ "$HOST_TRIPLET" != "" ]]; then - opts+=(--host "$HOST_TRIPLET") - fi + if [[ "$HOST_TRIPLET" != "" ]]; then + opts+=(--host "$HOST_TRIPLET") + fi git config --global --add safe.directory "$PWD" git clean -xdf @@ -128,9 +128,9 @@ for phase in "${PHASES[@]}"; do ninja -C build ;; CODECHECK) - make checklibdoc - make checkxalloc - ;; + make checklibdoc + make checkxalloc + ;; CHECK) if [[ "$SANITIZE" == "yes" ]]; then # All the following black magic is to make test/eject/umount work, since From f5b49efe42c0928dc292efe24946cccad86d711e Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Tue, 20 Jun 2023 16:25:07 +0200 Subject: [PATCH 2/4] ci: tweak build dir's ACL when collecting coverage So gcov can create necessary directories/.gcda files even with dropped privileges. --- .github/workflows/cibuild.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/cibuild.sh b/.github/workflows/cibuild.sh index 00fae0ab8..8adac1ab6 100755 --- a/.github/workflows/cibuild.sh +++ b/.github/workflows/cibuild.sh @@ -162,6 +162,20 @@ for phase in "${PHASES[@]}"; do fi fi + if [[ "$COVERAGE" == "yes" ]]; then + # Make (almost) everything under current directory readable/writable + # for everyone to allow gcov to write the .gcda files even with + # dropped privileges + find . tests/helpers/ -maxdepth 1 -type d ! -name . ! -name tests \ + -exec setfacl -R -m 'd:g::rwX,d:o::rwX' -m 'g::rwX,o::rwX' '{}' \; + # Make sure we can access $PWD as an unpriv user + path="$PWD" + while [[ "$path" != / ]]; do + chmod o+rx "$path" + path="$(dirname "$path")" + done + fi + ./tests/run.sh --show-diff if [[ "$COVERAGE" == "yes" ]]; then From b4b8f8c293507cbe86dbe55c9c955e511279d673 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Tue, 20 Jun 2023 23:00:28 +0200 Subject: [PATCH 3/4] ci: hide coverage-related stuff begind --enable-coverage --- .github/workflows/cibuild.sh | 4 +--- Makefile.am | 2 +- configure.ac | 14 +++++++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cibuild.sh b/.github/workflows/cibuild.sh index 8adac1ab6..6bb10862f 100755 --- a/.github/workflows/cibuild.sh +++ b/.github/workflows/cibuild.sh @@ -87,9 +87,7 @@ for phase in "${PHASES[@]}"; do ) if [[ "$COVERAGE" == "yes" ]]; then - CFLAGS+=(--coverage) - CXXFLAGS+=(--coverage) - LDFLAGS+=(--coverage) + opts+=(--enable-coverage) fi if [[ "$SANITIZE" == "yes" ]]; then diff --git a/Makefile.am b/Makefile.am index effbb02fc..e52a7f592 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ endif AM_CFLAGS = -fsigned-char $(WARN_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) -AM_LDFLAGS = $(ASAN_LDFLAGS) $(UBSAN_LDFLAGS) $(FUZZING_ENGINE_LDFLAGS) +AM_LDFLAGS = $(ASAN_LDFLAGS) $(UBSAN_LDFLAGS) $(FUZZING_ENGINE_LDFLAGS) $(COVERAGE_LDFLAGS) # Add gettext stuff to the global LDADD for systems with separate libintl # library. The LTLIBINTL is generated by AM_GNU_GETTEXT macro. diff --git a/configure.ac b/configure.ac index 7de254c2d..8bd10ee69 100644 --- a/configure.ac +++ b/configure.ac @@ -215,6 +215,17 @@ AC_PROG_CXX AM_CONDITIONAL([FUZZING_ENGINE], [test "x$enable_fuzzing_engine" = xyes]) AM_CONDITIONAL([OSS_FUZZ], [test "x$LIB_FUZZING_ENGINE" != x]) +AC_ARG_ENABLE([coverage], + AS_HELP_STRING([--enable-coverage], [compile with gcov]), + [], [enable_coverage=no] +) +AS_IF([test "x$enable_coverage" = xyes], [ + UL_WARN_ADD([--coverage]) + COVERAGE_LDFLAGS="--coverage" +]) +AC_SUBST([COVERAGE_LDFLAGS]) +AM_CONDITIONAL([WITH_COVERAGE], [test "x$enable_coverage" = xyes]) + dnl libtool-2 LT_INIT @@ -2891,7 +2902,8 @@ AC_MSG_RESULT([ ldflags: ${LDFLAGS} suid ldflags: ${SUID_LDFLAGS} ASAN enabled: ${enable_asan} - Fuzzing enabled: ${enable_fuzzing_engine} + Fuzzing enabled: ${enable_fuzzing_engine} + Coverage enabled ${enable_coverage} cflags: ${CFLAGS} From b0d003023cabecd45402a4d8e2529940ec778735 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Tue, 20 Jun 2023 23:01:35 +0200 Subject: [PATCH 4/4] ci: collect coverage on _exit() as well _exit() skips the gcov hooks, so we lose all coverage collected up to that point. Let's work around this by intercepting _exit() with our wrapper that calls __gcov_dump() just before _exit(). --- Makefile.am | 5 +++++ include/Makemodule.am | 1 + include/coverage.h | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 include/coverage.h diff --git a/Makefile.am b/Makefile.am index e52a7f592..0335f5893 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,11 @@ AM_CPPFLAGS += \ endif endif +if WITH_COVERAGE +AM_CPPFLAGS += \ + -include $(top_srcdir)/include/coverage.h +endif + AM_CFLAGS = -fsigned-char $(WARN_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) AM_LDFLAGS = $(ASAN_LDFLAGS) $(UBSAN_LDFLAGS) $(FUZZING_ENGINE_LDFLAGS) $(COVERAGE_LDFLAGS) diff --git a/include/Makemodule.am b/include/Makemodule.am index 068b0f8e8..52657f7d1 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -13,6 +13,7 @@ dist_noinst_HEADERS += \ include/closestream.h \ include/colors.h \ include/color-names.h \ + include/coverage.h \ include/cpuset.h \ include/crc32.h \ include/crc32c.h \ diff --git a/include/coverage.h b/include/coverage.h new file mode 100644 index 000000000..f0148e579 --- /dev/null +++ b/include/coverage.h @@ -0,0 +1,25 @@ +/* + * No copyright is claimed. This code is in the public domain; do with + * it what you wish. + */ +#ifndef UTIL_LINUX_COVERAGE_H +#define UTIL_LINUX_COVERAGE_H + +/* When built with --coverage (gcov) we need to explicitly call __gcov_dump() + * in places where we use _exit(), since _exit() skips at-exit hooks resulting + * in lost coverage. + * + * To make sure we don't miss any _exit() calls, this header file is included + * explicitly on the compiler command line via the -include directive (only + * when built with --coverage/-Db_coverage=true) + */ +void __gcov_dump(void); +void _exit(int); + +__attribute__((noreturn)) static inline void _coverage__exit(int status) { + __gcov_dump(); + _exit(status); +} +#define _exit(x) _coverage__exit(x) + +#endif