diff --git a/configure b/configure
index b7635e4..64bde7b 100755
--- a/configure
+++ b/configure
@@ -290,6 +290,7 @@ if test "$debug_info" = "yes"; then
     CFLAGS="-g $CFLAGS"
     LDFLAGS="-g $LDFLAGS"
 fi
+QEMU_DLL_CFLAGS=""
 
 # make source path absolute
 source_path=`cd "$source_path"; pwd`
@@ -1276,6 +1277,21 @@ EOF
   fi
 fi
 
+# GNUC symbol hiding macro
+cat > $TMPC << EOF
+#if defined(__GNUC__) && __GNUC__ >= 4
+int main(void) { return 0; }
+#else
+#error GNUC with verison >=4 not found.
+#endif
+EOF
+if compile_prog "-Werror" "" ; then
+  QEMU_DLL_CFLAGS="-fvisibility=hidden $QEMU_DLL_CFLAGS"
+  QEMU_CFLAGS="-D QEMU_DLL_PUBLIC='__attribute__((__visibility__(\"default\")))' $QEMU_CFLAGS"
+else
+  QEMU_CFLAGS="-D QEMU_DLL_PUBLIC='' $QEMU_CFLAGS"
+fi
+
 #
 # Solaris specific configure tool chain decisions
 #
@@ -3263,6 +3279,7 @@ echo "Host C compiler   $host_cc"
 echo "Objective-C compiler $objcc"
 echo "CFLAGS            $CFLAGS"
 echo "QEMU_CFLAGS       $QEMU_CFLAGS"
+echo "QEMU_DLL_CFLAGS   $QEMU_DLL_CFLAGS"
 echo "LDFLAGS           $LDFLAGS"
 echo "make              $make"
 echo "install           $install"
@@ -3770,6 +3787,7 @@ echo "WINDRES=$windres" >> $config_host_mak
 echo "LIBTOOL=$libtool" >> $config_host_mak
 echo "CFLAGS=$CFLAGS" >> $config_host_mak
 echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
+echo "QEMU_DLL_CFLAGS=$QEMU_DLL_CFLAGS" >> $config_host_mak
 echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
 if test "$sparse" = "yes" ; then
   echo "CC           := REAL_CC=\"\$(CC)\" cgcc"       >> $config_host_mak
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 803ae17..916a57c 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -31,6 +31,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "qapi/qmp/qerror.h"
 
 /* misc helpers */
+QEMU_DLL_PUBLIC
 int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
 int socket_set_cork(int fd, int v);
diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index c02404b..8274173 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -18,15 +18,19 @@ typedef struct QemuThread QemuThread;
 #define QEMU_THREAD_JOINABLE 0
 #define QEMU_THREAD_DETACHED 1
 
+QEMU_DLL_PUBLIC
 void qemu_mutex_init(QemuMutex *mutex);
 void qemu_mutex_destroy(QemuMutex *mutex);
+QEMU_DLL_PUBLIC
 void qemu_mutex_lock(QemuMutex *mutex);
 int qemu_mutex_trylock(QemuMutex *mutex);
+QEMU_DLL_PUBLIC
 void qemu_mutex_unlock(QemuMutex *mutex);
 
 #define rcu_read_lock() do { } while (0)
 #define rcu_read_unlock() do { } while (0)
 
+QEMU_DLL_PUBLIC
 void qemu_cond_init(QemuCond *cond);
 void qemu_cond_destroy(QemuCond *cond);
 
@@ -35,8 +39,10 @@ void qemu_cond_destroy(QemuCond *cond);
  * and pthread_cond_broadcast can be called except while the same mutex is
  * held as in the corresponding pthread_cond_wait calls!
  */
+QEMU_DLL_PUBLIC
 void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
+QEMU_DLL_PUBLIC
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
 
 void qemu_sem_init(QemuSemaphore *sem, int init);
diff --git a/libcacard/cac.h b/libcacard/cac.h
index 15a61be..c7b85f2 100644
--- a/libcacard/cac.h
+++ b/libcacard/cac.h
@@ -13,11 +13,13 @@
  * Initialize the cac card. This is the only public function in this file. All
  * the rest are connected through function pointers.
  */
+QEMU_DLL_PUBLIC
 VCardStatus cac_card_init(VReader *reader, VCard *card, const char *params,
               unsigned char * const *cert, int cert_len[],
               VCardKey *key[] /* adopt the keys*/,
               int cert_count);
 
 /* not yet implemented */
+QEMU_DLL_PUBLIC
 VCardStatus cac_is_cac_card(VReader *reader);
 #endif
