[PATCH 3/4] build: switch to hiding libnotmuch symbols by default

Jani Nikula jani at nikula.org
Sun Apr 23 13:01:58 PDT 2017


The dynamic generation of the linker version script for libnotmuch
exports has grown rather complicated.

Reverse the visibility control by hiding symbols by default using
-fvisibility=hidden, and explicitly exporting symbols in notmuch.h
using #pragma GCC visibility. (We could also use __attribute__
((visibility ("default"))) for each exported function, but the pragma
is more convenient.)

The above is not quite enough alone, as it would "leak" a number of
weak symbols from Xapian and C++ standard library. Combine it with a
small static version script that filters out everything except the
notmuch_* symbols that we explicitly exposed, and the C++ RTTI
typeinfo symbols for exception handling.

Finally, as the symbol hiding test can no longer look at the generated
symbol table, switch the test to parse the functions from notmuch.h.
---
 .gitignore                 |  1 -
 lib/Makefile.local         | 25 ++++++++++++-------------
 lib/database-private.h     |  4 ----
 lib/gen-version-script.sh  | 28 ----------------------------
 lib/notmuch-private.h      |  4 ----
 lib/notmuch.h              |  4 ++++
 lib/notmuch.sym            |  7 +++++++
 test/T360-symbol-hiding.sh |  2 +-
 8 files changed, 24 insertions(+), 51 deletions(-)
 delete mode 100644 lib/gen-version-script.sh
 create mode 100644 lib/notmuch.sym

diff --git a/.gitignore b/.gitignore
index 296030c76977..7b283fb3bff2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,6 @@ tags
 *cscope*
 .deps
 /notmuch
-notmuch.sym
 notmuch-shared
 libnotmuch.so*
 libnotmuch*.dylib
diff --git a/lib/Makefile.local b/lib/Makefile.local
index d36fd5a0678e..bf6e06494748 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -1,5 +1,12 @@
 # -*- makefile -*-
 
+dir := lib
+
+# The (often-reused) $dir works fine within targets/prerequisites,
+# but cannot be used reliably within commands, so copy its value to a
+# variable that is not reused.
+lib := $(dir)
+
 ifeq ($(PLATFORM),MACOSX)
 LIBRARY_SUFFIX = dylib
 # On OS X, library version numbers go before suffix.
@@ -12,7 +19,7 @@ LIBRARY_SUFFIX = so
 LINKER_NAME = libnotmuch.$(LIBRARY_SUFFIX)
 SONAME = $(LINKER_NAME).$(LIBNOTMUCH_VERSION_MAJOR)
 LIBNAME = $(SONAME).$(LIBNOTMUCH_VERSION_MINOR).$(LIBNOTMUCH_VERSION_RELEASE)
-LIBRARY_LINK_FLAG = -shared -Wl,--version-script=notmuch.sym,-soname=$(SONAME) $(NO_UNDEFINED_LDFLAGS)
+LIBRARY_LINK_FLAG = -shared -Wl,--version-script=$(lib)/notmuch.sym,-soname=$(SONAME) $(NO_UNDEFINED_LDFLAGS)
 ifeq ($(PLATFORM),OPENBSD)
 LIBRARY_LINK_FLAG += -lc
 endif
@@ -23,13 +30,8 @@ endif
 endif
 endif
 
-dir := lib
-extra_cflags += -I$(srcdir)/$(dir) -fPIC
-
-# The (often-reused) $dir works fine within targets/prerequisites,
-# but cannot be used reliably within commands, so copy its value to a
-# variable that is not reused.
-lib := $(dir)
+extra_cflags += -I$(srcdir)/$(dir) -fPIC -fvisibility=hidden
+extra_cxxflags += -fvisibility-inlines-hidden
 
 libnotmuch_c_srcs =		\
 	$(notmuch_compat_srcs)	\
@@ -60,12 +62,9 @@ libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
 $(dir)/libnotmuch.a: $(libnotmuch_modules)
 	$(call quiet,AR) rcs $@ $^
 
-$(dir)/$(LIBNAME): $(libnotmuch_modules) notmuch.sym util/libnotmuch_util.a parse-time-string/libparse-time-string.a
+$(dir)/$(LIBNAME): $(libnotmuch_modules) util/libnotmuch_util.a parse-time-string/libparse-time-string.a
 	$(call quiet,CXX $(CXXFLAGS)) $(libnotmuch_modules) $(FINAL_LIBNOTMUCH_LDFLAGS) $(LIBRARY_LINK_FLAG) -o $@ util/libnotmuch_util.a parse-time-string/libparse-time-string.a
 
-notmuch.sym: $(srcdir)/$(dir)/notmuch.h $(libnotmuch_modules)
-	sh $(srcdir)/$(lib)/gen-version-script.sh $< $(libnotmuch_modules) > $@
-
 $(dir)/$(SONAME): $(dir)/$(LIBNAME)
 	ln -sf $(LIBNAME) $@
 
