build: switch to hiding libnotmuch symbols by default
authorJani Nikula <jani@nikula.org>
Wed, 10 May 2017 19:42:11 +0000 (22:42 +0300)
committerDavid Bremner <david@tethera.net>
Fri, 12 May 2017 10:17:18 +0000 (07:17 -0300)
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
lib/Makefile.local
lib/database-private.h
lib/gen-version-script.sh [deleted file]
lib/notmuch-private.h
lib/notmuch.h
lib/notmuch.sym [new file with mode: 0644]
test/T360-symbol-hiding.sh

index 296030c76977b8a6f99eca86eaeb2f26456efe72..7b283fb3bff2482738b29e5a502596ed2176ec4b 100644 (file)
@@ -7,7 +7,6 @@ tags
 *cscope*
 .deps
 /notmuch
-notmuch.sym
 notmuch-shared
 libnotmuch.so*
 libnotmuch*.dylib
index d36fd5a0678e7cf11cebe13d565feb4520e71d16..bf6e06494748d965a67dc33643b38a81f817e1a1 100644 (file)
@@ -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
index ab3d9691247fdefdee4ec0f370908f0e11b377af..727b1d616f248f6aa3c5662985e0f69048a3c700 100644 (file)
@@ -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 (file)
index c98a07b..0000000
+++ /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"
index 8587e86ca57ad6697c4966f8fcf8ee9fc677c941..926707d82d12a2173d858d1ac1cd55c308197cd4 100644 (file)
@@ -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
index d374dc960fe67b4ccc1b096dc41c240d0779d808..e17454442333c80b459c0e3073b766c3fec6888e 100644 (file)
@@ -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 (file)
index 0000000..7d0c0af
--- /dev/null
@@ -0,0 +1,7 @@
+{
+global:
+       _ZTI*;
+       _ZTS*;
+       notmuch_*;
+local: *;
+};
index b3dbb1b543e9e0a9e8d83821ddf1e182f5fb0a57..9c6d4e647db5dc0e124e470e8ed707121406881c 100755 (executable)
@@ -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