diff --git a/libcacard/card_7816.h b/libcacard/card_7816.h
index 4a01993..207385a 100644
--- a/libcacard/card_7816.h
+++ b/libcacard/card_7816.h
@@ -14,21 +14,26 @@
  * constructors for VCardResponse's
  */
 /* response from a return buffer and a status */
+QEMU_DLL_PUBLIC
 VCardResponse *vcard_response_new(VCard *card, unsigned char *buf, int len,
                                   int Le, vcard_7816_status_t status);
 /* response from a return buffer and status bytes */
+QEMU_DLL_PUBLIC
 VCardResponse *vcard_response_new_bytes(VCard *card, unsigned char *buf,
                                         int len, int Le,
                                         unsigned char sw1, unsigned char sw2);
 /* response from just status bytes */
+QEMU_DLL_PUBLIC
 VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
                                                unsigned char sw2);
 /* response from just status: NOTE this cannot fail, it will always return a
  * valid response, if it can't allocate memory, the response will be
  * VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE */
+QEMU_DLL_PUBLIC
 VCardResponse *vcard_make_response(vcard_7816_status_t status);
 
 /* create a raw response (status has already been encoded */
+QEMU_DLL_PUBLIC
 VCardResponse *vcard_response_new_data(unsigned char *buf, int len);
 
 
@@ -38,11 +43,13 @@ VCardResponse *vcard_response_new_data(unsigned char *buf, int len);
  * destructor for VCardResponse.
  *  Can be called with a NULL response
  */
+QEMU_DLL_PUBLIC
 void vcard_response_delete(VCardResponse *response);
 
 /*
  * constructor for VCardAPDU
  */
+QEMU_DLL_PUBLIC
 VCardAPDU *vcard_apdu_new(unsigned char *raw_apdu, int len,
                           unsigned short *status);
 
@@ -50,12 +57,14 @@ VCardAPDU *vcard_apdu_new(unsigned char *raw_apdu, int len,
  * destructor for VCardAPDU
  *  Can be called with a NULL apdu
  */
+QEMU_DLL_PUBLIC
 void vcard_apdu_delete(VCardAPDU *apdu);
 
 /*
  * APDU processing starts here. This routes the card processing stuff to the
  * right location. Always returns a valid response.
  */
+QEMU_DLL_PUBLIC
 VCardStatus vcard_process_apdu(VCard *card, VCardAPDU *apdu,
                                VCardResponse **response);
 
diff --git a/libcacard/vcard.h b/libcacard/vcard.h
index 47dc703..a7692ab 100644
--- a/libcacard/vcard.h
+++ b/libcacard/vcard.h
@@ -13,13 +13,16 @@
  * response buffers are used when we need to return more data than will fit in
  * a normal APDU response (nominally 254 bytes).
  */
+QEMU_DLL_PUBLIC
 VCardBufferResponse *vcard_buffer_response_new(unsigned char *buffer, int size);
+QEMU_DLL_PUBLIC
 void vcard_buffer_response_delete(VCardBufferResponse *buffer_response);
 
 
 /*
  * clean up state on reset
  */
+QEMU_DLL_PUBLIC
 void vcard_reset(VCard *card, VCardPower power);
 
 /*
@@ -28,6 +31,7 @@ void vcard_reset(VCard *card, VCardPower power);
 /*
  * Constructor for a VCardApplet
  */
+QEMU_DLL_PUBLIC
 VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function,
                               VCardResetApplet applet_reset_function,
                               unsigned char *aid, int aid_len);
@@ -36,51 +40,69 @@ VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function,
  * destructor for a VCardApplet
  *  Can be called with a NULL applet
  */
+QEMU_DLL_PUBLIC
 void vcard_delete_applet(VCardApplet *applet);
 
 /* accessor - set the card type specific private data */
+QEMU_DLL_PUBLIC
 void vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *_private,
                               VCardAppletPrivateFree private_free);
 
 /* set type of vcard */
+QEMU_DLL_PUBLIC
 void vcard_set_type(VCard *card, VCardType type);
 
 /*
  * utilities interacting with the current applet
  */
 /* add a new applet to a card */
+QEMU_DLL_PUBLIC
 VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
 /* find the applet on the card with the given aid */
+QEMU_DLL_PUBLIC
 VCardApplet *vcard_find_applet(VCard *card, unsigned char *aid, int aid_len);
 /* set the following applet to be current on the given channel */
+QEMU_DLL_PUBLIC
 void vcard_select_applet(VCard *card, int channel, VCardApplet *applet);
 /* get the card type specific private data on the given channel */
