+ pthread_t td;
+ struct dso *p;
+ void **dtv;
+
+#ifdef TLS_ABOVE_TP
+ dtv = (void **)(mem + libc.tls_size) - (tls_cnt + 1);
+
+ mem += -((uintptr_t)mem + sizeof(struct pthread)) & (tls_align-1);
+ td = (pthread_t)mem;
+ mem += sizeof(struct pthread);
+
+ for (p=head; p; p=p->next) {
+ if (!p->tls_id) continue;
+ dtv[p->tls_id] = mem + p->tls_offset;
+ memcpy(dtv[p->tls_id], p->tls_image, p->tls_len);
+ }
+#else
+ dtv = (void **)mem;
+
+ mem += libc.tls_size - sizeof(struct pthread);
+ mem -= (uintptr_t)mem & (tls_align-1);
+ td = (pthread_t)mem;
+
+ for (p=head; p; p=p->next) {
+ if (!p->tls_id) continue;
+ dtv[p->tls_id] = mem - p->tls_offset;
+ memcpy(dtv[p->tls_id], p->tls_image, p->tls_len);
+ }
+#endif
+ dtv[0] = (void *)tls_cnt;
+ td->dtv = td->dtv_copy = dtv;
+ return td;
+}
+
+__attribute__((__visibility__("hidden")))
+void *__tls_get_new(size_t *v)
+{
+ pthread_t self = __pthread_self();
+
+ /* Block signals to make accessing new TLS async-signal-safe */
+ sigset_t set;
+ __block_all_sigs(&set);
+ if (v[0]<=(size_t)self->dtv[0]) {
+ __restore_sigs(&set);
+ return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET;
+ }
+
+ /* This is safe without any locks held because, if the caller
+ * is able to request the Nth entry of the DTV, the DSO list
+ * must be valid at least that far out and it was synchronized
+ * at program startup or by an already-completed call to dlopen. */
+ struct dso *p;
+ for (p=head; p->tls_id != v[0]; p=p->next);
+
+ /* Get new DTV space from new DSO if needed */
+ if (v[0] > (size_t)self->dtv[0]) {
+ void **newdtv = p->new_dtv +
+ (v[0]+1)*sizeof(void *)*a_fetch_add(&p->new_dtv_idx,1);
+ memcpy(newdtv, self->dtv,
+ ((size_t)self->dtv[0]+1) * sizeof(void *));
+ newdtv[0] = (void *)v[0];
+ self->dtv = self->dtv_copy = newdtv;
+ }
+
+ /* Get new TLS memory from all new DSOs up to the requested one */
+ unsigned char *mem;
+ for (p=head; ; p=p->next) {
+ if (!p->tls_id || self->dtv[p->tls_id]) continue;
+ mem = p->new_tls + (p->tls_size + p->tls_align)
+ * a_fetch_add(&p->new_tls_idx,1);
+ mem += ((uintptr_t)p->tls_image - (uintptr_t)mem)
+ & (p->tls_align-1);
+ self->dtv[p->tls_id] = mem;
+ memcpy(mem, p->tls_image, p->tls_len);
+ if (p->tls_id == v[0]) break;
+ }
+ __restore_sigs(&set);
+ return mem + v[1] + DTP_OFFSET;
+}
+
+static void update_tls_size()
+{
+ libc.tls_size = ALIGN(
+ (1+tls_cnt) * sizeof(void *) +
+ tls_offset +
+ sizeof(struct pthread) +
+ tls_align * 2,
+ tls_align);
+}
+
+/* Stage 1 of the dynamic linker is defined in dlstart.c. It calls the
+ * following stage 2 and stage 3 functions via primitive symbolic lookup
+ * since it does not have access to their addresses to begin with. */
+
+/* Stage 2 of the dynamic linker is called after relative relocations
+ * have been processed. It can make function calls to static functions
+ * and access string literals and static data, but cannot use extern
+ * symbols. Its job is to perform symbolic relocations on the dynamic
+ * linker itself, but some of the relocations performed may need to be
+ * replaced later due to copy relocations in the main program. */
+
+void __dls2(unsigned char *base, size_t *sp)
+{
+ if (DL_FDPIC) {
+ void *p1 = (void *)sp[-2];
+ void *p2 = (void *)sp[-1];
+ if (!p1) {
+ size_t *auxv, aux[AUX_CNT];
+ for (auxv=sp+1+*sp+1; *auxv; auxv++); auxv++;
+ decode_vec(auxv, aux, AUX_CNT);
+ if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE];
+ else ldso.base = (void *)(aux[AT_PHDR] & -4096);
+ }
+ app_loadmap = p2 ? p1 : 0;
+ ldso.loadmap = p2 ? p2 : p1;
+ ldso.base = laddr(&ldso, 0);
+ } else {
+ ldso.base = base;
+ }
+ Ehdr *ehdr = (void *)ldso.base;
+ ldso.name = ldso.shortname = "libc.so";
+ ldso.global = 1;
+ ldso.phnum = ehdr->e_phnum;
+ ldso.phdr = laddr(&ldso, ehdr->e_phoff);
+ ldso.phentsize = ehdr->e_phentsize;
+ kernel_mapped_dso(&ldso);
+ decode_dyn(&ldso);
+
+ if (DL_FDPIC) makefuncdescs(&ldso);
+
+ /* Prepare storage for to save clobbered REL addends so they
+ * can be reused in stage 3. There should be very few. If
+ * something goes wrong and there are a huge number, abort
+ * instead of risking stack overflow. */
+ size_t dyn[DYN_CNT];
+ decode_vec(ldso.dynv, dyn, DYN_CNT);
+ size_t *rel = laddr(&ldso, dyn[DT_REL]);
+ size_t rel_size = dyn[DT_RELSZ];
+ size_t symbolic_rel_cnt = 0;
+ apply_addends_to = rel;
+ for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t))
+ if (!IS_RELATIVE(rel[1], ldso.syms)) symbolic_rel_cnt++;
+ if (symbolic_rel_cnt >= ADDEND_LIMIT) a_crash();
+ size_t addends[symbolic_rel_cnt+1];
+ saved_addends = addends;
+
+ head = &ldso;
+ reloc_all(&ldso);
+
+ ldso.relocated = 0;
+
+ /* Call dynamic linker stage-3, __dls3, looking it up
+ * symbolically as a barrier against moving the address
+ * load across the above relocation processing. */
+ struct symdef dls3_def = find_sym(&ldso, "__dls3", 0);
+ if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp);
+ else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp);
+}
+
+/* Stage 3 of the dynamic linker is called with the dynamic linker/libc
+ * fully functional. Its job is to load (if not already loaded) and
+ * process dependencies and relocations for the main application and
+ * transfer control to its entry point. */
+
+_Noreturn void __dls3(size_t *sp)
+{
+ static struct dso app, vdso;
+ size_t aux[AUX_CNT], *auxv;