From 9cac6a46259f102af306840720b3af64d4b8c12a Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 28 Oct 2009 19:45:26 +0000 Subject: [PATCH] Initial step towards the ability to reduce c-ares exported symbols based on the 'visibility' attribute for GNUC and __global for Sun compilers, taking also in account __declspec function decoration for Win32 and Symbian DLL's. Introducing configure options --enable-hidden-symbols and --disable-hidden-symbols following libcurl's naming. --- Makefile.am | 4 +- ares.h | 262 ++++++++++++++++++++++++++++++++++++-------------- configure.ac | 23 +++++ m4/cares-compilers.m4 | 96 +++++++++++++++++- m4/cares-confopts.m4 | 63 +++++++++++- 5 files changed, 373 insertions(+), 75 deletions(-) diff --git a/Makefile.am b/Makefile.am index 302ac9d..b1f364a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,9 +91,7 @@ if NO_UNDEFINED UNDEF = -no-undefined endif -# EXPORT_SYMBOLS = -export-symbols-regex '^ares_[[:alnum:]].*' - -libcares_la_LDFLAGS = $(UNDEF) $(VER) $(EXPORT_SYMBOLS) +libcares_la_LDFLAGS = $(UNDEF) $(VER) # Makefile.inc provides the CSOURCES and HHEADERS defines include Makefile.inc diff --git a/ares.h b/ares.h index d7c0ad2..c5ff242 100644 --- a/ares.h +++ b/ares.h @@ -45,9 +45,9 @@ #endif #if defined(WATT32) - #include - #include - #include +# include +# include +# include #elif defined(WIN32) # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN @@ -56,14 +56,36 @@ # include # include #else - #include - #include +# include +# include #endif #ifdef __cplusplus extern "C" { #endif +/* +** c-ares external API function linkage decorations. +*/ + +#if !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) + /* __declspec function decoration for Win32 and Symbian DLL's */ +# if defined(CARES_BUILDING_LIB) +# define CARES_EXTERN __declspec(dllexport) +# else +# define CARES_EXTERN __declspec(dllimport) +# endif +#else + /* visibility function decoration for other cases */ +# ifdef CARES_HIDDEN_SYMBOLS +# define CARES_EXTERN CARES_EXTERN_SYMBOL +# else +# define CARES_EXTERN +# endif +#endif + + #define ARES_SUCCESS 0 /* Server error codes (ARES_ENODATA indicates no relevant answer) */ @@ -241,62 +263,143 @@ struct hostent; struct timeval; struct sockaddr; struct ares_channeldata; + typedef struct ares_channeldata *ares_channel; -typedef void (*ares_callback)(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -typedef void (*ares_host_callback)(void *arg, int status, int timeouts, + +typedef void (*ares_callback)(void *arg, + int status, + int timeouts, + unsigned char *abuf, + int alen); + +typedef void (*ares_host_callback)(void *arg, + int status, + int timeouts, struct hostent *hostent); -typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, - char *node, char *service); + +typedef void (*ares_nameinfo_callback)(void *arg, + int status, + int timeouts, + char *node, + char *service); + typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, - int type, void *data); - -int ares_library_init(int flags); -void ares_library_cleanup(void); -const char *ares_version(int *version); - -int ares_init(ares_channel *channelptr); -int ares_init_options(ares_channel *channelptr, struct ares_options *options, - int optmask); -int ares_save_options(ares_channel channel, struct ares_options *options, - int *optmask); -void ares_destroy_options(struct ares_options *options); -int ares_dup(ares_channel *dest, ares_channel src); -void ares_destroy(ares_channel channel); -void ares_cancel(ares_channel channel); + int type, + void *data); + +CARES_EXTERN int ares_library_init(int flags); + +CARES_EXTERN void ares_library_cleanup(void); + +CARES_EXTERN const char *ares_version(int *version); + +CARES_EXTERN int ares_init(ares_channel *channelptr); + +CARES_EXTERN int ares_init_options(ares_channel *channelptr, + struct ares_options *options, + int optmask); + +CARES_EXTERN int ares_save_options(ares_channel channel, + struct ares_options *options, + int *optmask); + +CARES_EXTERN void ares_destroy_options(struct ares_options *options); + +CARES_EXTERN int ares_dup(ares_channel *dest, + ares_channel src); + +CARES_EXTERN void ares_destroy(ares_channel channel); + +CARES_EXTERN void ares_cancel(ares_channel channel); + void ares_set_socket_callback(ares_channel channel, ares_sock_create_callback callback, void *user_data); -void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, - ares_callback callback, void *arg); -void ares_query(ares_channel channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg); -void ares_search(ares_channel channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg); -void ares_gethostbyname(ares_channel channel, const char *name, int family, - ares_host_callback callback, void *arg); -int ares_gethostbyname_file(ares_channel channel, const char *name, - int family, struct hostent **host); -void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, - int family, ares_host_callback callback, void *arg); -void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, - ares_socklen_t salen, int flags, - ares_nameinfo_callback callback, - void *arg); -int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds); -int ares_getsock(ares_channel channel, int *socks, int numsocks); -struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv, - struct timeval *tv); -void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds); -void ares_process_fd(ares_channel channel, ares_socket_t read_fd, - ares_socket_t write_fd); - -int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, - int rd, unsigned char **buf, int *buflen); -int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, - int alen, char **s, long *enclen); -int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf, - int alen, unsigned char **s, long *enclen); + +CARES_EXTERN void ares_send(ares_channel channel, + const unsigned char *qbuf, + int qlen, + ares_callback callback, + void *arg); + +CARES_EXTERN void ares_query(ares_channel channel, + const char *name, + int dnsclass, + int type, + ares_callback callback, + void *arg); + +CARES_EXTERN void ares_search(ares_channel channel, + const char *name, + int dnsclass, + int type, + ares_callback callback, + void *arg); + +CARES_EXTERN void ares_gethostbyname(ares_channel channel, + const char *name, + int family, + ares_host_callback callback, + void *arg); + +CARES_EXTERN int ares_gethostbyname_file(ares_channel channel, + const char *name, + int family, + struct hostent **host); + +CARES_EXTERN void ares_gethostbyaddr(ares_channel channel, + const void *addr, + int addrlen, + int family, + ares_host_callback callback, + void *arg); + +CARES_EXTERN void ares_getnameinfo(ares_channel channel, + const struct sockaddr *sa, + ares_socklen_t salen, + int flags, + ares_nameinfo_callback callback, + void *arg); + +CARES_EXTERN int ares_fds(ares_channel channel, + fd_set *read_fds, + fd_set *write_fds); + +CARES_EXTERN int ares_getsock(ares_channel channel, + int *socks, + int numsocks); + +CARES_EXTERN struct timeval *ares_timeout(ares_channel channel, + struct timeval *maxtv, + struct timeval *tv); + +CARES_EXTERN void ares_process(ares_channel channel, + fd_set *read_fds, + fd_set *write_fds); + +CARES_EXTERN void ares_process_fd(ares_channel channel, + ares_socket_t read_fd, + ares_socket_t write_fd); + +CARES_EXTERN int ares_mkquery(const char *name, + int dnsclass, + int type, + unsigned short id, + int rd, + unsigned char **buf, + int *buflen); + +CARES_EXTERN int ares_expand_name(const unsigned char *encoded, + const unsigned char *abuf, + int alen, + char **s, + long *enclen); + +CARES_EXTERN int ares_expand_string(const unsigned char *encoded, + const unsigned char *abuf, + int alen, + unsigned char **s, + long *enclen); /* * NOTE: before c-ares 1.6.1 we would most often use the system in6_addr @@ -338,21 +441,40 @@ struct srv_reply { ** their TTLs in that array, and set *naddrttls to the number of addresses ** so written. */ -int ares_parse_a_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct addrttl *addrttls, int *naddrttls); -int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct addr6ttl *addrttls, int *naddrttls); -int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, - int addrlen, int family, struct hostent **host); -int ares_parse_ns_reply(const unsigned char *abuf, int alen, - struct hostent **host); -int ares_parse_srv_reply(const unsigned char* abuf, int alen, - struct srv_reply** srv_out, int *nsrvreply); -void ares_free_string(void *str); -void ares_free_hostent(struct hostent *host); -const char *ares_strerror(int code); + +CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf, + int alen, + struct hostent **host, + struct addrttl *addrttls, + int *naddrttls); + +CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, + int alen, + struct hostent **host, + struct addr6ttl *addrttls, + int *naddrttls); + +CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, + int alen, + const void *addr, + int addrlen, + int family, + struct hostent **host); + +CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf, + int alen, + struct hostent **host); + +CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, + int alen, + struct srv_reply** srv_out, + int *nsrvreply); + +CARES_EXTERN void ares_free_string(void *str); + +CARES_EXTERN void ares_free_hostent(struct hostent *host); + +CARES_EXTERN const char *ares_strerror(int code); #ifdef __cplusplus } diff --git a/configure.ac b/configure.ac index 42ccd49..92db52e 100644 --- a/configure.ac +++ b/configure.ac @@ -14,6 +14,7 @@ CARES_CHECK_OPTION_DEBUG CARES_CHECK_OPTION_OPTIMIZE CARES_CHECK_OPTION_WARNINGS CARES_CHECK_OPTION_CURLDEBUG +CARES_CHECK_OPTION_HIDDEN_SYMBOLS CARES_CHECK_PATH_SEPARATOR_REQUIRED @@ -110,6 +111,25 @@ esac dnl libtool setup AC_PROG_LIBTOOL +AC_MSG_CHECKING([if we need CARES_BUILDING_LIB]) +case $host in + *-*-mingw*) + AC_DEFINE(CARES_BUILDING_LIB, 1, [when building c-ares library]) + AC_MSG_RESULT(yes) + AC_MSG_CHECKING([if we need CARES_STATICLIB]) + if test "X$enable_shared" = "Xno" + then + AC_DEFINE(CARES_STATICLIB, 1, [when not building a shared library]) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + ;; + *) + AC_MSG_RESULT(no) + ;; +esac + dnl ********************************************************************** dnl platform/compiler/architecture specific checks/flags dnl ********************************************************************** @@ -144,6 +164,7 @@ esac CARES_CHECK_COMPILER_HALT_ON_ERROR CARES_CHECK_COMPILER_ARRAY_SIZE_NEGATIVE +CARES_CHECK_COMPILER_HIDDEN_SYMBOLS CARES_CHECK_NO_UNDEFINED AM_CONDITIONAL(NO_UNDEFINED, test x$need_no_undefined = xyes) @@ -876,6 +897,8 @@ fi CARES_CHECK_OPTION_NONBLOCKING CARES_CHECK_NONBLOCKING_SOCKET +CARES_CONFIGURE_HIDDEN_SYMBOLS + CARES_PRIVATE_LIBS="$LIBS" AC_SUBST(CARES_PRIVATE_LIBS) diff --git a/m4/cares-compilers.m4 b/m4/cares-compilers.m4 index e4fd1ec..77e4651 100644 --- a/m4/cares-compilers.m4 +++ b/m4/cares-compilers.m4 @@ -16,7 +16,7 @@ #*************************************************************************** # File version for 'aclocal' use. Keep it a single number. -# serial 56 +# serial 59 dnl CARES_CHECK_COMPILER @@ -1249,6 +1249,100 @@ AC_DEFUN([CARES_CHECK_COMPILER_ARRAY_SIZE_NEGATIVE], [ ]) +dnl CARES_CHECK_COMPILER_HIDDEN_SYMBOLS +dnl ------------------------------------------------- +dnl Verify if compiler supports hiding library internal symbols, setting +dnl shell variable hidden_symbols_supported value as appropriate, as well +dnl as variable hidden_symbols_CFLAGS when supported. + +AC_DEFUN([CARES_CHECK_COMPILER_HIDDEN_SYMBOLS], [ + AC_REQUIRE([CARES_CHECK_COMPILER])dnl + AC_BEFORE([$0],[CARES_CONFIGURE_HIDDEN_SYMBOLS])dnl + AC_MSG_CHECKING([if compiler supports hiding library internal symbols]) + hidden_symbols_supported="no" + hidden_symbols_CFLAGS="" + tmp_CFLAGS="" + tmp_extern="" + case "$compiler_id" in + GNU_C) + dnl Only gcc 3.4 or later + if test "$compiler_num" -ge "304"; then + if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then + tmp_extern="__attribute__ ((visibility (\"default\")))" + tmp_CFLAGS="-fvisibility=hidden" + hidden_symbols_supported="yes" + echo " " >&6 + echo "debug: should work with this compiler and version" >&6 + echo " " >&6 + fi + fi + ;; + INTEL_UNIX_C) + dnl Only icc 9.0 or later + if test "$compiler_num" -ge "900"; then + if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then + tmp_extern="__attribute__ ((visibility (\"default\")))" + tmp_CFLAGS="-fvisibility=hidden" + hidden_symbols_supported="yes" + echo " " >&6 + echo "debug: should work with this compiler and version" >&6 + echo " " >&6 + fi + fi + ;; + SUNPRO_C) + if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then + tmp_extern="__global" + tmp_CFLAGS="-xldscope=hidden" + hidden_symbols_supported="yes" + echo " " >&6 + echo "debug: should work with this compiler and version" >&6 + echo " " >&6 + fi + ;; + esac + if test "$hidden_symbols_supported" = "yes"; then + tmp_save_CFLAGS="$CFLAGS" + CFLAGS="$tmp_save_CFLAGS $tmp_CFLAGS" + squeeze CFLAGS + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + $tmp_extern char *dummy(char *buff); + char *dummy(char *buff) + { + if(buff) + return ++buff; + else + return buff; + } + ]],[[ + char b[16]; + char *r = dummy(&b); + if(r) + return (int)*r; + ]]) + ],[ + hidden_symbols_supported="yes" + ],[ + hidden_symbols_supported="no" + sed 's/^/cc-src: /' conftest.$ac_ext >&6 + sed 's/^/cc-err: /' conftest.err >&6 + ]) + CFLAGS="$tmp_save_CFLAGS" + fi + if test "$hidden_symbols_supported" = "yes"; then + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED(CARES_HIDDEN_SYMBOLS, 1, + [Define to 1 to enable hiding of library internal symbols.]) + AC_DEFINE_UNQUOTED(CARES_EXTERN_SYMBOL, $tmp_extern, + [Definition to make a library symbol externally visible.]) + hidden_symbols_CFLAGS="$tmp_CFLAGS" + else + AC_MSG_RESULT([no]) + fi +]) + + dnl CARES_CHECK_COMPILER_STRUCT_MEMBER_SIZE dnl ------------------------------------------------- dnl Verifies if the compiler is capable of handling the diff --git a/m4/cares-confopts.m4 b/m4/cares-confopts.m4 index cc03a09..5af3232 100644 --- a/m4/cares-confopts.m4 +++ b/m4/cares-confopts.m4 @@ -16,7 +16,7 @@ #*************************************************************************** # File version for 'aclocal' use. Keep it a single number. -# serial 5 +# serial 6 dnl CARES_CHECK_OPTION_CURLDEBUG @@ -92,6 +92,46 @@ AC_HELP_STRING([--disable-debug],[Disable debug build options]), ]) +dnl CARES_CHECK_OPTION_HIDDEN_SYMBOLS +dnl ------------------------------------------------- +dnl Verify if configure has been invoked with option +dnl --enable-hidden-symbols or --disable-hidden-symbols, +dnl setting shell variable want_hidden_symbols value. + +AC_DEFUN([CARES_CHECK_OPTION_HIDDEN_SYMBOLS], [ + AC_BEFORE([$0],[CARES_CHECK_COMPILER_HIDDEN_SYMBOLS])dnl + AC_MSG_CHECKING([whether to enable hiding symbols]) + OPT_HIDDEN_SYMBOLS="default" + AC_ARG_ENABLE(hidden-symbols, +AC_HELP_STRING([--enable-hidden-symbols],[Enable hiding of library internal symbols]) +AC_HELP_STRING([--disable-hidden-symbols],[Disable hiding of library internal symbols]), + OPT_HIDDEN_SYMBOLS=$enableval) + case "$OPT_HIDDEN_SYMBOLS" in + no) + dnl --disable-hidden-symbols option used. + dnl This is an indication to not attempt hiding of library internal + dnl symbols. Default symbol visibility will be used, which normally + dnl exposes all library internal symbols. + want_hidden_symbols="no" + AC_MSG_RESULT([no]) + ;; + default) + dnl configure's hidden-symbols option not specified. + dnl Handle this as if --enable-hidden-symbols option was given. + want_hidden_symbols="yes" + AC_MSG_RESULT([not specified (assuming yes)]) + ;; + *) + dnl --enable-hidden-symbols option used. + dnl This is an indication to attempt hiding of library internal + dnl symbols. This is only supported on some compilers/linkers. + want_hidden_symbols="yes" + AC_MSG_RESULT([yes]) + ;; + esac +]) + + dnl CARES_CHECK_OPTION_NONBLOCKING dnl ------------------------------------------------- dnl Verify if configure has been invoked with option @@ -252,3 +292,24 @@ AC_DEFUN([CARES_CHECK_NONBLOCKING_SOCKET], [ fi ]) + +dnl CARES_CONFIGURE_HIDDEN_SYMBOLS +dnl ------------------------------------------------- +dnl Depending on --enable-hidden-symbols or --disable-hidden-symbols +dnl configure option, and compiler capability to actually honor such +dnl option, compiler flags will be modified as appropriate. +dnl This macro should not be used until all compilation tests have +dnl been done to prevent interferences on other tests. + +AC_DEFUN([CARES_CONFIGURE_HIDDEN_SYMBOLS], [ + AC_MSG_CHECKING([whether to actually hide library internal symbols]) + if test "$want_hidden_symbols" = "yes" && + test "$hidden_symbols_supported" = "yes"; then + tmp_save_CFLAGS="$CFLAGS" + CFLAGS="$tmp_save_CFLAGS $hidden_symbols_CFLAGS" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi +]) + -- 2.7.4