Subject: duplicate symbols when linking libbind.a programs statically
To: None <current-users@netbsd.org>
From: Todd Whitesel <toddpw@best.com>
List: current-users
Date: 12/13/1998 10:54:37
There appears to be some duplicated functionality in libbind.a and libc.a,
and due to differences in .o partitioning and exposed labels, duplicate
symbol errors are produced when statically linking 'dig' and various other
bind-related programs. Excerpt of 'make build' output:

all ===> usr.sbin/bind/dig
cc -O  -Werror   -I. -I/usr/src/usr.sbin/bind/dig/../include -c dig.c
cc -O  -Werror   -I. -I/usr/src/usr.sbin/bind/dig/../include -c /usr/src/usr.sbin/bind/dig/../nslookup/subr.c
cc -O  -Werror   -I. -I/usr/src/usr.sbin/bind/dig/../include -c /usr/src/usr.sbin/bind/dig/../nslookup/send.c
cc -O  -Werror   -I. -I/usr/src/usr.sbin/bind/dig/../include -c /usr/src/usr.sbin/bind/dig/../nslookup/list.c
cc -O  -Werror   -I. -I/usr/src/usr.sbin/bind/dig/../include -c /usr/src/usr.sbin/bind/dig/../nslookup/debug.c
cc  -static -o dig dig.o subr.o send.o list.o debug.o -L/usr/src/usr.sbin/bind/lib/ -lbind
/usr/src/usr.sbin/bind/lib//libbind.a(res_init.o): Definition of symbol `___res_randomid' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(inet_addr.o): Definition of symbol `_inet_addr' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(inet_addr.o): Definition of symbol `_inet_aton' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `__getshort' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___putshort' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___dn_skipname' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `__getlong' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___res_hnok' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___putlong' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___res_dnok' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___dn_comp' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___res_ownok' (multiply defined)
/usr/src/usr.sbin/bind/lib//libbind.a(res_comp.o): Definition of symbol `___res_mailok' (multiply defined)
/usr/lib/libc.a(res_init.o): Definition of symbol `___res_randomid' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `__getshort' (multiply define)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___putshort' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___dn_skipname' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `__getlong' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___res_hnok' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___putlong' (multiply define)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___res_dnok' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___dn_comp' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___res_ownok' (multiply defined)
/usr/lib/libc.a(res_comp.o): Definition of symbol `___res_mailok' (multiply defined)
/usr/lib/libc.a(inet_pton.o): Definition of symbol `_inet_addr' (multiply defined)
/usr/lib/libc.a(inet_pton.o): Definition of symbol `_inet_aton' (multiply defined)
collect2: ld returned 1 exit status
*** Error code 1

Stop.

This was discovered while building -current -static on arm32. My mk.conf:
	UVM=1
	LDSTATIC=-static
	NOPIC=1

The conflict comes from funky defines that add two underscores to many of
the identifiers in libbind.a, and libc.a references to the single-underscore
versions from elsewhere in libc, which yank in the libc version of a .o that
has already been pulled in from libbind -- thus the labels they both export
cause duplicate definition errors. Here is a set of kludgy patches that get
things to build, hopefully with no subtle behavioral dependency problems.

Index: ./usr.sbin/bind/lib/inet/Makefile.inc
--- ./usr.sbin/bind/lib/inet/Makefile.inc.orig	Sat Dec 12 18:46:37 1998
+++ ./usr.sbin/bind/lib/inet/Makefile.inc	Sat Dec 12 18:58:59 1998
@@ -2,6 +2,6 @@
 
 .PATH: ${.CURDIR}/inet
 
-SRCS+=	nsap_addr.c inet_addr.c inet_ntop.c inet_pton.c \
+SRCS+=	nsap_addr.c inet_ntop.c \
 	inet_ntoa.c inet_neta.c inet_net_ntop.c inet_net_pton.c \
 	inet_lnaof.c inet_makeaddr.c inet_netof.c inet_network.c
Index: ./usr.sbin/bind/lib/resolv/res_init.c
--- ./usr.sbin/bind/lib/resolv/res_init.c.orig	Sat Dec 12 18:25:50 1998
+++ ./usr.sbin/bind/lib/resolv/res_init.c	Sat Dec 12 18:37:44 1998
@@ -481,3 +481,7 @@
 	gettimeofday(&now, NULL);
 	return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
 }
+
+#undef res_init
+
+int res_init() { return __res_init(); }
Index: ./usr.sbin/bind/lib/resolv/res_comp.c
--- ./usr.sbin/bind/lib/resolv/res_comp.c.orig	Sat Dec 12 18:40:19 1998
+++ ./usr.sbin/bind/lib/resolv/res_comp.c	Sat Dec 12 18:41:37 1998
@@ -249,3 +249,12 @@
 u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
 u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
 #endif /*BIND_4_COMPAT*/
+
+#undef dn_expand
+
+int
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+	  char *dst, int dstsiz)
+{
+	return __dn_expand(msg, eom, src, dst, dstsiz);
+}
Index: ./usr.sbin/bind/lib/resolv/res_query.c
--- ./usr.sbin/bind/lib/resolv/res_query.c.orig	Sat Dec 12 18:50:45 1998
+++ ./usr.sbin/bind/lib/resolv/res_query.c	Sat Dec 12 18:53:20 1998
@@ -408,3 +408,36 @@
 	fclose(fp);
 	return (NULL);
 }
+
+#undef res_query
+int
+res_query(name, class, type, answer, anslen)
+	const char *name;	/* domain name */
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer buffer */
+{
+	return __res_query(name, class, type, answer, anslen);
+}
+
+#undef res_search
+int
+res_search(name, class, type, answer, anslen)
+	const char *name;	/* domain name */
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer */
+{
+	return __res_search(name, class, type, answer, anslen);
+}
+
+#undef res_querydomain
+int
+res_querydomain(name, domain, class, type, answer, anslen)
+	const char *name, *domain;
+	int class, type;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer */
+{
+	return __res_querydomain(name, domain, class, type, answer, anslen);
+}
# eop

Todd Whitesel
toddpw @ best.com