From a5a1d25c3e9773edda5fbb73c04c4c13fece72e2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sun, 31 Oct 2021 18:02:16 -0700
Subject: [PATCH v2 1/3] Use hidden visibility for shared libraries where
 possible.

---
 configure                                  | 153 +++++++++++++++++++++
 configure.ac                               |  14 ++
 contrib/hstore/hstore.h                    |  16 +--
 contrib/ltree/ltree.h                      |  40 +++---
 src/Makefile.global.in                     |   2 +
 src/Makefile.shlib                         |  13 ++
 src/include/c.h                            |  15 +-
 src/include/fmgr.h                         |  12 +-
 src/include/jit/jit.h                      |   2 +-
 src/include/pg_config.h.in                 |   3 +
 src/include/replication/output_plugin.h    |   2 +
 src/pl/plpython/plpy_elog.h                |   8 +-
 src/pl/plpython/plpy_typeio.h              |  18 +--
 src/pl/plpython/plpy_util.h                |   8 +-
 src/test/modules/test_shm_mq/test_shm_mq.h |   2 +-
 src/test/modules/worker_spi/worker_spi.c   |   2 +-
 src/tools/msvc/Solution.pm                 |   1 +
 17 files changed, 258 insertions(+), 53 deletions(-)

diff --git a/configure b/configure
index 4ffefe46552..9057791eb00 100755
--- a/configure
+++ b/configure
@@ -735,6 +735,8 @@ CPP
 CFLAGS_SL
 BITCODE_CXXFLAGS
 BITCODE_CFLAGS
+CXXFLAGS_SL_MOD
+CFLAGS_SL_MOD
 CFLAGS_VECTORIZE
 CFLAGS_UNROLL_LOOPS
 PERMIT_DECLARATION_AFTER_STATEMENT
@@ -6421,6 +6423,155 @@ fi
   if test -n "$NOT_THE_CFLAGS"; then
     CFLAGS="$CFLAGS -Wno-stringop-truncation"
   fi
+
+  # If the compiler knows how to hide symbols, use that. But only for shared libraries,
+  # for postgres itself that'd be too verbose for now.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -fvisibility=hidden, for CFLAGS_SL_MOD" >&5
+$as_echo_n "checking whether ${CC} supports -fvisibility=hidden, for CFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CC_cflags__fvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CFLAGS=$CFLAGS
+pgac_save_CC=$CC
+CC=${CC}
+CFLAGS="${CFLAGS_SL_MOD} -fvisibility=hidden"
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  pgac_cv_prog_CC_cflags__fvisibility_hidden=yes
+else
+  pgac_cv_prog_CC_cflags__fvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_c_werror_flag=$ac_save_c_werror_flag
+CFLAGS="$pgac_save_CFLAGS"
+CC="$pgac_save_CC"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__fvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CC_cflags__fvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CC_cflags__fvisibility_hidden" = x"yes"; then
+  CFLAGS_SL_MOD="${CFLAGS_SL_MOD} -fvisibility=hidden"
+fi
+
+
+  if test "$pgac_cv_prog_CC_cflags__fvisibility_hidden" = yes; then
+
+$as_echo "#define HAVE_VISIBILITY_ATTRIBUTE 1" >>confdefs.h
+
+  fi
+  # For C++ we additionally want -fvisibility-inlines-hidden
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -fvisibility=hidden, for CXXFLAGS_SL_MOD" >&5
+$as_echo_n "checking whether ${CXX} supports -fvisibility=hidden, for CXXFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__fvisibility_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS_SL_MOD} -fvisibility=hidden"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__fvisibility_hidden=yes
+else
+  pgac_cv_prog_CXX_cxxflags__fvisibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_hidden" = x"yes"; then
+  CXXFLAGS_SL_MOD="${CXXFLAGS_SL_MOD} -fvisibility=hidden"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports -fvisibility-inlines-hidden, for CXXFLAGS_SL_MOD" >&5
+$as_echo_n "checking whether ${CXX} supports -fvisibility-inlines-hidden, for CXXFLAGS_SL_MOD... " >&6; }
+if ${pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  pgac_save_CXXFLAGS=$CXXFLAGS
+pgac_save_CXX=$CXX
+CXX=${CXX}
+CXXFLAGS="${CXXFLAGS_SL_MOD} -fvisibility-inlines-hidden"
+ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ac_cxx_werror_flag=yes
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden=yes
+else
+  pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+CXXFLAGS="$pgac_save_CXXFLAGS"
+CXX="$pgac_save_CXX"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" >&5
+$as_echo "$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" >&6; }
+if test x"$pgac_cv_prog_CXX_cxxflags__fvisibility_inlines_hidden" = x"yes"; then
+  CXXFLAGS_SL_MOD="${CXXFLAGS_SL_MOD} -fvisibility-inlines-hidden"
+fi
+
+
 elif test "$ICC" = yes; then
   # Intel's compiler has a bug/misoptimization in checking for
   # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS.
