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.
This commit is contained in:
Yang Tse 2009-10-28 19:45:26 +00:00
parent 9fced16efb
commit 0d9f14f5c1
5 changed files with 370 additions and 72 deletions

View File

@ -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

View File

@ -45,9 +45,9 @@
#endif
#if defined(WATT32)
#include <netinet/in.h>
#include <sys/socket.h>
#include <tcp.h>
# include <netinet/in.h>
# include <sys/socket.h>
# include <tcp.h>
#elif defined(WIN32)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
@ -56,14 +56,36 @@
# include <winsock2.h>
# include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
# include <sys/socket.h>
# include <netinet/in.h>
#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 type,
void *data);
int ares_library_init(int flags);
void ares_library_cleanup(void);
const char *ares_version(int *version);
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);
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);
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
}

View File

@ -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)

View File

@ -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

View File

@ -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
])