During buildroot compilation with latest uClibc
I've encoutered linking error due to multiple definition
of some symbols from DNS code.
The error happens because the same file resolv.c
is included inside many other .c files:
res_comp.c:(.text+0x0): multiple definition of `__GI___dn_expand'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x8a0): first defined here
res_comp.c:(.text+0x0): multiple definition of `__dn_expand'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x8a0): first defined here
res_comp.c:(.text+0x34): multiple definition of `__GI___dn_comp'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xc68): first defined here
res_comp.c:(.text+0x34): multiple definition of `__dn_comp'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xc68): first defined here
ns_name.c:(.text+0x4c): multiple definition of `__GI___ns_name_ntop'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x4c): first defined here
ns_name.c:(.text+0x4c): multiple definition of `__ns_name_ntop'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x4c): first defined here
ns_name.c:(.text+0x1f8): multiple definition of `__GI___ns_name_pton'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x1f8): first defined here
ns_name.c:(.text+0x1f8): multiple definition of `__ns_name_pton'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x1f8): first defined here
ns_name.c:(.text+0x624): multiple definition of `__hnbad'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x624): first defined here
ns_name.c:(.text+0x718): multiple definition of `__GI___ns_name_unpack'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x718): first defined here
ns_name.c:(.text+0x718): multiple definition of `__ns_name_unpack'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x718): first defined here
ns_name.c:(.text+0x84c): multiple definition of `__GI___ns_name_uncompress'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x84c): first defined here
ns_name.c:(.text+0x84c): multiple definition of `__ns_name_uncompress'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x84c): first defined here
ns_name.c:(.text+0x8a0): multiple definition of `__GI___ns_name_pack'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x8d4): first defined here
ns_name.c:(.text+0x8a0): multiple definition of `__ns_name_pack'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0x8d4): first defined here
ns_name.c:(.text+0xbe4): multiple definition of `__GI___ns_name_compress'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xc18): first defined here
ns_name.c:(.text+0xbe4): multiple definition of `__ns_name_compress'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xc18): first defined here
ns_name.c:(.text+0xc34): multiple definition of `__GI___ns_name_skip'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xcdc): first defined here
ns_name.c:(.text+0xc34): multiple definition of `__ns_name_skip'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xcdc): first defined here
ns_name.c:(.text+0xcd4): multiple definition of `__GI___dn_skipname'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xd7c): first defined here
ns_name.c:(.text+0xcd4): multiple definition of `__dn_skipname'; libc/libc_so.a(encodeq.os):encodeq.c:(.text+0xd7c): first defined here
My previous commit that fixes build error of DNS code is okay,
but there are some 'bottlenecks' in uClibc-ng code, so if
we don't want to completely rewrite resolv.c we need to make some
symbols weak to prevent linking errors.
---
libc/inet/resolv.c | 42 +++++++++++++++++++++---------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 37842021c..d7a659a8c 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -2809,7 +2809,7 @@ libc_hidden_def(gethostbyaddr)
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
* Return size of compressed name or -1 if there was an error.
*/
-int dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+int weak_function dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
char *dst, int dstsiz)
{
int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
@@ -2818,14 +2818,14 @@ int dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
dst[0] = '\0';
return n;
}
-libc_hidden_def(dn_expand)
+libc_hidden_weak(dn_expand)
/*
* Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
* Return the size of the compressed name or -1.
* 'length' is the size of the array pointed to by 'comp_dn'.
*/
-int
+int weak_function
dn_comp(const char *src, u_char *dst, int dstsiz,
u_char **dnptrs, u_char **lastdnptr)
{
@@ -2833,7 +2833,7 @@ dn_comp(const char *src, u_char *dst, int dstsiz,
(const u_char **) dnptrs,
(const u_char **) lastdnptr);
}
-libc_hidden_def(dn_comp)
+libc_hidden_weak(dn_comp)
#endif /* L_res_comp */
@@ -2873,7 +2873,7 @@ static int special(int ch)
* note:
* Root domain returns as "." not "".
*/
-int ns_name_uncompress(const u_char *msg, const u_char *eom,
+int weak_function ns_name_uncompress(const u_char *msg, const u_char *eom,
const u_char *src, char *dst, size_t dstsiz)
{
u_char tmp[NS_MAXCDNAME];
@@ -2886,7 +2886,7 @@ int ns_name_uncompress(const u_char *msg, const u_char *eom,
return -1;
return n;
}
-libc_hidden_def(ns_name_uncompress)
+libc_hidden_weak(ns_name_uncompress)
/*
* ns_name_ntop(src, dst, dstsiz)
@@ -2897,7 +2897,7 @@ libc_hidden_def(ns_name_uncompress)
* The root is returned as "."
* All other domains are returned in non absolute form
*/
-int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
+int weak_function ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
{
const u_char *cp;
char *dn, *eom;
@@ -2967,7 +2967,7 @@ int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
*dn++ = '\0';
return (dn - dst);
}
-libc_hidden_def(ns_name_ntop)
+libc_hidden_weak(ns_name_ntop)
static int encode_bitstring(const char **bp, const char *end,
unsigned char **labelp,
@@ -3081,7 +3081,7 @@ static int encode_bitstring(const char **bp, const char *end,
return 0;
}
-int ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+int weak_function ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
{
static const char digits[] = "0123456789";
u_char *label, *bp, *eom;
@@ -3202,7 +3202,7 @@ int ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
errno = EMSGSIZE;
return -1;
}
-libc_hidden_def(ns_name_pton)
+libc_hidden_weak(ns_name_pton)
/*
* __hnbad(dotted)
@@ -3218,7 +3218,7 @@ libc_hidden_def(ns_name_pton)
* return:
* 0 if the name is ok
*/
-int __hnbad(const char *dotted)
+int weak_function __hnbad(const char *dotted)
{
unsigned char c, n, *cp;
unsigned char buf[NS_MAXCDNAME];
@@ -3255,7 +3255,7 @@ int __hnbad(const char *dotted)
* return:
* -1 if it fails, or consumed octets if it succeeds.
*/
-int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+int weak_function ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
u_char *dst, size_t dstsiz)
{
const u_char *srcp, *dstlim;
@@ -3322,7 +3322,7 @@ int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
len = srcp - src;
return len;
}
-libc_hidden_def(ns_name_unpack)
+libc_hidden_weak(ns_name_unpack)
static int labellen(const unsigned char *lp)
{
@@ -3416,7 +3416,7 @@ next:
return -1;
}
-int ns_name_pack(const unsigned char *src,
+int weak_function ns_name_pack(const unsigned char *src,
unsigned char *dst, int dstsiz,
const unsigned char **dnptrs,
const unsigned char **lastdnptr)
@@ -3525,9 +3525,9 @@ cleanup:
return dstp - dst;
}
-libc_hidden_def(ns_name_pack)
+libc_hidden_weak(ns_name_pack)
-int ns_name_compress(const char *src,
+int weak_function ns_name_compress(const char *src,
unsigned char *dst, size_t dstsiz,
const unsigned char **dnptrs,
const unsigned char **lastdnptr)
@@ -3539,9 +3539,9 @@ int ns_name_compress(const char *src,
return ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr);
}
-libc_hidden_def(ns_name_compress)
+libc_hidden_weak(ns_name_compress)
-int ns_name_skip(const unsigned char **ptrptr,
+int weak_function ns_name_skip(const unsigned char **ptrptr,
const unsigned char *eom)
{
const unsigned char *cp;
@@ -3583,9 +3583,9 @@ int ns_name_skip(const unsigned char **ptrptr,
return 0;
}
-libc_hidden_def(ns_name_skip)
+libc_hidden_weak(ns_name_skip)
-int dn_skipname(const unsigned char *ptr, const unsigned char *eom)
+int weak_function dn_skipname(const unsigned char *ptr, const unsigned char *eom)
{
const unsigned char *saveptr = ptr;
@@ -3594,7 +3594,7 @@ int dn_skipname(const unsigned char *ptr, const unsigned char *eom)
return ptr - saveptr;
}
-libc_hidden_def(dn_skipname)
+libc_hidden_weak(dn_skipname)
#endif /* L_ns_name */
--
2.43.2
The (glibc) documentation for _DEFAULT_SOURCE states:
The "default" definitions comprise those required by
POSIX.1-2008 and ISO C99, as well as various definitions
originally derived from BSD and System V. On glibc 2.19
and earlier, these defaults were approximately equivalent
to explicitly defining the following:
cc -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809
It also states that _BSD_SOURCE and _SVID_SOURCE are deprecated, and
have the same effect as setting _DEFAULT_SOURCE.
Therefore, when any of _BSD_SOURCE, _SVID_SOURCE or _DEFAULT_SOURCE is
set, the three macros should be set, and POSIX 2008.09 compatibility
should be enabled.
Signed-off-by: Paul Cercueil <paul(a)crapouillou.net>
---
include/features.h | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/features.h b/include/features.h
index d6e45c2ff..11b34205f 100644
--- a/include/features.h
+++ b/include/features.h
@@ -40,7 +40,8 @@
_SVID_SOURCE ISO C, POSIX, and SVID things.
_ATFILE_SOURCE Additional *at interfaces.
_GNU_SOURCE All of the above, plus GNU extensions.
- _DEFAULT_SOURCE Equivalent to defining _BSD_SOURCE and _SVID_SOURCE.
+ _DEFAULT_SOURCE Equivalent to defining _BSD_SOURCE and _SVID_SOURCE,
+ as well as _POSIX_C_SOURCE=200809L.
_REENTRANT Select additionally reentrant object.
_THREAD_SAFE Same as _REENTRANT, often used by other systems.
_FORTIFY_SOURCE If set to numeric value > 0 additional security
@@ -142,18 +143,19 @@
/* Whether to use feature set F. */
#define __GLIBC_USE(F) __GLIBC_USE_ ## F
-/* _DEFAULT_SOURCE is equivalent to defining _BSD_SOURCE and _SVID_SOURCE
- * and vice versa. */
-#ifdef _DEFAULT_SOURCE
+/* _DEFAULT_SOURCE is equivalent to defining _BSD_SOURCE, _SVID_SOURCE
+ * and _POSIX_C_SOURCE=200809L and vice versa. */
+#if defined _DEFAULT_SOURCE || defined _BSD_SOURCE || defined _SVID_SOURCE
+# undef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE 1
# undef _BSD_SOURCE
# define _BSD_SOURCE 1
# undef _SVID_SOURCE
# define _SVID_SOURCE 1
-#endif
-
-#if defined _BSD_SOURCE || defined _SVID_SOURCE
-# undef _DEFAULT_SOURCE
-# define _DEFAULT_SOURCE 1
+# if _POSIX_C_SOURCE < 200809L
+# undef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200809L
+# endif
#endif
/* If _GNU_SOURCE was defined by the user, turn on all the other features. */
--
2.43.0
While compiling OpenADK I discovered that
there may be a case where UCLIBC_EXTRA_LDFLAGS
contains `-fpie -pie`. Linker ignores `-shared`
if `-pie` flag is passed after and produces
an executable binary instead of shared object.
This leads to linking failure because `ld-uClibc.so.1`
becomes executable instead of shared object.
`ld-uClibc.so.1` is used as one of the inputs
when linking of libc.so.1 and linking proccess fails.
To prevent this issue we need to pass extra `-shared` flag
in `link.so` target command after all other flags to overwrite
`-pie` effect.
Signed-off-by: Dmitry Chestnykh <dm.chestnykh(a)gmail.com>
---
Makerules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makerules b/Makerules
index 1a7443c39..fe8a7916e 100644
--- a/Makerules
+++ b/Makerules
@@ -334,7 +334,7 @@ define link.so
-Wl,-soname=$(notdir $(a)).$(2) \
$(CFLAG_-nostdlib) $(CFLAG_-nostartfiles) \
-o $(dir $@)$(1) $(START_FILE-$(notdir $@)) \
- -Wl,--whole-archive $(firstword $^) -Wl,--no-whole-archive \
+ -Wl,--whole-archive $(firstword $^) -Wl,--no-whole-archive -shared \
$(LIBS-$(notdir $@)) $(LIBGCC) $(END_FILE-$(notdir $@))
$(Q)$(LN) -sf $(1) $@.$(2)
$(Q)$(LN) -sf $(1) $@
--
2.43.0
- The first observed issue is linking failure:
`
/usr/bin/ld: libc/libc_so.a(encodeq.os): in function `__encode_question':
encodeq.c:(.text+0x16): undefined reference to `__GI___dn_comp'
/usr/bin/ld: libc/libc_so.a(dnslookup.os): in function `__dns_lookup':
dnslookup.c:(.text+0x6fb): undefined reference to `__GI___dn_expand'
/usr/bin/ld: dnslookup.c:(.text+0x7ab): undefined reference to `__hnbad'
collect2: error: ld returned 1 exit status
`
The root cause is that the resolv.c file contains
some functions (dn_comp, dn_expand, __hnbad)
under `#ifdef L_ns_name` and `#ifdef L_ns_comp`
which wasn't defined, so we had undefined refs to such functions.
- The second issue is misleading indentation inside `ns_name_pack`.
`
libc/inet/resolv.c: In function '__ns_name_pack':
libc/inet/resolv.c:3519:17: warning: this 'if' clause does not guard...
3519 | if (msg != NULL)
...
./include/errno.h:73:18: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
73 | # define errno errno /* For #ifndef errno tests. */
| ^~~~~
libc/inet/resolv.c:3522:25: note: in expansion of macro 'errno'
3522 | errno = EMSGSIZE;
`
Signed-off-by: Dmitry Chestnykh <dm.chestnykh(a)gmail.com>
---
libc/inet/encodeq.c | 2 ++
libc/inet/resolv.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/libc/inet/encodeq.c b/libc/inet/encodeq.c
index 5555aa548..dc7945bc6 100644
--- a/libc/inet/encodeq.c
+++ b/libc/inet/encodeq.c
@@ -5,4 +5,6 @@
*/
#define L_encodeq
+#define L_ns_name
+#define L_res_comp
#include RESOLVER
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 2f627ca08..37842021c 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -3519,8 +3519,8 @@ cleanup:
if (msg != NULL)
*lpp = NULL;
- errno = EMSGSIZE;
- return -1;
+ errno = EMSGSIZE;
+ return -1;
}
return dstp - dst;
--
2.43.0