@@ -85,5 +84,5 @@ install-$(dir): $(dir)/$(LIBNAME)
 
 SRCS  := $(SRCS) $(libnotmuch_c_srcs) $(libnotmuch_cxx_srcs)
 CLEAN += $(libnotmuch_modules) $(dir)/$(SONAME) $(dir)/$(LINKER_NAME)
-CLEAN += $(dir)/$(LIBNAME) $(dir)/libnotmuch.a notmuch.sym
+CLEAN += $(dir)/$(LIBNAME) $(dir)/libnotmuch.a
 CLEAN += $(dir)/notmuch.h.gch
diff --git a/lib/database-private.h b/lib/database-private.h
index ab3d9691247f..727b1d616f24 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -38,8 +38,6 @@
 
 #include <xapian.h>
 
-#pragma GCC visibility push(hidden)
-
 /* Bit masks for _notmuch_database::features.  Features are named,
  * independent aspects of the database schema.
  *
@@ -248,6 +246,4 @@ _notmuch_database_get_terms_with_prefix (void *ctx, Xapian::TermIterator &i,
 					 Xapian::TermIterator &end,
 					 const char *prefix);
 
-#pragma GCC visibility pop
-
 #endif
diff --git a/lib/gen-version-script.sh b/lib/gen-version-script.sh
deleted file mode 100644
index c98a07b0c701..000000000000
--- a/lib/gen-version-script.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-set -eu
-
-# we go through a bit of work to get the unmangled names of the
-# typeinfo symbols because of
-# https://sourceware.org/bugzilla/show_bug.cgi?id=10326
-
-if [ $# -lt 2 ]; then
-    echo Usage: $0 header obj1 obj2 obj3
-    exit 1;
-fi
-
-HEADER=$1
-shift
-
-printf '{\nglobal:\n'
-nm  $* | awk '$1 ~ "^[0-9a-fA-F][0-9a-fA-F]*$" && $3 ~ "Xapian.*Error" {print $3}' | sort | uniq | \
-while read sym; do
-    demangled=$(c++filt $sym)
-    case $demangled in
-	typeinfo*)
-	    printf "\t$sym;\n"
-	    ;;
-	*)
-	    ;;
-    esac
-done
-sed  -n 's/^[[:space:]]*\(notmuch_[a-z_]*\)[[:space:]]*(.*/ \1;/p' $HEADER
-printf "local: *;\n};\n"
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 8587e86ca57a..926707d82d12 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -52,8 +52,6 @@ NOTMUCH_BEGIN_DECLS
 #include "error_util.h"
 #include "string-util.h"
 
-#pragma GCC visibility push(hidden)
-
 #ifdef DEBUG
 # define DEBUG_DATABASE_SANITY 1
 # define DEBUG_QUERY 1
@@ -621,6 +619,4 @@ _notmuch_talloc_steal (const void *new_ctx, const T *ptr)
 #endif
 #endif
 
-#pragma GCC visibility pop
-
 #endif
diff --git a/lib/notmuch.h b/lib/notmuch.h
index d374dc960fe6..e17454442333 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -43,6 +43,8 @@ NOTMUCH_BEGIN_DECLS
 
 #include <time.h>
 
+#pragma GCC visibility push(default)
+
 #ifndef FALSE
 #define FALSE 0
 #endif
@@ -2120,6 +2122,8 @@ notmuch_bool_t
 notmuch_built_with (const char *name);
 /* @} */
 
+#pragma GCC visibility pop
+
 NOTMUCH_END_DECLS
 
 #endif
diff --git a/lib/notmuch.sym b/lib/notmuch.sym
new file mode 100644
index 000000000000..7d0c0af40ad9
--- /dev/null
+++ b/lib/notmuch.sym
@@ -0,0 +1,7 @@
+{
+global:
+	_ZTI*;
+	_ZTS*;
+	notmuch_*;
+local: *;
+};
diff --git a/test/T360-symbol-hiding.sh b/test/T360-symbol-hiding.sh
index b3dbb1b543e9..9c6d4e647db5 100755
--- a/test/T360-symbol-hiding.sh
+++ b/test/T360-symbol-hiding.sh
@@ -27,7 +27,7 @@ test_expect_equal "$result" "$output"
 
 test_begin_subtest 'comparing existing to exported symbols'
 nm -P $TEST_DIRECTORY/../lib/libnotmuch.so | awk '$2 == "T" && $1 ~ "^notmuch" {print $1}' | sort | uniq > ACTUAL
-sed -n 's/[[:blank:]]*\(notmuch_[^;]*\);/\1/p' $TEST_DIRECTORY/../notmuch.sym | sort | uniq > EXPORTED
+sed -n 's/^\(notmuch_[a-zA-Z0-9_]*\)[[:blank:]]*(.*/\1/p' $TEST_DIRECTORY/../lib/notmuch.h | sort | uniq > EXPORTED
 test_expect_equal_file EXPORTED ACTUAL
 
 test_done
-- 
2.11.0



More information about the notmuch mailing list