#define _GNU_SOURCE
#define SYSCALL_NO_TLS 1
-#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <semaphore.h>
#include <sys/membarrier.h>
#include "pthread_impl.h"
+#include "fork_impl.h"
#include "libc.h"
#include "dynlink.h"
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc __libc_realloc
+#define free __libc_free
+
static void error(const char *, ...);
#define MAXP2(a,b) (-(-(a)&-(b)))
}
}
+static ssize_t read_loop(int fd, void *p, size_t n)
+{
+ for (size_t i=0; i<n; ) {
+ ssize_t l = read(fd, (char *)p+i, n-i);
+ if (l<0) {
+ if (errno==EINTR) continue;
+ else return -1;
+ }
+ if (l==0) return i;
+ i += l;
+ }
+ return n;
+}
+
static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
{
static int no_map_fixed;
char *q;
+ if (!n) return p;
if (!no_map_fixed) {
q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
snprintf(etc_ldso_path, sizeof etc_ldso_path,
"%.*s/etc/ld-musl-" LDSO_ARCH ".path",
(int)prefix_len, prefix);
- FILE *f = fopen(etc_ldso_path, "rbe");
- if (f) {
- if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
+ fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
+ if (fd>=0) {
+ size_t n = 0;
+ if (!fstat(fd, &st)) n = st.st_size;
+ if ((sys_path = malloc(n+1)))
+ sys_path[n] = 0;
+ if (!sys_path || read_loop(fd, sys_path, n)<0) {
free(sys_path);
sys_path = "";
}
- fclose(f);
+ close(fd);
} else if (errno != ENOENT) {
sys_path = "";
}
}
}
+void __ldso_atfork(int who)
+{
+ if (who<0) {
+ pthread_rwlock_wrlock(&lock);
+ pthread_mutex_lock(&init_fini_lock);
+ } else {
+ pthread_mutex_unlock(&init_fini_lock);
+ pthread_rwlock_unlock(&lock);
+ }
+}
+
static struct dso **queue_ctors(struct dso *dso)
{
size_t cnt, qpos, spos, i;
}
queue[qpos] = 0;
for (i=0; i<qpos; i++) queue[i]->mark = 0;
+ for (i=0; i<qpos; i++)
+ if (queue[i]->ctor_visitor && queue[i]->ctor_visitor->tid < 0) {
+ error("State of %s is inconsistent due to multithreaded fork\n",
+ queue[i]->name);
+ free(queue);
+ if (runtime) longjmp(*rtld_fail, 1);
+ }
return queue;
}
dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
_exit(1);
}
- Ehdr *ehdr = (void *)map_library(fd, &app);
+ Ehdr *ehdr = map_library(fd, &app);
if (!ehdr) {
dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
_exit(1);
info.dlpi_adds = gencnt;
info.dlpi_subs = 0;
info.dlpi_tls_modid = current->tls_id;
- info.dlpi_tls_data = current->tls.image;
+ info.dlpi_tls_data = !current->tls_id ? 0 :
+ __tls_get_addr((tls_mod_off_t[]){current->tls_id,0});
ret = (callback)(&info, sizeof (info), data);