@@ -6890,6 +7041,8 @@ fi
 
 
 
+
+
 # Determine flags used to emit bitcode for JIT inlining. Need to test
 # for behaviour changing compiler flags, to keep compatibility with
 # compiler used for normal postgres code.
diff --git a/configure.ac b/configure.ac
index 44ee3ebe2f1..b5cc312c3d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -541,6 +541,18 @@ if test "$GCC" = yes -a "$ICC" = no; then
   if test -n "$NOT_THE_CFLAGS"; then
     CFLAGS="$CFLAGS -Wno-stringop-truncation"
   fi
+
+  # If the compiler knows how to hide symbols, use that. But only for shared libraries,
+  # for postgres itself that'd be too verbose for now.
+  PGAC_PROG_CC_VAR_OPT(CFLAGS_SL_MOD, [-fvisibility=hidden])
+  if test "$pgac_cv_prog_CC_cflags__fvisibility_hidden" = yes; then
+     AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE, 1,
+               [Define to 1 if your compiler knows the visibility("hidden") attribute.])
+  fi
+  # For C++ we additionally want -fvisibility-inlines-hidden
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MOD, [-fvisibility=hidden])
+  PGAC_PROG_VARCXX_VARFLAGS_OPT(CXX, CXXFLAGS_SL_MOD, [-fvisibility-inlines-hidden])
+
 elif test "$ICC" = yes; then
   # Intel's compiler has a bug/misoptimization in checking for
   # division by NAN (NaN == 0), -mp1 fixes it, so add it to the CFLAGS.
@@ -564,6 +576,8 @@ fi
 
 AC_SUBST(CFLAGS_UNROLL_LOOPS)
 AC_SUBST(CFLAGS_VECTORIZE)
+AC_SUBST(CFLAGS_SL_MOD)
+AC_SUBST(CXXFLAGS_SL_MOD)
 
 # Determine flags used to emit bitcode for JIT inlining. Need to test
 # for behaviour changing compiler flags, to keep compatibility with
diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index bf4a565ed9b..625134c9f69 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -147,7 +147,7 @@ typedef struct
 	} while (0)
 
 /* DatumGetHStoreP includes support for reading old-format hstore values */
-extern HStore *hstoreUpgrade(Datum orig);
+extern PGDLLEXPORT HStore *hstoreUpgrade(Datum orig);
 
 #define DatumGetHStoreP(d) hstoreUpgrade(d)
 
@@ -168,14 +168,14 @@ typedef struct
 	bool		needfree;		/* need to pfree the value? */
 } Pairs;
 
-extern int	hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);
-extern HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);
+extern PGDLLEXPORT int	hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);
+extern PGDLLEXPORT HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);
 
-extern size_t hstoreCheckKeyLen(size_t len);
-extern size_t hstoreCheckValLen(size_t len);
+extern PGDLLEXPORT size_t hstoreCheckKeyLen(size_t len);
+extern PGDLLEXPORT size_t hstoreCheckValLen(size_t len);
 
-extern int	hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
-extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
+extern PGDLLEXPORT int	hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
+extern PGDLLEXPORT Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
 
 #define HStoreContainsStrategyNumber	7
 #define HStoreExistsStrategyNumber		9
@@ -194,7 +194,7 @@ extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
 #if HSTORE_POLLUTE_NAMESPACE
 #define HSTORE_POLLUTE(newname_,oldname_) \
 	PG_FUNCTION_INFO_V1(oldname_);		  \
