Merge "libc: Copy private C library declarations to private/"
diff --git a/libc/kernel/README.TXT b/libc/kernel/README.TXT
index 76dfa4d..9ff97d6 100644
--- a/libc/kernel/README.TXT
+++ b/libc/kernel/README.TXT
@@ -56,7 +56,7 @@
* tools/update_all.py
automatically update all clean headers from the content of
- 'bionic/kernel/original'. this is the script you're likely going to
+ 'external/kernel-headers/original'. this is the script you're likely going to
run whenever you update the original headers.
NOTE:
diff --git a/libc/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index 0549fc2..22e62aa 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -37,7 +37,7 @@
src_path = src_path[1:]
if len(src_path) == 0:
- panic( "oops, internal error, can't extract correct relative path" )
+ panic( "oops, internal error, can't extract correct relative path\n" )
# convert into destination path, extracting architecture if needed
# and the corresponding list of known static functions
diff --git a/libc/kernel/tools/update_all.py b/libc/kernel/tools/update_all.py
index 6a730a5..badef92 100755
--- a/libc/kernel/tools/update_all.py
+++ b/libc/kernel/tools/update_all.py
@@ -37,13 +37,13 @@
progdir = find_program_dir()
if len(args) == 1:
- original_dir = arg[0]
+ original_dir = args[0]
if not os.path.isdir(original_dir):
- panic( "Not a directory: %s" % original_dir )
+ panic( "Not a directory: %s\n" % original_dir )
else:
original_dir = kernel_original_path
if not os.path.isdir(original_dir):
- panic( "Missing directory, please specify one through command-line: %s" % original_dir )
+ panic( "Missing directory, please specify one through command-line: %s\n" % original_dir )
# find all source files in 'original'
#
diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c
index b118956..5d25087 100644
--- a/libc/netbsd/resolv/res_send.c
+++ b/libc/netbsd/resolv/res_send.c
@@ -99,6 +99,7 @@
#include <arpa/inet.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#ifdef ANDROID_CHANGES
#include "resolv_private.h"
@@ -109,6 +110,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <isc/eventlib.h>
@@ -117,6 +119,8 @@
# include <resolv_cache.h>
#endif
+#include "logd.h"
+
#ifndef DE_CONST
#define DE_CONST(c,v) v = ((c) ? \
strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
@@ -130,6 +134,7 @@
#include "res_private.h"
#define EXT(res) ((res)->_u._ext)
+#define DBG 0
static const int highestFD = FD_SETSIZE - 1;
@@ -152,7 +157,10 @@
const sigset_t *);
#endif
void res_pquery(const res_state, const u_char *, int, FILE *);
-
+static int connect_with_timeout(int sock, const struct sockaddr *nsap,
+ socklen_t salen, int sec);
+static int retrying_select(const int sock, fd_set *readset, fd_set *writeset,
+ const struct timespec *finish);
/* BIONIC-BEGIN: implement source port randomization */
typedef union {
@@ -521,16 +529,23 @@
Dprint(((statp->options & RES_DEBUG) &&
getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
- NULL, 0, niflags) == 0),
- (stdout, ";; Querying server (# %d) address = %s\n",
- ns + 1, abuf));
+ NULL, 0, niflags) == 0),
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, abuf));
if (v_circuit) {
/* Use VC; at most one attempt per server. */
try = statp->retry;
+
n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
ns);
+
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ "used send_vc %d\n", n);
+ }
+
if (n < 0)
goto fail;
if (n == 0)
@@ -538,12 +553,26 @@
resplen = n;
} else {
/* Use datagrams. */
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ "using send_dg\n");
+ }
+
n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
ns, &v_circuit, &gotsomewhere);
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ "used send_dg %d\n",n);
+ }
+
if (n < 0)
goto fail;
if (n == 0)
goto next_ns;
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ "time=%d, %d\n",time(NULL), time(NULL)%2);
+ }
if (v_circuit)
goto same_ns;
resplen = n;
@@ -668,6 +697,23 @@
}
}
+static int get_timeout(const res_state statp, const int ns)
+{
+ int timeout = (statp->retrans << ns);
+ if (ns > 0) {
+ timeout /= statp->nscount;
+ }
+ if (timeout <= 0) {
+ timeout = 1;
+ }
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ "using timeout of %d sec\n", timeout);
+ }
+
+ return timeout;
+}
+
static int
send_vc(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz,
@@ -683,6 +729,10 @@
u_char *cp;
void *tmp;
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
+ }
+
nsap = get_nsaddr(statp, (size_t)ns);
nsaplen = get_salen(nsap);
@@ -735,7 +785,8 @@
res_nclose(statp);
return (0);
}
- if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
+ if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
+ get_timeout(statp, ns)) < 0) {
*terrno = errno;
Aerror(statp, stderr, "connect/vc", errno, nsap,
nsaplen);
@@ -859,6 +910,111 @@
return (resplen);
}
+/* return -1 on error (errno set), 0 on success */
+static int
+connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec)
+{
+ int res, origflags;
+ fd_set rset, wset;
+ struct timespec now, timeout, finish;
+
+ origflags = fcntl(sock, F_GETFL, 0);
+ fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
+
+ res = connect(sock, nsap, salen);
+ if (res < 0 && errno != EINPROGRESS) {
+ res = -1;
+ goto done;
+ }
+ if (res != 0) {
+ now = evNowTime();
+ timeout = evConsTime((long)sec, 0L);
+ finish = evAddTime(now, timeout);
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ " %d send_vc\n", sock);
+ }
+
+ res = retrying_select(sock, &rset, &wset, &finish);
+ if (res <= 0) {
+ res = -1;
+ }
+ }
+done:
+ fcntl(sock, F_SETFL, origflags);
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ " %d connect_with_timeout returning %s\n", sock, res);
+ }
+ return res;
+}
+
+static int
+retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish)
+{
+ struct timespec now, timeout;
+ int n, error;
+ socklen_t len;
+
+
+retry:
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc", " %d retying_select\n", sock);
+ }
+
+ now = evNowTime();
+ if (readset) {
+ FD_ZERO(readset);
+ FD_SET(sock, readset);
+ }
+ if (writeset) {
+ FD_ZERO(writeset);
+ FD_SET(sock, writeset);
+ }
+ if (evCmpTime(*finish, now) > 0)
+ timeout = evSubTime(*finish, now);
+ else
+ timeout = evConsTime(0L, 0L);
+
+ n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
+ if (n == 0) {
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, " libc",
+ " %d retrying_select timeout\n", sock);
+ }
+ errno = ETIMEDOUT;
+ return 0;
+ }
+ if (n < 0) {
+ if (errno == EINTR)
+ goto retry;
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ " %d retrying_select got error %d\n",sock, n);
+ }
+ return n;
+ }
+ if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) {
+ len = sizeof(error);
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
+ errno = error;
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ " %d retrying_select dot error2 %d\n", sock, errno);
+ }
+
+ return -1;
+ }
+ }
+ if (DBG) {
+ __libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
+ " %d retrying_select returning %d for %d\n",sock, n);
+ }
+
+ return n;
+}
+
+
static int
send_dg(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz,
@@ -944,33 +1100,19 @@
/*
* Wait for reply.
*/
- seconds = (statp->retrans << ns);
- if (ns > 0)
- seconds /= statp->nscount;
- if (seconds <= 0)
- seconds = 1;
+ seconds = get_timeout(statp, ns);
now = evNowTime();
timeout = evConsTime((long)seconds, 0L);
finish = evAddTime(now, timeout);
- goto nonow;
- wait:
- now = evNowTime();
- nonow:
- FD_ZERO(&dsmask);
- FD_SET(s, &dsmask);
- if (evCmpTime(finish, now) > 0)
- timeout = evSubTime(finish, now);
- else
- timeout = evConsTime(0L, 0L);
- n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+retry:
+ n = retrying_select(s, &dsmask, NULL, &finish);
+
if (n == 0) {
Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
*gotsomewhere = 1;
return (0);
}
if (n < 0) {
- if (errno == EINTR)
- goto wait;
Perror(statp, stderr, "select", errno);
res_nclose(statp);
return (0);
@@ -1006,7 +1148,7 @@
(statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer:\n"),
ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
+ goto retry;
}
if (!(statp->options & RES_INSECURE1) &&
!res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
@@ -1019,7 +1161,7 @@
(statp->pfcode & RES_PRF_REPLY),
(stdout, ";; not our server:\n"),
ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
+ goto retry;
}
#ifdef RES_USE_EDNS0
if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
@@ -1049,7 +1191,7 @@
(statp->pfcode & RES_PRF_REPLY),
(stdout, ";; wrong query name:\n"),
ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
+ goto retry;;
}
if (anhp->rcode == SERVFAIL ||
anhp->rcode == NOTIMP ||
diff --git a/linker/README.TXT b/linker/README.TXT
index a8efe35..f920b97 100644
--- a/linker/README.TXT
+++ b/linker/README.TXT
@@ -87,6 +87,7 @@
present in executables, not shared libraries, which contains
a list of functions that need to be called before any other
initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY)
+ in the executable or any of its libraries.
Note: this is generally stored in a .preinit_array section
diff --git a/linker/dlfcn.c b/linker/dlfcn.c
index 7161455..62dde2f 100644
--- a/linker/dlfcn.c
+++ b/linker/dlfcn.c
@@ -60,6 +60,7 @@
if (unlikely(ret == NULL)) {
set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
} else {
+ call_constructors_recursive(ret);
ret->refcount++;
}
pthread_mutex_unlock(&dl_lock);
diff --git a/linker/linker.c b/linker/linker.c
index e4618e3..a692d62 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -1617,8 +1617,11 @@
}
}
-static void call_constructors(soinfo *si)
+void call_constructors_recursive(soinfo *si)
{
+ if (si->constructors_called)
+ return;
+
if (si->flags & FLAG_EXE) {
TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n",
pid, (unsigned)si->preinit_array, si->preinit_array_count,
@@ -1633,6 +1636,21 @@
}
}
+ if (si->dynamic) {
+ unsigned *d;
+ for(d = si->dynamic; *d; d += 2) {
+ if(d[0] == DT_NEEDED){
+ soinfo* lsi = (soinfo *)d[1];
+ if (!validate_soinfo(lsi)) {
+ DL_ERR("%5d bad DT_NEEDED pointer in %s",
+ pid, si->name);
+ } else {
+ call_constructors_recursive(lsi);
+ }
+ }
+ }
+ }
+
if (si->init_func) {
TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid,
(unsigned)si->init_func, si->name);
@@ -1646,8 +1664,9 @@
call_array(si->init_array, si->init_array_count, 0);
TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name);
}
-}
+ si->constructors_called = 1;
+}
static void call_destructors(soinfo *si)
{
@@ -2046,7 +2065,6 @@
if (program_is_setuid)
nullify_closed_stdio ();
notify_gdb_of_load(si);
- call_constructors(si);
return 0;
fail:
@@ -2251,6 +2269,8 @@
exit(-1);
}
+ call_constructors_recursive(si);
+
#if ALLOW_SYMBOLS_FROM_MAIN
/* Set somain after we've loaded all the libraries in order to prevent
* linking of symbols back to the main image, which is not set up at that
diff --git a/linker/linker.h b/linker/linker.h
index aa1e5e7..c9e0309 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -149,6 +149,8 @@
unsigned refcount;
struct link_map linkmap;
+
+ int constructors_called;
};
@@ -217,6 +219,7 @@
soinfo *find_containing_library(const void *addr);
Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si);
const char *linker_get_error(void);
+void call_constructors_recursive(soinfo *si);
#ifdef ANDROID_ARM_LINKER
typedef long unsigned int *_Unwind_Ptr;