+QEMU_DLL_PUBLIC
 VCardAppletPrivate *vcard_get_current_applet_private(VCard *card, int channel);
 /* fetch the applet's id */
+QEMU_DLL_PUBLIC
 unsigned char *vcard_applet_get_aid(VCardApplet *applet, int *aid_len);
 
 /* process the apdu for the current selected applet/file */
+QEMU_DLL_PUBLIC
 VCardStatus vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu,
                                       VCardResponse **response);
 /*
  * VCard utilities
  */
 /* constructor */
+QEMU_DLL_PUBLIC
 VCard *vcard_new(VCardEmul *_private, VCardEmulFree private_free);
 /* get a reference */
+QEMU_DLL_PUBLIC
 VCard *vcard_reference(VCard *);
 /* destructor (reference counted) */
+QEMU_DLL_PUBLIC
 void vcard_free(VCard *);
 /* get the atr from the card */
+QEMU_DLL_PUBLIC
 void vcard_get_atr(VCard *card, unsigned char *atr, int *atr_len);
+QEMU_DLL_PUBLIC
 void vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr);
 
 /* accessor functions for the response buffer */
+QEMU_DLL_PUBLIC
 VCardBufferResponse *vcard_get_buffer_response(VCard *card);
+QEMU_DLL_PUBLIC
 void vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer);
 /* accessor functions for the type */
+QEMU_DLL_PUBLIC
 VCardType vcard_get_type(VCard *card);
 /* get the private data */
+QEMU_DLL_PUBLIC
 VCardEmul *vcard_get_private(VCard *card);
 
 #endif
diff --git a/libcacard/vcard_emul.h b/libcacard/vcard_emul.h
index 963563f..2081c73 100644
--- a/libcacard/vcard_emul.h
+++ b/libcacard/vcard_emul.h
@@ -36,8 +36,10 @@ typedef struct VCardEmulOptionsStruct VCardEmulOptions;
  */
 /* return the number of login attempts still possible on the card. if unknown,
  * return -1 */
+QEMU_DLL_PUBLIC
 int vcard_emul_get_login_count(VCard *card);
 /* login into the card, return the 7816 status word (sw2 || sw1) */
+QEMU_DLL_PUBLIC
 vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin,
                                      int pin_len);
 
@@ -45,21 +47,31 @@ vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin,
  * key functions
  */
 /* delete a key */
+QEMU_DLL_PUBLIC
 void vcard_emul_delete_key(VCardKey *key);
 /* RSA sign/decrypt with the key, signature happens 'in place' */
+QEMU_DLL_PUBLIC
 vcard_7816_status_t vcard_emul_rsa_op(VCard *card, VCardKey *key,
                                   unsigned char *buffer, int buffer_size);
 
+QEMU_DLL_PUBLIC
 void vcard_emul_reset(VCard *card, VCardPower power);
+QEMU_DLL_PUBLIC
 void vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len);
 
 /* Re-insert of a card that has been removed by force removal */
+QEMU_DLL_PUBLIC
 VCardEmulError vcard_emul_force_card_insert(VReader *vreader);
 /* Force a card removal even if the card is not physically removed */
+QEMU_DLL_PUBLIC
 VCardEmulError vcard_emul_force_card_remove(VReader *vreader);
 
+QEMU_DLL_PUBLIC
 VCardEmulOptions *vcard_emul_options(const char *args);
+QEMU_DLL_PUBLIC
 VCardEmulError vcard_emul_init(const VCardEmulOptions *options);
+QEMU_DLL_PUBLIC
 void vcard_emul_replay_insertion_events(void);
+QEMU_DLL_PUBLIC
 void vcard_emul_usage(void);
 #endif
diff --git a/libcacard/vcard_emul_type.h b/libcacard/vcard_emul_type.h
index 0242f40..08df160 100644
--- a/libcacard/vcard_emul_type.h
+++ b/libcacard/vcard_emul_type.h
@@ -23,10 +23,13 @@ typedef enum {
 } VCardEmulType;
 
 /* functions used by the rest of the emulator */
+QEMU_DLL_PUBLIC
 VCardStatus vcard_init(VReader *vreader, VCard *vcard, VCardEmulType type,
                        const char *params, unsigned char * const *cert,
                        int cert_len[], VCardKey *key[], int cert_count);
+QEMU_DLL_PUBLIC
 VCardEmulType vcard_emul_type_select(VReader *vreader);
+QEMU_DLL_PUBLIC
 VCardEmulType vcard_emul_type_from_string(const char *type_string);
 
 #endif
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d3e9522..10a9779 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -14,6 +14,14 @@
 #define MAX(x, y) ((x) > (y) ? (x) : (y))
 #endif
 