-	Datum newname_(PG_FUNCTION_ARGS);	  \
+	extern PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS);	  \
 	Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
 	extern int no_such_variable
 #else
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 5b4be5e680a..d8bcdedbdbe 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -176,30 +176,30 @@ typedef struct
 
 
 /* use in array iterator */
-Datum		ltree_isparent(PG_FUNCTION_ARGS);
-Datum		ltree_risparent(PG_FUNCTION_ARGS);
-Datum		ltq_regex(PG_FUNCTION_ARGS);
-Datum		ltq_rregex(PG_FUNCTION_ARGS);
-Datum		lt_q_regex(PG_FUNCTION_ARGS);
-Datum		lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltq_regex(PG_FUNCTION_ARGS);
-Datum		_ltq_rregex(PG_FUNCTION_ARGS);
-Datum		_lt_q_regex(PG_FUNCTION_ARGS);
-Datum		_lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		_ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		_ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltree_isparent(PG_FUNCTION_ARGS);
-Datum		_ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltree_risparent(PG_FUNCTION_ARGS);
 
 /* Concatenation functions */
-Datum		ltree_addltree(PG_FUNCTION_ARGS);
-Datum		ltree_addtext(PG_FUNCTION_ARGS);
-Datum		ltree_textadd(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_addltree(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_addtext(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_textadd(PG_FUNCTION_ARGS);
 
 /* Util function */
-Datum		ltree_in(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_in(PG_FUNCTION_ARGS);
 
 bool		ltree_execute(ITEM *curitem, void *checkval,
 						  bool calcnot, bool (*chkcond) (void *checkval, ITEM *val));
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 533c12fef95..fbd2f2eab3d 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -259,6 +259,8 @@ SUN_STUDIO_CC = @SUN_STUDIO_CC@
 CXX = @CXX@
 CFLAGS = @CFLAGS@
 CFLAGS_SL = @CFLAGS_SL@
+CFLAGS_SL_MOD = @CFLAGS_SL_MOD@
+CXXFLAGS_SL_MOD = @CXXFLAGS_SL_MOD@
 CFLAGS_UNROLL_LOOPS = @CFLAGS_UNROLL_LOOPS@
 CFLAGS_VECTORIZE = @CFLAGS_VECTORIZE@
 CFLAGS_SSE42 = @CFLAGS_SSE42@
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 551023c6fb0..9119e9bb5d6 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -253,6 +253,19 @@ ifeq ($(PORTNAME), win32)
 endif
 
 
+# If the shared library doesn't have an export file, mark all symbols not
+# explicitly exported using PGDLLEXPORT as hidden. We can't pass these flags
+# when building a library with explicit exports, as the symbols would be
+# hidden before the linker script / exported symbol list takes effect.
+#
+# XXX: This probably isn't the best location, but not clear where else
+# instead?
+ifeq ($(SHLIB_EXPORTS),)
+  LDFLAGS += $(CFLAGS_SL_MOD)
+  override CFLAGS += $(CFLAGS_SL_MOD)
+  override CXXFLAGS += $(CXXFLAGS_SL_MOD)
+endif
+
 
 ##
 ## BUILD
diff --git a/src/include/c.h b/src/include/c.h
index c8ede082739..9b539a2657b 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1312,11 +1312,18 @@ extern long long strtoll(const char *str, char **endptr, int base);
 extern unsigned long long strtoull(const char *str, char **endptr, int base);
 #endif
 
-/* no special DLL markers on most ports */
-#ifndef PGDLLIMPORT
-#define PGDLLIMPORT
+/*
+ * If the platform knows __attribute__((visibility("*"))), i.e. gcc like
+ * compilers, we use that.
+ */
+#if !defined(PGDLLIMPORT) && defined(HAVE_VISIBILITY_ATTRIBUTE)
+#define PGDLLIMPORT __attribute__((visibility("default")))
+#define PGDLLEXPORT __attribute__((visibility("default")))
 #endif
-#ifndef PGDLLEXPORT
+
+/* No special DLL markers on the remaining ports. */
+#if !defined(PGDLLIMPORT)
+#define PGDLLIMPORT
 #define PGDLLEXPORT
 #endif
 
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index ab7b85c86e1..e200a4170a9 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -413,7 +413,7 @@ typedef const Pg_finfo_record *(*PGFInfoFunction) (void);
  *	info function, since authors shouldn't need to be explicitly aware of it.
  */
 #define PG_FUNCTION_INFO_V1(funcname) \
-extern Datum funcname(PG_FUNCTION_ARGS); \
+extern PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS); \
 extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
 const Pg_finfo_record * \
 CppConcat(pg_finfo_,funcname) (void) \
@@ -424,6 +424,16 @@ CppConcat(pg_finfo_,funcname) (void) \
 extern int no_such_variable
 
 
+/*
+ * Declare _PG_init/_PG_fini centrally. Historically each shared library had
+ * its own declaration, but now that we want to mark the symbols PGDLLEXPORT,
+ * the central declaration helps find extensions with local declarations
+ * missing PGDLLEXPORT.
+ */
+extern PGDLLEXPORT void _PG_init(void);
+extern PGDLLEXPORT void _PG_fini(void);
+
+
 /*-------------------------------------------------------------------------
  *		Support for verifying backend compatibility of loaded modules
  *
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index b634df30b98..74617ad1b64 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -63,7 +63,7 @@ typedef struct JitContext
 
 typedef struct JitProviderCallbacks JitProviderCallbacks;
 
-extern void _PG_jit_provider_init(JitProviderCallbacks *cb);
+extern PGDLLEXPORT void _PG_jit_provider_init(JitProviderCallbacks *cb);
 typedef void (*JitProviderInit) (JitProviderCallbacks *cb);
 typedef void (*JitProviderResetAfterErrorCB) (void);
 typedef void (*JitProviderReleaseContextCB) (JitContext *context);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 15ffdd895aa..e3ab1c7752f 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -710,6 +710,9 @@
 /* Define to 1 if you have the <uuid/uuid.h> header file. */
 #undef HAVE_UUID_UUID_H
 
+/* Define to 1 if your compiler knows the visibility("hidden") attribute. */
+#undef HAVE_VISIBILITY_ATTRIBUTE
+
 /* Define to 1 if you have the `wcstombs_l' function. */
 #undef HAVE_WCSTOMBS_L
 
diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
index 810495ed0e4..a087f14dadd 100644
--- a/src/include/replication/output_plugin.h
+++ b/src/include/replication/output_plugin.h
@@ -35,6 +35,8 @@ typedef struct OutputPluginOptions
  */
 typedef void (*LogicalOutputPluginInit) (struct OutputPluginCallbacks *cb);
 
+extern PGDLLEXPORT void _PG_output_plugin_init(struct OutputPluginCallbacks *cb);
+
 /*
  * Callback that gets called in a user-defined plugin. ctx->private_data can
  * be set to some private data.
diff --git a/src/pl/plpython/plpy_elog.h b/src/pl/plpython/plpy_elog.h
index e02ef4ffe9f..aeade82ce10 100644
--- a/src/pl/plpython/plpy_elog.h
+++ b/src/pl/plpython/plpy_elog.h
@@ -34,13 +34,13 @@ extern PyObject *PLy_exc_spi_error;
 	} while(0)
 #endif							/* HAVE__BUILTIN_CONSTANT_P */
 
-extern void PLy_elog_impl(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);
+extern PGDLLEXPORT void PLy_elog_impl(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);
 
-extern void PLy_exception_set(PyObject *exc, const char *fmt,...) pg_attribute_printf(2, 3);
+extern PGDLLEXPORT void PLy_exception_set(PyObject *exc, const char *fmt,...) pg_attribute_printf(2, 3);
 
-extern void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural,
+extern PGDLLEXPORT void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural,
 									 unsigned long n,...) pg_attribute_printf(2, 5) pg_attribute_printf(3, 5);
 
-extern void PLy_exception_set_with_details(PyObject *excclass, ErrorData *edata);
+extern PGDLLEXPORT void PLy_exception_set_with_details(PyObject *excclass, ErrorData *edata);
 
 #endif							/* PLPY_ELOG_H */
diff --git a/src/pl/plpython/plpy_typeio.h b/src/pl/plpython/plpy_typeio.h
index d11e6ae1b89..87e3b2c464e 100644
--- a/src/pl/plpython/plpy_typeio.h
+++ b/src/pl/plpython/plpy_typeio.h
@@ -147,29 +147,29 @@ struct PLyObToDatum
 };
 
 
-extern PyObject *PLy_input_convert(PLyDatumToOb *arg, Datum val);
-extern Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val,
+extern PGDLLEXPORT PyObject *PLy_input_convert(PLyDatumToOb *arg, Datum val);
+extern PGDLLEXPORT Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val,
 								bool *isnull);
 
-extern PyObject *PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple,
+extern PGDLLEXPORT PyObject *PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple,
 									  TupleDesc desc, bool include_generated);
 
-extern void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
+extern PGDLLEXPORT void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
 								 Oid typeOid, int32 typmod,
 								 struct PLyProcedure *proc);
-extern void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
+extern PGDLLEXPORT void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
 								  Oid typeOid, int32 typmod,
 								  struct PLyProcedure *proc);
 
-extern void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc,
 								  struct PLyProcedure *proc);
-extern void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc,
 								   struct PLyProcedure *proc);
 
-extern void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc,
+extern PGDLLEXPORT void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc,
 									struct PLyProcedure *proc);
 
 /* conversion from Python objects to C strings --- exported for transforms */
-extern char *PLyObject_AsString(PyObject *plrv);
+extern PGDLLEXPORT char *PLyObject_AsString(PyObject *plrv);
 
 #endif							/* PLPY_TYPEIO_H */
diff --git a/src/pl/plpython/plpy_util.h b/src/pl/plpython/plpy_util.h
index c9ba7edc0ec..6927601e0be 100644
--- a/src/pl/plpython/plpy_util.h
+++ b/src/pl/plpython/plpy_util.h
@@ -8,12 +8,12 @@
 
 #include "plpython.h"
 