+/*
+ * In case libcacard is used by other project which have not defined
+ * QEMU_DLL_PUBLIC.
+ */
+#ifndef QEMU_DLL_PUBLIC
+#define QEMU_DLL_PUBLIC
+#endif
+
 typedef struct VCardStruct VCard;
 typedef struct VCardAPDUStruct VCardAPDU;
 typedef struct VCardResponseStruct VCardResponse;
diff --git a/libcacard/vevent.h b/libcacard/vevent.h
index 38c3482..80115ab 100644
--- a/libcacard/vevent.h
+++ b/libcacard/vevent.h
@@ -8,19 +8,25 @@
 #include "vreadert.h"
 #include "vcardt.h"
 
+QEMU_DLL_PUBLIC
 VEvent *vevent_new(VEventType type, VReader *reader, VCard *card);
+QEMU_DLL_PUBLIC
 void vevent_delete(VEvent *);
 
 /*
  * VEvent queueing services
  */
+QEMU_DLL_PUBLIC
 void vevent_queue_vevent(VEvent *);
+QEMU_DLL_PUBLIC
 void vevent_queue_init(void);
 
 /*
  *  VEvent dequeing services
  */
+QEMU_DLL_PUBLIC
 VEvent *vevent_wait_next_vevent(void);
+QEMU_DLL_PUBLIC
 VEvent *vevent_get_next_vevent(void);
 
 
diff --git a/libcacard/vreader.h b/libcacard/vreader.h
index ec20421..ac800f7 100644
--- a/libcacard/vreader.h
+++ b/libcacard/vreader.h
@@ -13,43 +13,66 @@
 /*
  * calls for reader front end
  */
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_power_on(VReader *reader, unsigned char *atr, int *len);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_power_off(VReader *reader);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_xfr_bytes(VReader *reader, unsigned char *send_buf,
                                 int send_buf_len, unsigned char *receive_buf,
                                 int *receive_buf_len);
 
 /* constructor */
+QEMU_DLL_PUBLIC
 VReader *vreader_new(const char *readerName, VReaderEmul *emul_private,
                      VReaderEmulFree private_free);
 /* get a new reference to a reader */
+QEMU_DLL_PUBLIC
 VReader *vreader_reference(VReader *reader);
 /* "destructor" (readers are reference counted) */
+QEMU_DLL_PUBLIC
 void vreader_free(VReader *reader);
 
 /* accessors */
+QEMU_DLL_PUBLIC
 VReaderEmul *vreader_get_private(VReader *);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_card_is_present(VReader *reader);
+QEMU_DLL_PUBLIC
 void vreader_queue_card_event(VReader *reader);
+QEMU_DLL_PUBLIC
 const char *vreader_get_name(VReader *reader);
+QEMU_DLL_PUBLIC
 vreader_id_t vreader_get_id(VReader *reader);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_set_id(VReader *reader, vreader_id_t id);
 
 /* list operations */
+QEMU_DLL_PUBLIC
 VReaderList *vreader_get_reader_list(void);
+QEMU_DLL_PUBLIC
 void vreader_list_delete(VReaderList *list);
+QEMU_DLL_PUBLIC
 VReader *vreader_list_get_reader(VReaderListEntry *entry);
+QEMU_DLL_PUBLIC
 VReaderListEntry *vreader_list_get_first(VReaderList *list);
+QEMU_DLL_PUBLIC
 VReaderListEntry *vreader_list_get_next(VReaderListEntry *list);
+QEMU_DLL_PUBLIC
 VReader *vreader_get_reader_by_id(vreader_id_t id);
+QEMU_DLL_PUBLIC
 VReader *vreader_get_reader_by_name(const char *name);
 
 /*
  * list tools for vcard_emul
  */
+QEMU_DLL_PUBLIC
 void vreader_init(void);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_add_reader(VReader *reader);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_remove_reader(VReader *reader);
+QEMU_DLL_PUBLIC
 VReaderStatus vreader_insert_card(VReader *reader, VCard *card);
 
 #endif
diff --git a/rules.mak b/rules.mak
index 6d82c0d..09ec69f 100644
--- a/rules.mak
+++ b/rules.mak
@@ -27,6 +27,7 @@ LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
        $(LIBS),"  LINK  $(TARGET_DIR)$@")
 else
 LIBTOOL += $(if $(V),,--quiet)
+%.lo: QEMU_CFLAGS += $(QEMU_DLL_CFLAGS)
 %.lo: %.c
 	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  lt CC $@")
 %.lo: %.dtrace