-extern PyObject *PLyUnicode_Bytes(PyObject *unicode);
-extern char *PLyUnicode_AsString(PyObject *unicode);
+extern PGDLLEXPORT PyObject *PLyUnicode_Bytes(PyObject *unicode);
+extern PGDLLEXPORT char *PLyUnicode_AsString(PyObject *unicode);
 
 #if PY_MAJOR_VERSION >= 3
-extern PyObject *PLyUnicode_FromString(const char *s);
-extern PyObject *PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size);
+extern PGDLLEXPORT PyObject *PLyUnicode_FromString(const char *s);
+extern PGDLLEXPORT PyObject *PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size);
 #endif
 
 #endif							/* PLPY_UTIL_H */
diff --git a/src/test/modules/test_shm_mq/test_shm_mq.h b/src/test/modules/test_shm_mq/test_shm_mq.h
index a6661218347..a7a36714a48 100644
--- a/src/test/modules/test_shm_mq/test_shm_mq.h
+++ b/src/test/modules/test_shm_mq/test_shm_mq.h
@@ -40,6 +40,6 @@ extern void test_shm_mq_setup(int64 queue_size, int32 nworkers,
 							  shm_mq_handle **input);
 
 /* Main entrypoint for a worker. */
-extern void test_shm_mq_main(Datum) pg_attribute_noreturn();
+extern PGDLLEXPORT void test_shm_mq_main(Datum) pg_attribute_noreturn();
 
 #endif
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 0b6246676b6..e267bc3cffa 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -47,7 +47,7 @@ PG_MODULE_MAGIC;
 PG_FUNCTION_INFO_V1(worker_spi_launch);
 
 void		_PG_init(void);
-void		worker_spi_main(Datum) pg_attribute_noreturn();
+PGDLLEXPORT void worker_spi_main(Datum) pg_attribute_noreturn();
 
 /* GUC variables */
 static int	worker_spi_naptime = 10;
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 43fd1be0888..7ce250ea332 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -432,6 +432,7 @@ sub GenerateFiles
 		HAVE_WINLDAP_H                           => undef,
 		HAVE_WCSTOMBS_L                          => 1,
 		HAVE_WCTYPE_H                            => 1,
+		HAVE_VISIBILITY_ATTRIBUTE                => undef,
 		HAVE_WRITEV                              => undef,
 		HAVE_X509_GET_SIGNATURE_NID              => 1,
 		HAVE_X86_64_POPCNTQ                      => undef,
-- 
2.23.0.385.gbc12974a89

