1*c9945492SAndroid Build Coastguard Worker #define _GNU_SOURCE
2*c9945492SAndroid Build Coastguard Worker #define SYSCALL_NO_TLS 1
3*c9945492SAndroid Build Coastguard Worker #include <stdlib.h>
4*c9945492SAndroid Build Coastguard Worker #include <stdarg.h>
5*c9945492SAndroid Build Coastguard Worker #include <stddef.h>
6*c9945492SAndroid Build Coastguard Worker #include <string.h>
7*c9945492SAndroid Build Coastguard Worker #include <unistd.h>
8*c9945492SAndroid Build Coastguard Worker #include <stdint.h>
9*c9945492SAndroid Build Coastguard Worker #include <elf.h>
10*c9945492SAndroid Build Coastguard Worker #include <sys/mman.h>
11*c9945492SAndroid Build Coastguard Worker #include <limits.h>
12*c9945492SAndroid Build Coastguard Worker #include <fcntl.h>
13*c9945492SAndroid Build Coastguard Worker #include <sys/stat.h>
14*c9945492SAndroid Build Coastguard Worker #include <errno.h>
15*c9945492SAndroid Build Coastguard Worker #include <link.h>
16*c9945492SAndroid Build Coastguard Worker #include <setjmp.h>
17*c9945492SAndroid Build Coastguard Worker #include <pthread.h>
18*c9945492SAndroid Build Coastguard Worker #include <ctype.h>
19*c9945492SAndroid Build Coastguard Worker #include <dlfcn.h>
20*c9945492SAndroid Build Coastguard Worker #include <semaphore.h>
21*c9945492SAndroid Build Coastguard Worker #include <sys/membarrier.h>
22*c9945492SAndroid Build Coastguard Worker #include "pthread_impl.h"
23*c9945492SAndroid Build Coastguard Worker #include "fork_impl.h"
24*c9945492SAndroid Build Coastguard Worker #include "libc.h"
25*c9945492SAndroid Build Coastguard Worker #include "dynlink.h"
26*c9945492SAndroid Build Coastguard Worker
27*c9945492SAndroid Build Coastguard Worker static size_t ldso_page_size;
28*c9945492SAndroid Build Coastguard Worker /* libc.h may have defined a macro for dynamic PAGE_SIZE already, but
29*c9945492SAndroid Build Coastguard Worker * PAGESIZE is only defined if it's constant for the arch. */
30*c9945492SAndroid Build Coastguard Worker #ifndef PAGESIZE
31*c9945492SAndroid Build Coastguard Worker #undef PAGE_SIZE
32*c9945492SAndroid Build Coastguard Worker #define PAGE_SIZE ldso_page_size
33*c9945492SAndroid Build Coastguard Worker #endif
34*c9945492SAndroid Build Coastguard Worker
35*c9945492SAndroid Build Coastguard Worker #define STRINGIFY(x) __STRINGIFY(x)
36*c9945492SAndroid Build Coastguard Worker #define __STRINGIFY(x) #x
37*c9945492SAndroid Build Coastguard Worker
38*c9945492SAndroid Build Coastguard Worker #define malloc __libc_malloc
39*c9945492SAndroid Build Coastguard Worker #define calloc __libc_calloc
40*c9945492SAndroid Build Coastguard Worker #define realloc __libc_realloc
41*c9945492SAndroid Build Coastguard Worker #define free __libc_free
42*c9945492SAndroid Build Coastguard Worker
43*c9945492SAndroid Build Coastguard Worker static void error_impl(const char *, ...);
44*c9945492SAndroid Build Coastguard Worker static void error_noop(const char *, ...);
45*c9945492SAndroid Build Coastguard Worker static void (*error)(const char *, ...) = error_noop;
46*c9945492SAndroid Build Coastguard Worker
47*c9945492SAndroid Build Coastguard Worker #define MAXP2(a,b) (-(-(a)&-(b)))
48*c9945492SAndroid Build Coastguard Worker #define ALIGN(x,y) ((x)+(y)-1 & -(y))
49*c9945492SAndroid Build Coastguard Worker
50*c9945492SAndroid Build Coastguard Worker #define container_of(p,t,m) ((t*)((char *)(p)-offsetof(t,m)))
51*c9945492SAndroid Build Coastguard Worker #define countof(a) ((sizeof (a))/(sizeof (a)[0]))
52*c9945492SAndroid Build Coastguard Worker
53*c9945492SAndroid Build Coastguard Worker struct debug {
54*c9945492SAndroid Build Coastguard Worker int ver;
55*c9945492SAndroid Build Coastguard Worker void *head;
56*c9945492SAndroid Build Coastguard Worker void (*bp)(void);
57*c9945492SAndroid Build Coastguard Worker int state;
58*c9945492SAndroid Build Coastguard Worker void *base;
59*c9945492SAndroid Build Coastguard Worker };
60*c9945492SAndroid Build Coastguard Worker
61*c9945492SAndroid Build Coastguard Worker struct td_index {
62*c9945492SAndroid Build Coastguard Worker size_t args[2];
63*c9945492SAndroid Build Coastguard Worker struct td_index *next;
64*c9945492SAndroid Build Coastguard Worker };
65*c9945492SAndroid Build Coastguard Worker
66*c9945492SAndroid Build Coastguard Worker struct dso {
67*c9945492SAndroid Build Coastguard Worker #if DL_FDPIC
68*c9945492SAndroid Build Coastguard Worker struct fdpic_loadmap *loadmap;
69*c9945492SAndroid Build Coastguard Worker #else
70*c9945492SAndroid Build Coastguard Worker unsigned char *base;
71*c9945492SAndroid Build Coastguard Worker #endif
72*c9945492SAndroid Build Coastguard Worker char *name;
73*c9945492SAndroid Build Coastguard Worker size_t *dynv;
74*c9945492SAndroid Build Coastguard Worker struct dso *next, *prev;
75*c9945492SAndroid Build Coastguard Worker
76*c9945492SAndroid Build Coastguard Worker int elfmachine;
77*c9945492SAndroid Build Coastguard Worker int elfclass;
78*c9945492SAndroid Build Coastguard Worker Phdr *phdr;
79*c9945492SAndroid Build Coastguard Worker int phnum;
80*c9945492SAndroid Build Coastguard Worker size_t phentsize;
81*c9945492SAndroid Build Coastguard Worker Sym *syms;
82*c9945492SAndroid Build Coastguard Worker Elf_Symndx *hashtab;
83*c9945492SAndroid Build Coastguard Worker uint32_t *ghashtab;
84*c9945492SAndroid Build Coastguard Worker int16_t *versym;
85*c9945492SAndroid Build Coastguard Worker char *strings;
86*c9945492SAndroid Build Coastguard Worker struct dso *syms_next, *lazy_next;
87*c9945492SAndroid Build Coastguard Worker size_t *lazy, lazy_cnt;
88*c9945492SAndroid Build Coastguard Worker unsigned char *map;
89*c9945492SAndroid Build Coastguard Worker size_t map_len;
90*c9945492SAndroid Build Coastguard Worker dev_t dev;
91*c9945492SAndroid Build Coastguard Worker ino_t ino;
92*c9945492SAndroid Build Coastguard Worker char relocated;
93*c9945492SAndroid Build Coastguard Worker char constructed;
94*c9945492SAndroid Build Coastguard Worker char kernel_mapped;
95*c9945492SAndroid Build Coastguard Worker char mark;
96*c9945492SAndroid Build Coastguard Worker char bfs_built;
97*c9945492SAndroid Build Coastguard Worker char runtime_loaded;
98*c9945492SAndroid Build Coastguard Worker struct dso **deps, *needed_by;
99*c9945492SAndroid Build Coastguard Worker size_t ndeps_direct;
100*c9945492SAndroid Build Coastguard Worker size_t next_dep;
101*c9945492SAndroid Build Coastguard Worker pthread_t ctor_visitor;
102*c9945492SAndroid Build Coastguard Worker char *rpath_orig, *rpath;
103*c9945492SAndroid Build Coastguard Worker struct tls_module tls;
104*c9945492SAndroid Build Coastguard Worker size_t tls_id;
105*c9945492SAndroid Build Coastguard Worker size_t relro_start, relro_end;
106*c9945492SAndroid Build Coastguard Worker uintptr_t *new_dtv;
107*c9945492SAndroid Build Coastguard Worker unsigned char *new_tls;
108*c9945492SAndroid Build Coastguard Worker struct td_index *td_index;
109*c9945492SAndroid Build Coastguard Worker struct dso *fini_next;
110*c9945492SAndroid Build Coastguard Worker char *shortname;
111*c9945492SAndroid Build Coastguard Worker #if DL_FDPIC
112*c9945492SAndroid Build Coastguard Worker unsigned char *base;
113*c9945492SAndroid Build Coastguard Worker #else
114*c9945492SAndroid Build Coastguard Worker struct fdpic_loadmap *loadmap;
115*c9945492SAndroid Build Coastguard Worker #endif
116*c9945492SAndroid Build Coastguard Worker struct funcdesc {
117*c9945492SAndroid Build Coastguard Worker void *addr;
118*c9945492SAndroid Build Coastguard Worker size_t *got;
119*c9945492SAndroid Build Coastguard Worker } *funcdescs;
120*c9945492SAndroid Build Coastguard Worker size_t *got;
121*c9945492SAndroid Build Coastguard Worker char buf[];
122*c9945492SAndroid Build Coastguard Worker };
123*c9945492SAndroid Build Coastguard Worker
124*c9945492SAndroid Build Coastguard Worker struct symdef {
125*c9945492SAndroid Build Coastguard Worker Sym *sym;
126*c9945492SAndroid Build Coastguard Worker struct dso *dso;
127*c9945492SAndroid Build Coastguard Worker };
128*c9945492SAndroid Build Coastguard Worker
129*c9945492SAndroid Build Coastguard Worker typedef void (*stage3_func)(size_t *, size_t *);
130*c9945492SAndroid Build Coastguard Worker
131*c9945492SAndroid Build Coastguard Worker static struct builtin_tls {
132*c9945492SAndroid Build Coastguard Worker char c;
133*c9945492SAndroid Build Coastguard Worker struct pthread pt;
134*c9945492SAndroid Build Coastguard Worker void *space[16];
135*c9945492SAndroid Build Coastguard Worker } builtin_tls[1];
136*c9945492SAndroid Build Coastguard Worker #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)
137*c9945492SAndroid Build Coastguard Worker
138*c9945492SAndroid Build Coastguard Worker #define ADDEND_LIMIT 4096
139*c9945492SAndroid Build Coastguard Worker static size_t *saved_addends, *apply_addends_to;
140*c9945492SAndroid Build Coastguard Worker
141*c9945492SAndroid Build Coastguard Worker static struct dso ldso;
142*c9945492SAndroid Build Coastguard Worker static struct dso *head, *tail, *fini_head, *syms_tail, *lazy_head;
143*c9945492SAndroid Build Coastguard Worker static char *env_path, *sys_path;
144*c9945492SAndroid Build Coastguard Worker static unsigned long long gencnt;
145*c9945492SAndroid Build Coastguard Worker static int runtime;
146*c9945492SAndroid Build Coastguard Worker static int ldd_mode;
147*c9945492SAndroid Build Coastguard Worker static int ldso_fail;
148*c9945492SAndroid Build Coastguard Worker static int noload;
149*c9945492SAndroid Build Coastguard Worker static int shutting_down;
150*c9945492SAndroid Build Coastguard Worker static jmp_buf *rtld_fail;
151*c9945492SAndroid Build Coastguard Worker static pthread_rwlock_t lock;
152*c9945492SAndroid Build Coastguard Worker static struct debug debug;
153*c9945492SAndroid Build Coastguard Worker static struct tls_module *tls_tail;
154*c9945492SAndroid Build Coastguard Worker static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN;
155*c9945492SAndroid Build Coastguard Worker static size_t static_tls_cnt;
156*c9945492SAndroid Build Coastguard Worker static pthread_mutex_t init_fini_lock;
157*c9945492SAndroid Build Coastguard Worker static pthread_cond_t ctor_cond;
158*c9945492SAndroid Build Coastguard Worker static struct dso *builtin_deps[2];
159*c9945492SAndroid Build Coastguard Worker static struct dso *const no_deps[1];
160*c9945492SAndroid Build Coastguard Worker static struct dso *builtin_ctor_queue[4];
161*c9945492SAndroid Build Coastguard Worker static struct dso **main_ctor_queue;
162*c9945492SAndroid Build Coastguard Worker static struct fdpic_loadmap *app_loadmap;
163*c9945492SAndroid Build Coastguard Worker static struct fdpic_dummy_loadmap app_dummy_loadmap;
164*c9945492SAndroid Build Coastguard Worker
165*c9945492SAndroid Build Coastguard Worker struct debug *_dl_debug_addr = &debug;
166*c9945492SAndroid Build Coastguard Worker static void (*exe_dl_debug_state)(void) = 0;
167*c9945492SAndroid Build Coastguard Worker
168*c9945492SAndroid Build Coastguard Worker extern weak hidden char __ehdr_start[];
169*c9945492SAndroid Build Coastguard Worker
170*c9945492SAndroid Build Coastguard Worker extern hidden int __malloc_replaced;
171*c9945492SAndroid Build Coastguard Worker
172*c9945492SAndroid Build Coastguard Worker hidden void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0;
173*c9945492SAndroid Build Coastguard Worker
174*c9945492SAndroid Build Coastguard Worker extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(void);
175*c9945492SAndroid Build Coastguard Worker
176*c9945492SAndroid Build Coastguard Worker weak_alias(__init_array_start, __init_array_end);
177*c9945492SAndroid Build Coastguard Worker weak_alias(__fini_array_start, __fini_array_end);
178*c9945492SAndroid Build Coastguard Worker
dl_strcmp(const char * l,const char * r)179*c9945492SAndroid Build Coastguard Worker static int dl_strcmp(const char *l, const char *r)
180*c9945492SAndroid Build Coastguard Worker {
181*c9945492SAndroid Build Coastguard Worker for (; *l==*r && *l; l++, r++);
182*c9945492SAndroid Build Coastguard Worker return *(unsigned char *)l - *(unsigned char *)r;
183*c9945492SAndroid Build Coastguard Worker }
184*c9945492SAndroid Build Coastguard Worker #define strcmp(l,r) dl_strcmp(l,r)
185*c9945492SAndroid Build Coastguard Worker
186*c9945492SAndroid Build Coastguard Worker /* Compute load address for a virtual address in a given dso. */
187*c9945492SAndroid Build Coastguard Worker #if DL_FDPIC
laddr(const struct dso * p,size_t v)188*c9945492SAndroid Build Coastguard Worker static void *laddr(const struct dso *p, size_t v)
189*c9945492SAndroid Build Coastguard Worker {
190*c9945492SAndroid Build Coastguard Worker size_t j=0;
191*c9945492SAndroid Build Coastguard Worker if (!p->loadmap) return p->base + v;
192*c9945492SAndroid Build Coastguard Worker for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
193*c9945492SAndroid Build Coastguard Worker return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
194*c9945492SAndroid Build Coastguard Worker }
laddr_pg(const struct dso * p,size_t v)195*c9945492SAndroid Build Coastguard Worker static void *laddr_pg(const struct dso *p, size_t v)
196*c9945492SAndroid Build Coastguard Worker {
197*c9945492SAndroid Build Coastguard Worker size_t j=0;
198*c9945492SAndroid Build Coastguard Worker size_t pgsz = PAGE_SIZE;
199*c9945492SAndroid Build Coastguard Worker if (!p->loadmap) return p->base + v;
200*c9945492SAndroid Build Coastguard Worker for (j=0; ; j++) {
201*c9945492SAndroid Build Coastguard Worker size_t a = p->loadmap->segs[j].p_vaddr;
202*c9945492SAndroid Build Coastguard Worker size_t b = a + p->loadmap->segs[j].p_memsz;
203*c9945492SAndroid Build Coastguard Worker a &= -pgsz;
204*c9945492SAndroid Build Coastguard Worker b += pgsz-1;
205*c9945492SAndroid Build Coastguard Worker b &= -pgsz;
206*c9945492SAndroid Build Coastguard Worker if (v-a<b-a) break;
207*c9945492SAndroid Build Coastguard Worker }
208*c9945492SAndroid Build Coastguard Worker return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
209*c9945492SAndroid Build Coastguard Worker }
fdbarrier(void * p)210*c9945492SAndroid Build Coastguard Worker static void (*fdbarrier(void *p))()
211*c9945492SAndroid Build Coastguard Worker {
212*c9945492SAndroid Build Coastguard Worker void (*fd)();
213*c9945492SAndroid Build Coastguard Worker __asm__("" : "=r"(fd) : "0"(p));
214*c9945492SAndroid Build Coastguard Worker return fd;
215*c9945492SAndroid Build Coastguard Worker }
216*c9945492SAndroid Build Coastguard Worker #define fpaddr(p, v) fdbarrier((&(struct funcdesc){ \
217*c9945492SAndroid Build Coastguard Worker laddr(p, v), (p)->got }))
218*c9945492SAndroid Build Coastguard Worker #else
219*c9945492SAndroid Build Coastguard Worker #define laddr(p, v) (void *)((p)->base + (v))
220*c9945492SAndroid Build Coastguard Worker #define laddr_pg(p, v) laddr(p, v)
221*c9945492SAndroid Build Coastguard Worker #define fpaddr(p, v) ((void (*)())laddr(p, v))
222*c9945492SAndroid Build Coastguard Worker #endif
223*c9945492SAndroid Build Coastguard Worker
decode_vec(size_t * v,size_t * a,size_t cnt)224*c9945492SAndroid Build Coastguard Worker static void decode_vec(size_t *v, size_t *a, size_t cnt)
225*c9945492SAndroid Build Coastguard Worker {
226*c9945492SAndroid Build Coastguard Worker size_t i;
227*c9945492SAndroid Build Coastguard Worker for (i=0; i<cnt; i++) a[i] = 0;
228*c9945492SAndroid Build Coastguard Worker for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
229*c9945492SAndroid Build Coastguard Worker if (v[0] < 8*sizeof(long))
230*c9945492SAndroid Build Coastguard Worker a[0] |= 1UL<<v[0];
231*c9945492SAndroid Build Coastguard Worker a[v[0]] = v[1];
232*c9945492SAndroid Build Coastguard Worker }
233*c9945492SAndroid Build Coastguard Worker }
234*c9945492SAndroid Build Coastguard Worker
search_vec(size_t * v,size_t * r,size_t key)235*c9945492SAndroid Build Coastguard Worker static int search_vec(size_t *v, size_t *r, size_t key)
236*c9945492SAndroid Build Coastguard Worker {
237*c9945492SAndroid Build Coastguard Worker for (; v[0]!=key; v+=2)
238*c9945492SAndroid Build Coastguard Worker if (!v[0]) return 0;
239*c9945492SAndroid Build Coastguard Worker *r = v[1];
240*c9945492SAndroid Build Coastguard Worker return 1;
241*c9945492SAndroid Build Coastguard Worker }
242*c9945492SAndroid Build Coastguard Worker
sysv_hash(const char * s0)243*c9945492SAndroid Build Coastguard Worker static uint32_t sysv_hash(const char *s0)
244*c9945492SAndroid Build Coastguard Worker {
245*c9945492SAndroid Build Coastguard Worker const unsigned char *s = (void *)s0;
246*c9945492SAndroid Build Coastguard Worker uint_fast32_t h = 0;
247*c9945492SAndroid Build Coastguard Worker while (*s) {
248*c9945492SAndroid Build Coastguard Worker h = 16*h + *s++;
249*c9945492SAndroid Build Coastguard Worker h ^= h>>24 & 0xf0;
250*c9945492SAndroid Build Coastguard Worker }
251*c9945492SAndroid Build Coastguard Worker return h & 0xfffffff;
252*c9945492SAndroid Build Coastguard Worker }
253*c9945492SAndroid Build Coastguard Worker
gnu_hash(const char * s0)254*c9945492SAndroid Build Coastguard Worker static uint32_t gnu_hash(const char *s0)
255*c9945492SAndroid Build Coastguard Worker {
256*c9945492SAndroid Build Coastguard Worker const unsigned char *s = (void *)s0;
257*c9945492SAndroid Build Coastguard Worker uint_fast32_t h = 5381;
258*c9945492SAndroid Build Coastguard Worker for (; *s; s++)
259*c9945492SAndroid Build Coastguard Worker h += h*32 + *s;
260*c9945492SAndroid Build Coastguard Worker return h;
261*c9945492SAndroid Build Coastguard Worker }
262*c9945492SAndroid Build Coastguard Worker
sysv_lookup(const char * s,uint32_t h,struct dso * dso)263*c9945492SAndroid Build Coastguard Worker static Sym *sysv_lookup(const char *s, uint32_t h, struct dso *dso)
264*c9945492SAndroid Build Coastguard Worker {
265*c9945492SAndroid Build Coastguard Worker size_t i;
266*c9945492SAndroid Build Coastguard Worker Sym *syms = dso->syms;
267*c9945492SAndroid Build Coastguard Worker Elf_Symndx *hashtab = dso->hashtab;
268*c9945492SAndroid Build Coastguard Worker char *strings = dso->strings;
269*c9945492SAndroid Build Coastguard Worker for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
270*c9945492SAndroid Build Coastguard Worker if ((!dso->versym || dso->versym[i] >= 0)
271*c9945492SAndroid Build Coastguard Worker && (!strcmp(s, strings+syms[i].st_name)))
272*c9945492SAndroid Build Coastguard Worker return syms+i;
273*c9945492SAndroid Build Coastguard Worker }
274*c9945492SAndroid Build Coastguard Worker return 0;
275*c9945492SAndroid Build Coastguard Worker }
276*c9945492SAndroid Build Coastguard Worker
gnu_lookup(uint32_t h1,uint32_t * hashtab,struct dso * dso,const char * s)277*c9945492SAndroid Build Coastguard Worker static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s)
278*c9945492SAndroid Build Coastguard Worker {
279*c9945492SAndroid Build Coastguard Worker uint32_t nbuckets = hashtab[0];
280*c9945492SAndroid Build Coastguard Worker uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
281*c9945492SAndroid Build Coastguard Worker uint32_t i = buckets[h1 % nbuckets];
282*c9945492SAndroid Build Coastguard Worker
283*c9945492SAndroid Build Coastguard Worker if (!i) return 0;
284*c9945492SAndroid Build Coastguard Worker
285*c9945492SAndroid Build Coastguard Worker uint32_t *hashval = buckets + nbuckets + (i - hashtab[1]);
286*c9945492SAndroid Build Coastguard Worker
287*c9945492SAndroid Build Coastguard Worker for (h1 |= 1; ; i++) {
288*c9945492SAndroid Build Coastguard Worker uint32_t h2 = *hashval++;
289*c9945492SAndroid Build Coastguard Worker if ((h1 == (h2|1)) && (!dso->versym || dso->versym[i] >= 0)
290*c9945492SAndroid Build Coastguard Worker && !strcmp(s, dso->strings + dso->syms[i].st_name))
291*c9945492SAndroid Build Coastguard Worker return dso->syms+i;
292*c9945492SAndroid Build Coastguard Worker if (h2 & 1) break;
293*c9945492SAndroid Build Coastguard Worker }
294*c9945492SAndroid Build Coastguard Worker
295*c9945492SAndroid Build Coastguard Worker return 0;
296*c9945492SAndroid Build Coastguard Worker }
297*c9945492SAndroid Build Coastguard Worker
gnu_lookup_filtered(uint32_t h1,uint32_t * hashtab,struct dso * dso,const char * s,uint32_t fofs,size_t fmask)298*c9945492SAndroid Build Coastguard Worker static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s, uint32_t fofs, size_t fmask)
299*c9945492SAndroid Build Coastguard Worker {
300*c9945492SAndroid Build Coastguard Worker const size_t *bloomwords = (const void *)(hashtab+4);
301*c9945492SAndroid Build Coastguard Worker size_t f = bloomwords[fofs & (hashtab[2]-1)];
302*c9945492SAndroid Build Coastguard Worker if (!(f & fmask)) return 0;
303*c9945492SAndroid Build Coastguard Worker
304*c9945492SAndroid Build Coastguard Worker f >>= (h1 >> hashtab[3]) % (8 * sizeof f);
305*c9945492SAndroid Build Coastguard Worker if (!(f & 1)) return 0;
306*c9945492SAndroid Build Coastguard Worker
307*c9945492SAndroid Build Coastguard Worker return gnu_lookup(h1, hashtab, dso, s);
308*c9945492SAndroid Build Coastguard Worker }
309*c9945492SAndroid Build Coastguard Worker
310*c9945492SAndroid Build Coastguard Worker #define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
311*c9945492SAndroid Build Coastguard Worker #define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
312*c9945492SAndroid Build Coastguard Worker
313*c9945492SAndroid Build Coastguard Worker #ifndef ARCH_SYM_REJECT_UND
314*c9945492SAndroid Build Coastguard Worker #define ARCH_SYM_REJECT_UND(s) 0
315*c9945492SAndroid Build Coastguard Worker #endif
316*c9945492SAndroid Build Coastguard Worker
317*c9945492SAndroid Build Coastguard Worker #if defined(__GNUC__)
318*c9945492SAndroid Build Coastguard Worker __attribute__((always_inline))
319*c9945492SAndroid Build Coastguard Worker #endif
find_sym2(struct dso * dso,const char * s,int need_def,int use_deps)320*c9945492SAndroid Build Coastguard Worker static inline struct symdef find_sym2(struct dso *dso, const char *s, int need_def, int use_deps)
321*c9945492SAndroid Build Coastguard Worker {
322*c9945492SAndroid Build Coastguard Worker uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght;
323*c9945492SAndroid Build Coastguard Worker size_t ghm = 1ul << gh % (8*sizeof(size_t));
324*c9945492SAndroid Build Coastguard Worker struct symdef def = {0};
325*c9945492SAndroid Build Coastguard Worker struct dso **deps = use_deps ? dso->deps : 0;
326*c9945492SAndroid Build Coastguard Worker for (; dso; dso=use_deps ? *deps++ : dso->syms_next) {
327*c9945492SAndroid Build Coastguard Worker Sym *sym;
328*c9945492SAndroid Build Coastguard Worker if ((ght = dso->ghashtab)) {
329*c9945492SAndroid Build Coastguard Worker sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
330*c9945492SAndroid Build Coastguard Worker } else {
331*c9945492SAndroid Build Coastguard Worker if (!h) h = sysv_hash(s);
332*c9945492SAndroid Build Coastguard Worker sym = sysv_lookup(s, h, dso);
333*c9945492SAndroid Build Coastguard Worker }
334*c9945492SAndroid Build Coastguard Worker if (!sym) continue;
335*c9945492SAndroid Build Coastguard Worker if (!sym->st_shndx)
336*c9945492SAndroid Build Coastguard Worker if (need_def || (sym->st_info&0xf) == STT_TLS
337*c9945492SAndroid Build Coastguard Worker || ARCH_SYM_REJECT_UND(sym))
338*c9945492SAndroid Build Coastguard Worker continue;
339*c9945492SAndroid Build Coastguard Worker if (!sym->st_value)
340*c9945492SAndroid Build Coastguard Worker if ((sym->st_info&0xf) != STT_TLS)
341*c9945492SAndroid Build Coastguard Worker continue;
342*c9945492SAndroid Build Coastguard Worker if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
343*c9945492SAndroid Build Coastguard Worker if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;
344*c9945492SAndroid Build Coastguard Worker def.sym = sym;
345*c9945492SAndroid Build Coastguard Worker def.dso = dso;
346*c9945492SAndroid Build Coastguard Worker break;
347*c9945492SAndroid Build Coastguard Worker }
348*c9945492SAndroid Build Coastguard Worker return def;
349*c9945492SAndroid Build Coastguard Worker }
350*c9945492SAndroid Build Coastguard Worker
find_sym(struct dso * dso,const char * s,int need_def)351*c9945492SAndroid Build Coastguard Worker static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
352*c9945492SAndroid Build Coastguard Worker {
353*c9945492SAndroid Build Coastguard Worker return find_sym2(dso, s, need_def, 0);
354*c9945492SAndroid Build Coastguard Worker }
355*c9945492SAndroid Build Coastguard Worker
get_lfs64(const char * name)356*c9945492SAndroid Build Coastguard Worker static struct symdef get_lfs64(const char *name)
357*c9945492SAndroid Build Coastguard Worker {
358*c9945492SAndroid Build Coastguard Worker const char *p;
359*c9945492SAndroid Build Coastguard Worker static const char lfs64_list[] =
360*c9945492SAndroid Build Coastguard Worker "aio_cancel\0aio_error\0aio_fsync\0aio_read\0aio_return\0"
361*c9945492SAndroid Build Coastguard Worker "aio_suspend\0aio_write\0alphasort\0creat\0fallocate\0"
362*c9945492SAndroid Build Coastguard Worker "fgetpos\0fopen\0freopen\0fseeko\0fsetpos\0fstat\0"
363*c9945492SAndroid Build Coastguard Worker "fstatat\0fstatfs\0fstatvfs\0ftello\0ftruncate\0ftw\0"
364*c9945492SAndroid Build Coastguard Worker "getdents\0getrlimit\0glob\0globfree\0lio_listio\0"
365*c9945492SAndroid Build Coastguard Worker "lockf\0lseek\0lstat\0mkostemp\0mkostemps\0mkstemp\0"
366*c9945492SAndroid Build Coastguard Worker "mkstemps\0mmap\0nftw\0open\0openat\0posix_fadvise\0"
367*c9945492SAndroid Build Coastguard Worker "posix_fallocate\0pread\0preadv\0prlimit\0pwrite\0"
368*c9945492SAndroid Build Coastguard Worker "pwritev\0readdir\0scandir\0sendfile\0setrlimit\0"
369*c9945492SAndroid Build Coastguard Worker "stat\0statfs\0statvfs\0tmpfile\0truncate\0versionsort\0"
370*c9945492SAndroid Build Coastguard Worker "__fxstat\0__fxstatat\0__lxstat\0__xstat\0";
371*c9945492SAndroid Build Coastguard Worker if (!strcmp(name, "readdir64_r"))
372*c9945492SAndroid Build Coastguard Worker return find_sym(&ldso, "readdir_r", 1);
373*c9945492SAndroid Build Coastguard Worker size_t l = strnlen(name, 18);
374*c9945492SAndroid Build Coastguard Worker if (l<2 || name[l-2]!='6' || name[l-1]!='4' || name[l])
375*c9945492SAndroid Build Coastguard Worker goto nomatch;
376*c9945492SAndroid Build Coastguard Worker for (p=lfs64_list; *p; p++) {
377*c9945492SAndroid Build Coastguard Worker if (!strncmp(name, p, l-2) && !p[l-2])
378*c9945492SAndroid Build Coastguard Worker return find_sym(&ldso, p, 1);
379*c9945492SAndroid Build Coastguard Worker while (*p) p++;
380*c9945492SAndroid Build Coastguard Worker }
381*c9945492SAndroid Build Coastguard Worker nomatch:
382*c9945492SAndroid Build Coastguard Worker return (struct symdef){ 0 };
383*c9945492SAndroid Build Coastguard Worker }
384*c9945492SAndroid Build Coastguard Worker
do_relocs(struct dso * dso,size_t * rel,size_t rel_size,size_t stride)385*c9945492SAndroid Build Coastguard Worker static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
386*c9945492SAndroid Build Coastguard Worker {
387*c9945492SAndroid Build Coastguard Worker unsigned char *base = dso->base;
388*c9945492SAndroid Build Coastguard Worker Sym *syms = dso->syms;
389*c9945492SAndroid Build Coastguard Worker char *strings = dso->strings;
390*c9945492SAndroid Build Coastguard Worker Sym *sym;
391*c9945492SAndroid Build Coastguard Worker const char *name;
392*c9945492SAndroid Build Coastguard Worker void *ctx;
393*c9945492SAndroid Build Coastguard Worker int type;
394*c9945492SAndroid Build Coastguard Worker int sym_index;
395*c9945492SAndroid Build Coastguard Worker struct symdef def;
396*c9945492SAndroid Build Coastguard Worker size_t *reloc_addr;
397*c9945492SAndroid Build Coastguard Worker size_t sym_val;
398*c9945492SAndroid Build Coastguard Worker size_t tls_val;
399*c9945492SAndroid Build Coastguard Worker size_t addend;
400*c9945492SAndroid Build Coastguard Worker int skip_relative = 0, reuse_addends = 0, save_slot = 0;
401*c9945492SAndroid Build Coastguard Worker
402*c9945492SAndroid Build Coastguard Worker if (dso == &ldso) {
403*c9945492SAndroid Build Coastguard Worker /* Only ldso's REL table needs addend saving/reuse. */
404*c9945492SAndroid Build Coastguard Worker if (rel == apply_addends_to)
405*c9945492SAndroid Build Coastguard Worker reuse_addends = 1;
406*c9945492SAndroid Build Coastguard Worker skip_relative = 1;
407*c9945492SAndroid Build Coastguard Worker }
408*c9945492SAndroid Build Coastguard Worker
409*c9945492SAndroid Build Coastguard Worker for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
410*c9945492SAndroid Build Coastguard Worker if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue;
411*c9945492SAndroid Build Coastguard Worker type = R_TYPE(rel[1]);
412*c9945492SAndroid Build Coastguard Worker if (type == REL_NONE) continue;
413*c9945492SAndroid Build Coastguard Worker reloc_addr = laddr(dso, rel[0]);
414*c9945492SAndroid Build Coastguard Worker
415*c9945492SAndroid Build Coastguard Worker if (stride > 2) {
416*c9945492SAndroid Build Coastguard Worker addend = rel[2];
417*c9945492SAndroid Build Coastguard Worker } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) {
418*c9945492SAndroid Build Coastguard Worker addend = 0;
419*c9945492SAndroid Build Coastguard Worker } else if (reuse_addends) {
420*c9945492SAndroid Build Coastguard Worker /* Save original addend in stage 2 where the dso
421*c9945492SAndroid Build Coastguard Worker * chain consists of just ldso; otherwise read back
422*c9945492SAndroid Build Coastguard Worker * saved addend since the inline one was clobbered. */
423*c9945492SAndroid Build Coastguard Worker if (head==&ldso)
424*c9945492SAndroid Build Coastguard Worker saved_addends[save_slot] = *reloc_addr;
425*c9945492SAndroid Build Coastguard Worker addend = saved_addends[save_slot++];
426*c9945492SAndroid Build Coastguard Worker } else {
427*c9945492SAndroid Build Coastguard Worker addend = *reloc_addr;
428*c9945492SAndroid Build Coastguard Worker }
429*c9945492SAndroid Build Coastguard Worker
430*c9945492SAndroid Build Coastguard Worker sym_index = R_SYM(rel[1]);
431*c9945492SAndroid Build Coastguard Worker if (sym_index) {
432*c9945492SAndroid Build Coastguard Worker sym = syms + sym_index;
433*c9945492SAndroid Build Coastguard Worker name = strings + sym->st_name;
434*c9945492SAndroid Build Coastguard Worker ctx = type==REL_COPY ? head->syms_next : head;
435*c9945492SAndroid Build Coastguard Worker def = (sym->st_info>>4) == STB_LOCAL
436*c9945492SAndroid Build Coastguard Worker ? (struct symdef){ .dso = dso, .sym = sym }
437*c9945492SAndroid Build Coastguard Worker : find_sym(ctx, name, type==REL_PLT);
438*c9945492SAndroid Build Coastguard Worker if (!def.sym) def = get_lfs64(name);
439*c9945492SAndroid Build Coastguard Worker if (!def.sym && (sym->st_shndx != SHN_UNDEF
440*c9945492SAndroid Build Coastguard Worker || sym->st_info>>4 != STB_WEAK)) {
441*c9945492SAndroid Build Coastguard Worker if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
442*c9945492SAndroid Build Coastguard Worker dso->lazy[3*dso->lazy_cnt+0] = rel[0];
443*c9945492SAndroid Build Coastguard Worker dso->lazy[3*dso->lazy_cnt+1] = rel[1];
444*c9945492SAndroid Build Coastguard Worker dso->lazy[3*dso->lazy_cnt+2] = addend;
445*c9945492SAndroid Build Coastguard Worker dso->lazy_cnt++;
446*c9945492SAndroid Build Coastguard Worker continue;
447*c9945492SAndroid Build Coastguard Worker }
448*c9945492SAndroid Build Coastguard Worker error("Error relocating %s: %s: symbol not found",
449*c9945492SAndroid Build Coastguard Worker dso->name, name);
450*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
451*c9945492SAndroid Build Coastguard Worker continue;
452*c9945492SAndroid Build Coastguard Worker }
453*c9945492SAndroid Build Coastguard Worker } else {
454*c9945492SAndroid Build Coastguard Worker sym = 0;
455*c9945492SAndroid Build Coastguard Worker def.sym = 0;
456*c9945492SAndroid Build Coastguard Worker def.dso = dso;
457*c9945492SAndroid Build Coastguard Worker }
458*c9945492SAndroid Build Coastguard Worker
459*c9945492SAndroid Build Coastguard Worker sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
460*c9945492SAndroid Build Coastguard Worker tls_val = def.sym ? def.sym->st_value : 0;
461*c9945492SAndroid Build Coastguard Worker
462*c9945492SAndroid Build Coastguard Worker if ((type == REL_TPOFF || type == REL_TPOFF_NEG)
463*c9945492SAndroid Build Coastguard Worker && def.dso && def.dso->tls_id > static_tls_cnt) {
464*c9945492SAndroid Build Coastguard Worker error("Error relocating %s: %s: initial-exec TLS "
465*c9945492SAndroid Build Coastguard Worker "resolves to dynamic definition in %s",
466*c9945492SAndroid Build Coastguard Worker dso->name, name, def.dso->name);
467*c9945492SAndroid Build Coastguard Worker longjmp(*rtld_fail, 1);
468*c9945492SAndroid Build Coastguard Worker }
469*c9945492SAndroid Build Coastguard Worker
470*c9945492SAndroid Build Coastguard Worker switch(type) {
471*c9945492SAndroid Build Coastguard Worker case REL_OFFSET:
472*c9945492SAndroid Build Coastguard Worker addend -= (size_t)reloc_addr;
473*c9945492SAndroid Build Coastguard Worker case REL_SYMBOLIC:
474*c9945492SAndroid Build Coastguard Worker case REL_GOT:
475*c9945492SAndroid Build Coastguard Worker case REL_PLT:
476*c9945492SAndroid Build Coastguard Worker *reloc_addr = sym_val + addend;
477*c9945492SAndroid Build Coastguard Worker break;
478*c9945492SAndroid Build Coastguard Worker case REL_USYMBOLIC:
479*c9945492SAndroid Build Coastguard Worker memcpy(reloc_addr, &(size_t){sym_val + addend}, sizeof(size_t));
480*c9945492SAndroid Build Coastguard Worker break;
481*c9945492SAndroid Build Coastguard Worker case REL_RELATIVE:
482*c9945492SAndroid Build Coastguard Worker *reloc_addr = (size_t)base + addend;
483*c9945492SAndroid Build Coastguard Worker break;
484*c9945492SAndroid Build Coastguard Worker case REL_SYM_OR_REL:
485*c9945492SAndroid Build Coastguard Worker if (sym) *reloc_addr = sym_val + addend;
486*c9945492SAndroid Build Coastguard Worker else *reloc_addr = (size_t)base + addend;
487*c9945492SAndroid Build Coastguard Worker break;
488*c9945492SAndroid Build Coastguard Worker case REL_COPY:
489*c9945492SAndroid Build Coastguard Worker memcpy(reloc_addr, (void *)sym_val, sym->st_size);
490*c9945492SAndroid Build Coastguard Worker break;
491*c9945492SAndroid Build Coastguard Worker case REL_OFFSET32:
492*c9945492SAndroid Build Coastguard Worker *(uint32_t *)reloc_addr = sym_val + addend
493*c9945492SAndroid Build Coastguard Worker - (size_t)reloc_addr;
494*c9945492SAndroid Build Coastguard Worker break;
495*c9945492SAndroid Build Coastguard Worker case REL_FUNCDESC:
496*c9945492SAndroid Build Coastguard Worker *reloc_addr = def.sym ? (size_t)(def.dso->funcdescs
497*c9945492SAndroid Build Coastguard Worker + (def.sym - def.dso->syms)) : 0;
498*c9945492SAndroid Build Coastguard Worker break;
499*c9945492SAndroid Build Coastguard Worker case REL_FUNCDESC_VAL:
500*c9945492SAndroid Build Coastguard Worker if ((sym->st_info&0xf) == STT_SECTION) *reloc_addr += sym_val;
501*c9945492SAndroid Build Coastguard Worker else *reloc_addr = sym_val;
502*c9945492SAndroid Build Coastguard Worker reloc_addr[1] = def.sym ? (size_t)def.dso->got : 0;
503*c9945492SAndroid Build Coastguard Worker break;
504*c9945492SAndroid Build Coastguard Worker case REL_DTPMOD:
505*c9945492SAndroid Build Coastguard Worker *reloc_addr = def.dso->tls_id;
506*c9945492SAndroid Build Coastguard Worker break;
507*c9945492SAndroid Build Coastguard Worker case REL_DTPOFF:
508*c9945492SAndroid Build Coastguard Worker *reloc_addr = tls_val + addend - DTP_OFFSET;
509*c9945492SAndroid Build Coastguard Worker break;
510*c9945492SAndroid Build Coastguard Worker #ifdef TLS_ABOVE_TP
511*c9945492SAndroid Build Coastguard Worker case REL_TPOFF:
512*c9945492SAndroid Build Coastguard Worker *reloc_addr = (def.dso ? tls_val + def.dso->tls.offset + TPOFF_K : 0) + addend;
513*c9945492SAndroid Build Coastguard Worker break;
514*c9945492SAndroid Build Coastguard Worker #else
515*c9945492SAndroid Build Coastguard Worker case REL_TPOFF:
516*c9945492SAndroid Build Coastguard Worker *reloc_addr = (def.dso ? tls_val - def.dso->tls.offset : 0) + addend;
517*c9945492SAndroid Build Coastguard Worker break;
518*c9945492SAndroid Build Coastguard Worker case REL_TPOFF_NEG:
519*c9945492SAndroid Build Coastguard Worker *reloc_addr = (def.dso ? def.dso->tls.offset - tls_val : 0) + addend;
520*c9945492SAndroid Build Coastguard Worker break;
521*c9945492SAndroid Build Coastguard Worker #endif
522*c9945492SAndroid Build Coastguard Worker case REL_TLSDESC:
523*c9945492SAndroid Build Coastguard Worker if (stride<3) addend = reloc_addr[!TLSDESC_BACKWARDS];
524*c9945492SAndroid Build Coastguard Worker if (def.dso->tls_id > static_tls_cnt) {
525*c9945492SAndroid Build Coastguard Worker struct td_index *new = malloc(sizeof *new);
526*c9945492SAndroid Build Coastguard Worker if (!new) {
527*c9945492SAndroid Build Coastguard Worker error(
528*c9945492SAndroid Build Coastguard Worker "Error relocating %s: cannot allocate TLSDESC for %s",
529*c9945492SAndroid Build Coastguard Worker dso->name, sym ? name : "(local)" );
530*c9945492SAndroid Build Coastguard Worker longjmp(*rtld_fail, 1);
531*c9945492SAndroid Build Coastguard Worker }
532*c9945492SAndroid Build Coastguard Worker new->next = dso->td_index;
533*c9945492SAndroid Build Coastguard Worker dso->td_index = new;
534*c9945492SAndroid Build Coastguard Worker new->args[0] = def.dso->tls_id;
535*c9945492SAndroid Build Coastguard Worker new->args[1] = tls_val + addend - DTP_OFFSET;
536*c9945492SAndroid Build Coastguard Worker reloc_addr[0] = (size_t)__tlsdesc_dynamic;
537*c9945492SAndroid Build Coastguard Worker reloc_addr[1] = (size_t)new;
538*c9945492SAndroid Build Coastguard Worker } else {
539*c9945492SAndroid Build Coastguard Worker reloc_addr[0] = (size_t)__tlsdesc_static;
540*c9945492SAndroid Build Coastguard Worker #ifdef TLS_ABOVE_TP
541*c9945492SAndroid Build Coastguard Worker reloc_addr[1] = tls_val + def.dso->tls.offset
542*c9945492SAndroid Build Coastguard Worker + TPOFF_K + addend;
543*c9945492SAndroid Build Coastguard Worker #else
544*c9945492SAndroid Build Coastguard Worker reloc_addr[1] = tls_val - def.dso->tls.offset
545*c9945492SAndroid Build Coastguard Worker + addend;
546*c9945492SAndroid Build Coastguard Worker #endif
547*c9945492SAndroid Build Coastguard Worker }
548*c9945492SAndroid Build Coastguard Worker /* Some archs (32-bit ARM at least) invert the order of
549*c9945492SAndroid Build Coastguard Worker * the descriptor members. Fix them up here. */
550*c9945492SAndroid Build Coastguard Worker if (TLSDESC_BACKWARDS) {
551*c9945492SAndroid Build Coastguard Worker size_t tmp = reloc_addr[0];
552*c9945492SAndroid Build Coastguard Worker reloc_addr[0] = reloc_addr[1];
553*c9945492SAndroid Build Coastguard Worker reloc_addr[1] = tmp;
554*c9945492SAndroid Build Coastguard Worker }
555*c9945492SAndroid Build Coastguard Worker break;
556*c9945492SAndroid Build Coastguard Worker default:
557*c9945492SAndroid Build Coastguard Worker error("Error relocating %s: unsupported relocation type %d",
558*c9945492SAndroid Build Coastguard Worker dso->name, type);
559*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
560*c9945492SAndroid Build Coastguard Worker continue;
561*c9945492SAndroid Build Coastguard Worker }
562*c9945492SAndroid Build Coastguard Worker }
563*c9945492SAndroid Build Coastguard Worker }
564*c9945492SAndroid Build Coastguard Worker
do_relr_relocs(struct dso * dso,size_t * relr,size_t relr_size)565*c9945492SAndroid Build Coastguard Worker static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size)
566*c9945492SAndroid Build Coastguard Worker {
567*c9945492SAndroid Build Coastguard Worker if (dso == &ldso) return; /* self-relocation was done in _dlstart */
568*c9945492SAndroid Build Coastguard Worker unsigned char *base = dso->base;
569*c9945492SAndroid Build Coastguard Worker size_t *reloc_addr;
570*c9945492SAndroid Build Coastguard Worker for (; relr_size; relr++, relr_size-=sizeof(size_t))
571*c9945492SAndroid Build Coastguard Worker if ((relr[0]&1) == 0) {
572*c9945492SAndroid Build Coastguard Worker reloc_addr = laddr(dso, relr[0]);
573*c9945492SAndroid Build Coastguard Worker *reloc_addr++ += (size_t)base;
574*c9945492SAndroid Build Coastguard Worker } else {
575*c9945492SAndroid Build Coastguard Worker int i = 0;
576*c9945492SAndroid Build Coastguard Worker for (size_t bitmap=relr[0]; (bitmap>>=1); i++)
577*c9945492SAndroid Build Coastguard Worker if (bitmap&1)
578*c9945492SAndroid Build Coastguard Worker reloc_addr[i] += (size_t)base;
579*c9945492SAndroid Build Coastguard Worker reloc_addr += 8*sizeof(size_t)-1;
580*c9945492SAndroid Build Coastguard Worker }
581*c9945492SAndroid Build Coastguard Worker }
582*c9945492SAndroid Build Coastguard Worker
redo_lazy_relocs()583*c9945492SAndroid Build Coastguard Worker static void redo_lazy_relocs()
584*c9945492SAndroid Build Coastguard Worker {
585*c9945492SAndroid Build Coastguard Worker struct dso *p = lazy_head, *next;
586*c9945492SAndroid Build Coastguard Worker lazy_head = 0;
587*c9945492SAndroid Build Coastguard Worker for (; p; p=next) {
588*c9945492SAndroid Build Coastguard Worker next = p->lazy_next;
589*c9945492SAndroid Build Coastguard Worker size_t size = p->lazy_cnt*3*sizeof(size_t);
590*c9945492SAndroid Build Coastguard Worker p->lazy_cnt = 0;
591*c9945492SAndroid Build Coastguard Worker do_relocs(p, p->lazy, size, 3);
592*c9945492SAndroid Build Coastguard Worker if (p->lazy_cnt) {
593*c9945492SAndroid Build Coastguard Worker p->lazy_next = lazy_head;
594*c9945492SAndroid Build Coastguard Worker lazy_head = p;
595*c9945492SAndroid Build Coastguard Worker } else {
596*c9945492SAndroid Build Coastguard Worker free(p->lazy);
597*c9945492SAndroid Build Coastguard Worker p->lazy = 0;
598*c9945492SAndroid Build Coastguard Worker p->lazy_next = 0;
599*c9945492SAndroid Build Coastguard Worker }
600*c9945492SAndroid Build Coastguard Worker }
601*c9945492SAndroid Build Coastguard Worker }
602*c9945492SAndroid Build Coastguard Worker
603*c9945492SAndroid Build Coastguard Worker /* A huge hack: to make up for the wastefulness of shared libraries
604*c9945492SAndroid Build Coastguard Worker * needing at least a page of dirty memory even if they have no global
605*c9945492SAndroid Build Coastguard Worker * data, we reclaim the gaps at the beginning and end of writable maps
606*c9945492SAndroid Build Coastguard Worker * and "donate" them to the heap. */
607*c9945492SAndroid Build Coastguard Worker
reclaim(struct dso * dso,size_t start,size_t end)608*c9945492SAndroid Build Coastguard Worker static void reclaim(struct dso *dso, size_t start, size_t end)
609*c9945492SAndroid Build Coastguard Worker {
610*c9945492SAndroid Build Coastguard Worker if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
611*c9945492SAndroid Build Coastguard Worker if (end >= dso->relro_start && end < dso->relro_end) end = dso->relro_start;
612*c9945492SAndroid Build Coastguard Worker if (start >= end) return;
613*c9945492SAndroid Build Coastguard Worker char *base = laddr_pg(dso, start);
614*c9945492SAndroid Build Coastguard Worker __malloc_donate(base, base+(end-start));
615*c9945492SAndroid Build Coastguard Worker }
616*c9945492SAndroid Build Coastguard Worker
reclaim_gaps(struct dso * dso)617*c9945492SAndroid Build Coastguard Worker static void reclaim_gaps(struct dso *dso)
618*c9945492SAndroid Build Coastguard Worker {
619*c9945492SAndroid Build Coastguard Worker Phdr *ph = dso->phdr;
620*c9945492SAndroid Build Coastguard Worker size_t phcnt = dso->phnum;
621*c9945492SAndroid Build Coastguard Worker
622*c9945492SAndroid Build Coastguard Worker for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
623*c9945492SAndroid Build Coastguard Worker if (ph->p_type!=PT_LOAD) continue;
624*c9945492SAndroid Build Coastguard Worker if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
625*c9945492SAndroid Build Coastguard Worker reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
626*c9945492SAndroid Build Coastguard Worker reclaim(dso, ph->p_vaddr+ph->p_memsz,
627*c9945492SAndroid Build Coastguard Worker ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
628*c9945492SAndroid Build Coastguard Worker }
629*c9945492SAndroid Build Coastguard Worker }
630*c9945492SAndroid Build Coastguard Worker
read_loop(int fd,void * p,size_t n)631*c9945492SAndroid Build Coastguard Worker static ssize_t read_loop(int fd, void *p, size_t n)
632*c9945492SAndroid Build Coastguard Worker {
633*c9945492SAndroid Build Coastguard Worker for (size_t i=0; i<n; ) {
634*c9945492SAndroid Build Coastguard Worker ssize_t l = read(fd, (char *)p+i, n-i);
635*c9945492SAndroid Build Coastguard Worker if (l<0) {
636*c9945492SAndroid Build Coastguard Worker if (errno==EINTR) continue;
637*c9945492SAndroid Build Coastguard Worker else return -1;
638*c9945492SAndroid Build Coastguard Worker }
639*c9945492SAndroid Build Coastguard Worker if (l==0) return i;
640*c9945492SAndroid Build Coastguard Worker i += l;
641*c9945492SAndroid Build Coastguard Worker }
642*c9945492SAndroid Build Coastguard Worker return n;
643*c9945492SAndroid Build Coastguard Worker }
644*c9945492SAndroid Build Coastguard Worker
mmap_fixed(void * p,size_t n,int prot,int flags,int fd,off_t off)645*c9945492SAndroid Build Coastguard Worker static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
646*c9945492SAndroid Build Coastguard Worker {
647*c9945492SAndroid Build Coastguard Worker static int no_map_fixed;
648*c9945492SAndroid Build Coastguard Worker char *q;
649*c9945492SAndroid Build Coastguard Worker if (!n) return p;
650*c9945492SAndroid Build Coastguard Worker if (!no_map_fixed) {
651*c9945492SAndroid Build Coastguard Worker q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
652*c9945492SAndroid Build Coastguard Worker if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
653*c9945492SAndroid Build Coastguard Worker return q;
654*c9945492SAndroid Build Coastguard Worker no_map_fixed = 1;
655*c9945492SAndroid Build Coastguard Worker }
656*c9945492SAndroid Build Coastguard Worker /* Fallbacks for MAP_FIXED failure on NOMMU kernels. */
657*c9945492SAndroid Build Coastguard Worker if (flags & MAP_ANONYMOUS) {
658*c9945492SAndroid Build Coastguard Worker memset(p, 0, n);
659*c9945492SAndroid Build Coastguard Worker return p;
660*c9945492SAndroid Build Coastguard Worker }
661*c9945492SAndroid Build Coastguard Worker ssize_t r;
662*c9945492SAndroid Build Coastguard Worker if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
663*c9945492SAndroid Build Coastguard Worker for (q=p; n; q+=r, off+=r, n-=r) {
664*c9945492SAndroid Build Coastguard Worker r = read(fd, q, n);
665*c9945492SAndroid Build Coastguard Worker if (r < 0 && errno != EINTR) return MAP_FAILED;
666*c9945492SAndroid Build Coastguard Worker if (!r) {
667*c9945492SAndroid Build Coastguard Worker memset(q, 0, n);
668*c9945492SAndroid Build Coastguard Worker break;
669*c9945492SAndroid Build Coastguard Worker }
670*c9945492SAndroid Build Coastguard Worker }
671*c9945492SAndroid Build Coastguard Worker return p;
672*c9945492SAndroid Build Coastguard Worker }
673*c9945492SAndroid Build Coastguard Worker
unmap_library(struct dso * dso)674*c9945492SAndroid Build Coastguard Worker static void unmap_library(struct dso *dso)
675*c9945492SAndroid Build Coastguard Worker {
676*c9945492SAndroid Build Coastguard Worker if (dso->loadmap) {
677*c9945492SAndroid Build Coastguard Worker size_t i;
678*c9945492SAndroid Build Coastguard Worker for (i=0; i<dso->loadmap->nsegs; i++) {
679*c9945492SAndroid Build Coastguard Worker if (!dso->loadmap->segs[i].p_memsz)
680*c9945492SAndroid Build Coastguard Worker continue;
681*c9945492SAndroid Build Coastguard Worker munmap((void *)dso->loadmap->segs[i].addr,
682*c9945492SAndroid Build Coastguard Worker dso->loadmap->segs[i].p_memsz);
683*c9945492SAndroid Build Coastguard Worker }
684*c9945492SAndroid Build Coastguard Worker free(dso->loadmap);
685*c9945492SAndroid Build Coastguard Worker } else if (dso->map && dso->map_len) {
686*c9945492SAndroid Build Coastguard Worker munmap(dso->map, dso->map_len);
687*c9945492SAndroid Build Coastguard Worker }
688*c9945492SAndroid Build Coastguard Worker }
689*c9945492SAndroid Build Coastguard Worker
verify_elf_magic(const Ehdr * eh)690*c9945492SAndroid Build Coastguard Worker static int verify_elf_magic(const Ehdr* eh) {
691*c9945492SAndroid Build Coastguard Worker return eh->e_ident[0] == ELFMAG0 &&
692*c9945492SAndroid Build Coastguard Worker eh->e_ident[1] == ELFMAG1 &&
693*c9945492SAndroid Build Coastguard Worker eh->e_ident[2] == ELFMAG2 &&
694*c9945492SAndroid Build Coastguard Worker eh->e_ident[3] == ELFMAG3;
695*c9945492SAndroid Build Coastguard Worker }
696*c9945492SAndroid Build Coastguard Worker
697*c9945492SAndroid Build Coastguard Worker /* Verifies that an elf header's machine and class match the loader */
verify_elf_arch(const Ehdr * eh)698*c9945492SAndroid Build Coastguard Worker static int verify_elf_arch(const Ehdr* eh) {
699*c9945492SAndroid Build Coastguard Worker return eh->e_machine == ldso.elfmachine &&
700*c9945492SAndroid Build Coastguard Worker eh->e_ident[EI_CLASS] == ldso.elfclass;
701*c9945492SAndroid Build Coastguard Worker }
702*c9945492SAndroid Build Coastguard Worker
map_library(int fd,struct dso * dso)703*c9945492SAndroid Build Coastguard Worker static void *map_library(int fd, struct dso *dso)
704*c9945492SAndroid Build Coastguard Worker {
705*c9945492SAndroid Build Coastguard Worker Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
706*c9945492SAndroid Build Coastguard Worker void *allocated_buf=0;
707*c9945492SAndroid Build Coastguard Worker size_t phsize;
708*c9945492SAndroid Build Coastguard Worker size_t addr_min=SIZE_MAX, addr_max=0, map_len;
709*c9945492SAndroid Build Coastguard Worker size_t this_min, this_max;
710*c9945492SAndroid Build Coastguard Worker size_t nsegs = 0;
711*c9945492SAndroid Build Coastguard Worker off_t off_start;
712*c9945492SAndroid Build Coastguard Worker Ehdr *eh;
713*c9945492SAndroid Build Coastguard Worker Phdr *ph, *ph0;
714*c9945492SAndroid Build Coastguard Worker unsigned prot;
715*c9945492SAndroid Build Coastguard Worker unsigned char *map=MAP_FAILED, *base;
716*c9945492SAndroid Build Coastguard Worker size_t dyn=0;
717*c9945492SAndroid Build Coastguard Worker size_t tls_image=0;
718*c9945492SAndroid Build Coastguard Worker size_t i;
719*c9945492SAndroid Build Coastguard Worker
720*c9945492SAndroid Build Coastguard Worker ssize_t l = read(fd, buf, sizeof buf);
721*c9945492SAndroid Build Coastguard Worker eh = buf;
722*c9945492SAndroid Build Coastguard Worker if (l<0) return 0;
723*c9945492SAndroid Build Coastguard Worker if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
724*c9945492SAndroid Build Coastguard Worker goto noexec;
725*c9945492SAndroid Build Coastguard Worker if (!verify_elf_magic(eh)) goto noexec;
726*c9945492SAndroid Build Coastguard Worker if (!verify_elf_arch(eh)) goto noexec;
727*c9945492SAndroid Build Coastguard Worker dso->elfmachine = eh->e_machine;
728*c9945492SAndroid Build Coastguard Worker dso->elfclass = eh->e_ident[EI_CLASS];
729*c9945492SAndroid Build Coastguard Worker phsize = eh->e_phentsize * eh->e_phnum;
730*c9945492SAndroid Build Coastguard Worker if (phsize > sizeof buf - sizeof *eh) {
731*c9945492SAndroid Build Coastguard Worker allocated_buf = malloc(phsize);
732*c9945492SAndroid Build Coastguard Worker if (!allocated_buf) return 0;
733*c9945492SAndroid Build Coastguard Worker l = pread(fd, allocated_buf, phsize, eh->e_phoff);
734*c9945492SAndroid Build Coastguard Worker if (l < 0) goto error;
735*c9945492SAndroid Build Coastguard Worker if (l != phsize) goto noexec;
736*c9945492SAndroid Build Coastguard Worker ph = ph0 = allocated_buf;
737*c9945492SAndroid Build Coastguard Worker } else if (eh->e_phoff + phsize > l) {
738*c9945492SAndroid Build Coastguard Worker l = pread(fd, buf+1, phsize, eh->e_phoff);
739*c9945492SAndroid Build Coastguard Worker if (l < 0) goto error;
740*c9945492SAndroid Build Coastguard Worker if (l != phsize) goto noexec;
741*c9945492SAndroid Build Coastguard Worker ph = ph0 = (void *)(buf + 1);
742*c9945492SAndroid Build Coastguard Worker } else {
743*c9945492SAndroid Build Coastguard Worker ph = ph0 = (void *)((char *)buf + eh->e_phoff);
744*c9945492SAndroid Build Coastguard Worker }
745*c9945492SAndroid Build Coastguard Worker for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
746*c9945492SAndroid Build Coastguard Worker if (ph->p_type == PT_DYNAMIC) {
747*c9945492SAndroid Build Coastguard Worker dyn = ph->p_vaddr;
748*c9945492SAndroid Build Coastguard Worker } else if (ph->p_type == PT_TLS) {
749*c9945492SAndroid Build Coastguard Worker tls_image = ph->p_vaddr;
750*c9945492SAndroid Build Coastguard Worker dso->tls.align = ph->p_align;
751*c9945492SAndroid Build Coastguard Worker dso->tls.len = ph->p_filesz;
752*c9945492SAndroid Build Coastguard Worker dso->tls.size = ph->p_memsz;
753*c9945492SAndroid Build Coastguard Worker } else if (ph->p_type == PT_GNU_RELRO) {
754*c9945492SAndroid Build Coastguard Worker dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
755*c9945492SAndroid Build Coastguard Worker dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
756*c9945492SAndroid Build Coastguard Worker } else if (ph->p_type == PT_GNU_STACK) {
757*c9945492SAndroid Build Coastguard Worker if (!runtime && ph->p_memsz > __default_stacksize) {
758*c9945492SAndroid Build Coastguard Worker __default_stacksize =
759*c9945492SAndroid Build Coastguard Worker ph->p_memsz < DEFAULT_STACK_MAX ?
760*c9945492SAndroid Build Coastguard Worker ph->p_memsz : DEFAULT_STACK_MAX;
761*c9945492SAndroid Build Coastguard Worker }
762*c9945492SAndroid Build Coastguard Worker }
763*c9945492SAndroid Build Coastguard Worker if (ph->p_type != PT_LOAD) continue;
764*c9945492SAndroid Build Coastguard Worker nsegs++;
765*c9945492SAndroid Build Coastguard Worker if (ph->p_vaddr < addr_min) {
766*c9945492SAndroid Build Coastguard Worker addr_min = ph->p_vaddr;
767*c9945492SAndroid Build Coastguard Worker off_start = ph->p_offset;
768*c9945492SAndroid Build Coastguard Worker prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
769*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
770*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_X) ? PROT_EXEC : 0));
771*c9945492SAndroid Build Coastguard Worker }
772*c9945492SAndroid Build Coastguard Worker if (ph->p_vaddr+ph->p_memsz > addr_max) {
773*c9945492SAndroid Build Coastguard Worker addr_max = ph->p_vaddr+ph->p_memsz;
774*c9945492SAndroid Build Coastguard Worker }
775*c9945492SAndroid Build Coastguard Worker }
776*c9945492SAndroid Build Coastguard Worker if (!dyn) goto noexec;
777*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
778*c9945492SAndroid Build Coastguard Worker dso->loadmap = calloc(1, sizeof *dso->loadmap
779*c9945492SAndroid Build Coastguard Worker + nsegs * sizeof *dso->loadmap->segs);
780*c9945492SAndroid Build Coastguard Worker if (!dso->loadmap) goto error;
781*c9945492SAndroid Build Coastguard Worker dso->loadmap->nsegs = nsegs;
782*c9945492SAndroid Build Coastguard Worker for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
783*c9945492SAndroid Build Coastguard Worker if (ph->p_type != PT_LOAD) continue;
784*c9945492SAndroid Build Coastguard Worker prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
785*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
786*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_X) ? PROT_EXEC : 0));
787*c9945492SAndroid Build Coastguard Worker map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
788*c9945492SAndroid Build Coastguard Worker prot, MAP_PRIVATE,
789*c9945492SAndroid Build Coastguard Worker fd, ph->p_offset & -PAGE_SIZE);
790*c9945492SAndroid Build Coastguard Worker if (map == MAP_FAILED) {
791*c9945492SAndroid Build Coastguard Worker unmap_library(dso);
792*c9945492SAndroid Build Coastguard Worker goto error;
793*c9945492SAndroid Build Coastguard Worker }
794*c9945492SAndroid Build Coastguard Worker dso->loadmap->segs[i].addr = (size_t)map +
795*c9945492SAndroid Build Coastguard Worker (ph->p_vaddr & PAGE_SIZE-1);
796*c9945492SAndroid Build Coastguard Worker dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
797*c9945492SAndroid Build Coastguard Worker dso->loadmap->segs[i].p_memsz = ph->p_memsz;
798*c9945492SAndroid Build Coastguard Worker i++;
799*c9945492SAndroid Build Coastguard Worker if (prot & PROT_WRITE) {
800*c9945492SAndroid Build Coastguard Worker size_t brk = (ph->p_vaddr & PAGE_SIZE-1)
801*c9945492SAndroid Build Coastguard Worker + ph->p_filesz;
802*c9945492SAndroid Build Coastguard Worker size_t pgbrk = brk + PAGE_SIZE-1 & -PAGE_SIZE;
803*c9945492SAndroid Build Coastguard Worker size_t pgend = brk + ph->p_memsz - ph->p_filesz
804*c9945492SAndroid Build Coastguard Worker + PAGE_SIZE-1 & -PAGE_SIZE;
805*c9945492SAndroid Build Coastguard Worker if (pgend > pgbrk && mmap_fixed(map+pgbrk,
806*c9945492SAndroid Build Coastguard Worker pgend-pgbrk, prot,
807*c9945492SAndroid Build Coastguard Worker MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
808*c9945492SAndroid Build Coastguard Worker -1, off_start) == MAP_FAILED)
809*c9945492SAndroid Build Coastguard Worker goto error;
810*c9945492SAndroid Build Coastguard Worker memset(map + brk, 0, pgbrk-brk);
811*c9945492SAndroid Build Coastguard Worker }
812*c9945492SAndroid Build Coastguard Worker }
813*c9945492SAndroid Build Coastguard Worker map = (void *)dso->loadmap->segs[0].addr;
814*c9945492SAndroid Build Coastguard Worker map_len = 0;
815*c9945492SAndroid Build Coastguard Worker goto done_mapping;
816*c9945492SAndroid Build Coastguard Worker }
817*c9945492SAndroid Build Coastguard Worker addr_max += PAGE_SIZE-1;
818*c9945492SAndroid Build Coastguard Worker addr_max &= -PAGE_SIZE;
819*c9945492SAndroid Build Coastguard Worker addr_min &= -PAGE_SIZE;
820*c9945492SAndroid Build Coastguard Worker off_start &= -PAGE_SIZE;
821*c9945492SAndroid Build Coastguard Worker map_len = addr_max - addr_min + off_start;
822*c9945492SAndroid Build Coastguard Worker /* The first time, we map too much, possibly even more than
823*c9945492SAndroid Build Coastguard Worker * the length of the file. This is okay because we will not
824*c9945492SAndroid Build Coastguard Worker * use the invalid part; we just need to reserve the right
825*c9945492SAndroid Build Coastguard Worker * amount of virtual address space to map over later. */
826*c9945492SAndroid Build Coastguard Worker map = DL_NOMMU_SUPPORT
827*c9945492SAndroid Build Coastguard Worker ? mmap((void *)addr_min, map_len, PROT_READ|PROT_WRITE|PROT_EXEC,
828*c9945492SAndroid Build Coastguard Worker MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
829*c9945492SAndroid Build Coastguard Worker : mmap((void *)addr_min, map_len, prot,
830*c9945492SAndroid Build Coastguard Worker MAP_PRIVATE, fd, off_start);
831*c9945492SAndroid Build Coastguard Worker if (map==MAP_FAILED) goto error;
832*c9945492SAndroid Build Coastguard Worker dso->map = map;
833*c9945492SAndroid Build Coastguard Worker dso->map_len = map_len;
834*c9945492SAndroid Build Coastguard Worker /* If the loaded file is not relocatable and the requested address is
835*c9945492SAndroid Build Coastguard Worker * not available, then the load operation must fail. */
836*c9945492SAndroid Build Coastguard Worker if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
837*c9945492SAndroid Build Coastguard Worker errno = EBUSY;
838*c9945492SAndroid Build Coastguard Worker goto error;
839*c9945492SAndroid Build Coastguard Worker }
840*c9945492SAndroid Build Coastguard Worker base = map - addr_min;
841*c9945492SAndroid Build Coastguard Worker dso->phdr = 0;
842*c9945492SAndroid Build Coastguard Worker dso->phnum = 0;
843*c9945492SAndroid Build Coastguard Worker for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
844*c9945492SAndroid Build Coastguard Worker if (ph->p_type != PT_LOAD) continue;
845*c9945492SAndroid Build Coastguard Worker /* Check if the programs headers are in this load segment, and
846*c9945492SAndroid Build Coastguard Worker * if so, record the address for use by dl_iterate_phdr. */
847*c9945492SAndroid Build Coastguard Worker if (!dso->phdr && eh->e_phoff >= ph->p_offset
848*c9945492SAndroid Build Coastguard Worker && eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
849*c9945492SAndroid Build Coastguard Worker dso->phdr = (void *)(base + ph->p_vaddr
850*c9945492SAndroid Build Coastguard Worker + (eh->e_phoff-ph->p_offset));
851*c9945492SAndroid Build Coastguard Worker dso->phnum = eh->e_phnum;
852*c9945492SAndroid Build Coastguard Worker dso->phentsize = eh->e_phentsize;
853*c9945492SAndroid Build Coastguard Worker }
854*c9945492SAndroid Build Coastguard Worker this_min = ph->p_vaddr & -PAGE_SIZE;
855*c9945492SAndroid Build Coastguard Worker this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
856*c9945492SAndroid Build Coastguard Worker off_start = ph->p_offset & -PAGE_SIZE;
857*c9945492SAndroid Build Coastguard Worker prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
858*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
859*c9945492SAndroid Build Coastguard Worker ((ph->p_flags&PF_X) ? PROT_EXEC : 0));
860*c9945492SAndroid Build Coastguard Worker /* Reuse the existing mapping for the lowest-address LOAD */
861*c9945492SAndroid Build Coastguard Worker if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
862*c9945492SAndroid Build Coastguard Worker if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
863*c9945492SAndroid Build Coastguard Worker goto error;
864*c9945492SAndroid Build Coastguard Worker if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
865*c9945492SAndroid Build Coastguard Worker size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
866*c9945492SAndroid Build Coastguard Worker size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
867*c9945492SAndroid Build Coastguard Worker memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
868*c9945492SAndroid Build Coastguard Worker if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
869*c9945492SAndroid Build Coastguard Worker goto error;
870*c9945492SAndroid Build Coastguard Worker }
871*c9945492SAndroid Build Coastguard Worker }
872*c9945492SAndroid Build Coastguard Worker for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
873*c9945492SAndroid Build Coastguard Worker if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
874*c9945492SAndroid Build Coastguard Worker if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
875*c9945492SAndroid Build Coastguard Worker && errno != ENOSYS)
876*c9945492SAndroid Build Coastguard Worker goto error;
877*c9945492SAndroid Build Coastguard Worker break;
878*c9945492SAndroid Build Coastguard Worker }
879*c9945492SAndroid Build Coastguard Worker done_mapping:
880*c9945492SAndroid Build Coastguard Worker dso->base = base;
881*c9945492SAndroid Build Coastguard Worker dso->dynv = laddr(dso, dyn);
882*c9945492SAndroid Build Coastguard Worker if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
883*c9945492SAndroid Build Coastguard Worker free(allocated_buf);
884*c9945492SAndroid Build Coastguard Worker return map;
885*c9945492SAndroid Build Coastguard Worker noexec:
886*c9945492SAndroid Build Coastguard Worker errno = ENOEXEC;
887*c9945492SAndroid Build Coastguard Worker error:
888*c9945492SAndroid Build Coastguard Worker if (map!=MAP_FAILED) unmap_library(dso);
889*c9945492SAndroid Build Coastguard Worker free(allocated_buf);
890*c9945492SAndroid Build Coastguard Worker return 0;
891*c9945492SAndroid Build Coastguard Worker }
892*c9945492SAndroid Build Coastguard Worker
path_open_library(const char * name,const char * s,char * buf,size_t buf_size)893*c9945492SAndroid Build Coastguard Worker static int path_open_library(const char *name, const char *s, char *buf, size_t buf_size)
894*c9945492SAndroid Build Coastguard Worker {
895*c9945492SAndroid Build Coastguard Worker size_t l;
896*c9945492SAndroid Build Coastguard Worker int fd;
897*c9945492SAndroid Build Coastguard Worker const char *p;
898*c9945492SAndroid Build Coastguard Worker for (;;) {
899*c9945492SAndroid Build Coastguard Worker s += strspn(s, ":\n");
900*c9945492SAndroid Build Coastguard Worker p = s;
901*c9945492SAndroid Build Coastguard Worker l = strcspn(s, ":\n");
902*c9945492SAndroid Build Coastguard Worker if (l-1 >= INT_MAX) return -1;
903*c9945492SAndroid Build Coastguard Worker s += l;
904*c9945492SAndroid Build Coastguard Worker if (snprintf(buf, buf_size, "%.*s/%s", (int)l, p, name) < buf_size) {
905*c9945492SAndroid Build Coastguard Worker fd = open(buf, O_RDONLY|O_CLOEXEC);
906*c9945492SAndroid Build Coastguard Worker if (fd < 0) {
907*c9945492SAndroid Build Coastguard Worker switch (errno) {
908*c9945492SAndroid Build Coastguard Worker case ENOENT:
909*c9945492SAndroid Build Coastguard Worker case ENOTDIR:
910*c9945492SAndroid Build Coastguard Worker case EACCES:
911*c9945492SAndroid Build Coastguard Worker case ENAMETOOLONG:
912*c9945492SAndroid Build Coastguard Worker /* Keep searching in path list. */
913*c9945492SAndroid Build Coastguard Worker continue;
914*c9945492SAndroid Build Coastguard Worker default:
915*c9945492SAndroid Build Coastguard Worker /* Any negative value but -1 will
916*c9945492SAndroid Build Coastguard Worker * inhibit further path search in
917*c9945492SAndroid Build Coastguard Worker * load_library. */
918*c9945492SAndroid Build Coastguard Worker return -2;
919*c9945492SAndroid Build Coastguard Worker }
920*c9945492SAndroid Build Coastguard Worker }
921*c9945492SAndroid Build Coastguard Worker Ehdr eh;
922*c9945492SAndroid Build Coastguard Worker ssize_t n = pread(fd, &eh, sizeof eh, 0);
923*c9945492SAndroid Build Coastguard Worker /* If the elf file is invalid return -2 to inhibit
924*c9945492SAndroid Build Coastguard Worker * further path search in load_library. */
925*c9945492SAndroid Build Coastguard Worker if (n < 0 ||
926*c9945492SAndroid Build Coastguard Worker n != sizeof eh ||
927*c9945492SAndroid Build Coastguard Worker !verify_elf_magic(&eh)) {
928*c9945492SAndroid Build Coastguard Worker close(fd);
929*c9945492SAndroid Build Coastguard Worker return -2;
930*c9945492SAndroid Build Coastguard Worker }
931*c9945492SAndroid Build Coastguard Worker /* If the elf file has a valid header but is for the
932*c9945492SAndroid Build Coastguard Worker * wrong architecture ignore it and keep searching the
933*c9945492SAndroid Build Coastguard Worker * path list. */
934*c9945492SAndroid Build Coastguard Worker if (!verify_elf_arch(&eh)) {
935*c9945492SAndroid Build Coastguard Worker close(fd);
936*c9945492SAndroid Build Coastguard Worker continue;
937*c9945492SAndroid Build Coastguard Worker }
938*c9945492SAndroid Build Coastguard Worker return fd;
939*c9945492SAndroid Build Coastguard Worker }
940*c9945492SAndroid Build Coastguard Worker }
941*c9945492SAndroid Build Coastguard Worker }
942*c9945492SAndroid Build Coastguard Worker
fixup_rpath(struct dso * p,char * buf,size_t buf_size)943*c9945492SAndroid Build Coastguard Worker static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
944*c9945492SAndroid Build Coastguard Worker {
945*c9945492SAndroid Build Coastguard Worker size_t n, l;
946*c9945492SAndroid Build Coastguard Worker const char *s, *t, *origin;
947*c9945492SAndroid Build Coastguard Worker char *d;
948*c9945492SAndroid Build Coastguard Worker if (p->rpath || !p->rpath_orig) return 0;
949*c9945492SAndroid Build Coastguard Worker if (!strchr(p->rpath_orig, '$')) {
950*c9945492SAndroid Build Coastguard Worker p->rpath = p->rpath_orig;
951*c9945492SAndroid Build Coastguard Worker return 0;
952*c9945492SAndroid Build Coastguard Worker }
953*c9945492SAndroid Build Coastguard Worker n = 0;
954*c9945492SAndroid Build Coastguard Worker s = p->rpath_orig;
955*c9945492SAndroid Build Coastguard Worker while ((t=strchr(s, '$'))) {
956*c9945492SAndroid Build Coastguard Worker if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
957*c9945492SAndroid Build Coastguard Worker return 0;
958*c9945492SAndroid Build Coastguard Worker s = t+1;
959*c9945492SAndroid Build Coastguard Worker n++;
960*c9945492SAndroid Build Coastguard Worker }
961*c9945492SAndroid Build Coastguard Worker if (n > SSIZE_MAX/PATH_MAX) return 0;
962*c9945492SAndroid Build Coastguard Worker
963*c9945492SAndroid Build Coastguard Worker if (p->kernel_mapped) {
964*c9945492SAndroid Build Coastguard Worker /* $ORIGIN searches cannot be performed for the main program
965*c9945492SAndroid Build Coastguard Worker * when it is suid/sgid/AT_SECURE. This is because the
966*c9945492SAndroid Build Coastguard Worker * pathname is under the control of the caller of execve.
967*c9945492SAndroid Build Coastguard Worker * For libraries, however, $ORIGIN can be processed safely
968*c9945492SAndroid Build Coastguard Worker * since the library's pathname came from a trusted source
969*c9945492SAndroid Build Coastguard Worker * (either system paths or a call to dlopen). */
970*c9945492SAndroid Build Coastguard Worker if (libc.secure)
971*c9945492SAndroid Build Coastguard Worker return 0;
972*c9945492SAndroid Build Coastguard Worker l = readlink("/proc/self/exe", buf, buf_size);
973*c9945492SAndroid Build Coastguard Worker if (l == -1) switch (errno) {
974*c9945492SAndroid Build Coastguard Worker case ENOENT:
975*c9945492SAndroid Build Coastguard Worker case ENOTDIR:
976*c9945492SAndroid Build Coastguard Worker case EACCES:
977*c9945492SAndroid Build Coastguard Worker return 0;
978*c9945492SAndroid Build Coastguard Worker default:
979*c9945492SAndroid Build Coastguard Worker return -1;
980*c9945492SAndroid Build Coastguard Worker }
981*c9945492SAndroid Build Coastguard Worker if (l >= buf_size)
982*c9945492SAndroid Build Coastguard Worker return 0;
983*c9945492SAndroid Build Coastguard Worker buf[l] = 0;
984*c9945492SAndroid Build Coastguard Worker origin = buf;
985*c9945492SAndroid Build Coastguard Worker } else {
986*c9945492SAndroid Build Coastguard Worker origin = p->name;
987*c9945492SAndroid Build Coastguard Worker }
988*c9945492SAndroid Build Coastguard Worker t = strrchr(origin, '/');
989*c9945492SAndroid Build Coastguard Worker if (t) {
990*c9945492SAndroid Build Coastguard Worker l = t-origin;
991*c9945492SAndroid Build Coastguard Worker } else {
992*c9945492SAndroid Build Coastguard Worker /* Normally p->name will always be an absolute or relative
993*c9945492SAndroid Build Coastguard Worker * pathname containing at least one '/' character, but in the
994*c9945492SAndroid Build Coastguard Worker * case where ldso was invoked as a command to execute a
995*c9945492SAndroid Build Coastguard Worker * program in the working directory, app.name may not. Fix. */
996*c9945492SAndroid Build Coastguard Worker origin = ".";
997*c9945492SAndroid Build Coastguard Worker l = 1;
998*c9945492SAndroid Build Coastguard Worker }
999*c9945492SAndroid Build Coastguard Worker /* Disallow non-absolute origins for suid/sgid/AT_SECURE. */
1000*c9945492SAndroid Build Coastguard Worker if (libc.secure && *origin != '/')
1001*c9945492SAndroid Build Coastguard Worker return 0;
1002*c9945492SAndroid Build Coastguard Worker p->rpath = malloc(strlen(p->rpath_orig) + n*l + 1);
1003*c9945492SAndroid Build Coastguard Worker if (!p->rpath) return -1;
1004*c9945492SAndroid Build Coastguard Worker
1005*c9945492SAndroid Build Coastguard Worker d = p->rpath;
1006*c9945492SAndroid Build Coastguard Worker s = p->rpath_orig;
1007*c9945492SAndroid Build Coastguard Worker while ((t=strchr(s, '$'))) {
1008*c9945492SAndroid Build Coastguard Worker memcpy(d, s, t-s);
1009*c9945492SAndroid Build Coastguard Worker d += t-s;
1010*c9945492SAndroid Build Coastguard Worker memcpy(d, origin, l);
1011*c9945492SAndroid Build Coastguard Worker d += l;
1012*c9945492SAndroid Build Coastguard Worker /* It was determined previously that the '$' is followed
1013*c9945492SAndroid Build Coastguard Worker * either by "ORIGIN" or "{ORIGIN}". */
1014*c9945492SAndroid Build Coastguard Worker s = t + 7 + 2*(t[1]=='{');
1015*c9945492SAndroid Build Coastguard Worker }
1016*c9945492SAndroid Build Coastguard Worker strcpy(d, s);
1017*c9945492SAndroid Build Coastguard Worker return 0;
1018*c9945492SAndroid Build Coastguard Worker }
1019*c9945492SAndroid Build Coastguard Worker
decode_dyn(struct dso * p)1020*c9945492SAndroid Build Coastguard Worker static void decode_dyn(struct dso *p)
1021*c9945492SAndroid Build Coastguard Worker {
1022*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT];
1023*c9945492SAndroid Build Coastguard Worker decode_vec(p->dynv, dyn, DYN_CNT);
1024*c9945492SAndroid Build Coastguard Worker p->syms = laddr(p, dyn[DT_SYMTAB]);
1025*c9945492SAndroid Build Coastguard Worker p->strings = laddr(p, dyn[DT_STRTAB]);
1026*c9945492SAndroid Build Coastguard Worker if (dyn[0]&(1<<DT_HASH))
1027*c9945492SAndroid Build Coastguard Worker p->hashtab = laddr(p, dyn[DT_HASH]);
1028*c9945492SAndroid Build Coastguard Worker if (dyn[0]&(1<<DT_RPATH))
1029*c9945492SAndroid Build Coastguard Worker p->rpath_orig = p->strings + dyn[DT_RPATH];
1030*c9945492SAndroid Build Coastguard Worker if (dyn[0]&(1<<DT_RUNPATH))
1031*c9945492SAndroid Build Coastguard Worker p->rpath_orig = p->strings + dyn[DT_RUNPATH];
1032*c9945492SAndroid Build Coastguard Worker if (dyn[0]&(1<<DT_PLTGOT))
1033*c9945492SAndroid Build Coastguard Worker p->got = laddr(p, dyn[DT_PLTGOT]);
1034*c9945492SAndroid Build Coastguard Worker if (search_vec(p->dynv, dyn, DT_GNU_HASH))
1035*c9945492SAndroid Build Coastguard Worker p->ghashtab = laddr(p, *dyn);
1036*c9945492SAndroid Build Coastguard Worker if (search_vec(p->dynv, dyn, DT_VERSYM))
1037*c9945492SAndroid Build Coastguard Worker p->versym = laddr(p, *dyn);
1038*c9945492SAndroid Build Coastguard Worker }
1039*c9945492SAndroid Build Coastguard Worker
count_syms(struct dso * p)1040*c9945492SAndroid Build Coastguard Worker static size_t count_syms(struct dso *p)
1041*c9945492SAndroid Build Coastguard Worker {
1042*c9945492SAndroid Build Coastguard Worker if (p->hashtab) return p->hashtab[1];
1043*c9945492SAndroid Build Coastguard Worker
1044*c9945492SAndroid Build Coastguard Worker size_t nsym, i;
1045*c9945492SAndroid Build Coastguard Worker uint32_t *buckets = p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4);
1046*c9945492SAndroid Build Coastguard Worker uint32_t *hashval;
1047*c9945492SAndroid Build Coastguard Worker for (i = nsym = 0; i < p->ghashtab[0]; i++) {
1048*c9945492SAndroid Build Coastguard Worker if (buckets[i] > nsym)
1049*c9945492SAndroid Build Coastguard Worker nsym = buckets[i];
1050*c9945492SAndroid Build Coastguard Worker }
1051*c9945492SAndroid Build Coastguard Worker if (nsym) {
1052*c9945492SAndroid Build Coastguard Worker hashval = buckets + p->ghashtab[0] + (nsym - p->ghashtab[1]);
1053*c9945492SAndroid Build Coastguard Worker do nsym++;
1054*c9945492SAndroid Build Coastguard Worker while (!(*hashval++ & 1));
1055*c9945492SAndroid Build Coastguard Worker }
1056*c9945492SAndroid Build Coastguard Worker return nsym;
1057*c9945492SAndroid Build Coastguard Worker }
1058*c9945492SAndroid Build Coastguard Worker
dl_mmap(size_t n)1059*c9945492SAndroid Build Coastguard Worker static void *dl_mmap(size_t n)
1060*c9945492SAndroid Build Coastguard Worker {
1061*c9945492SAndroid Build Coastguard Worker void *p;
1062*c9945492SAndroid Build Coastguard Worker int prot = PROT_READ|PROT_WRITE, flags = MAP_ANONYMOUS|MAP_PRIVATE;
1063*c9945492SAndroid Build Coastguard Worker #ifdef SYS_mmap2
1064*c9945492SAndroid Build Coastguard Worker p = (void *)__syscall(SYS_mmap2, 0, n, prot, flags, -1, 0);
1065*c9945492SAndroid Build Coastguard Worker #else
1066*c9945492SAndroid Build Coastguard Worker p = (void *)__syscall(SYS_mmap, 0, n, prot, flags, -1, 0);
1067*c9945492SAndroid Build Coastguard Worker #endif
1068*c9945492SAndroid Build Coastguard Worker return (unsigned long)p > -4096UL ? 0 : p;
1069*c9945492SAndroid Build Coastguard Worker }
1070*c9945492SAndroid Build Coastguard Worker
makefuncdescs(struct dso * p)1071*c9945492SAndroid Build Coastguard Worker static void makefuncdescs(struct dso *p)
1072*c9945492SAndroid Build Coastguard Worker {
1073*c9945492SAndroid Build Coastguard Worker static int self_done;
1074*c9945492SAndroid Build Coastguard Worker size_t nsym = count_syms(p);
1075*c9945492SAndroid Build Coastguard Worker size_t i, size = nsym * sizeof(*p->funcdescs);
1076*c9945492SAndroid Build Coastguard Worker
1077*c9945492SAndroid Build Coastguard Worker if (!self_done) {
1078*c9945492SAndroid Build Coastguard Worker p->funcdescs = dl_mmap(size);
1079*c9945492SAndroid Build Coastguard Worker self_done = 1;
1080*c9945492SAndroid Build Coastguard Worker } else {
1081*c9945492SAndroid Build Coastguard Worker p->funcdescs = malloc(size);
1082*c9945492SAndroid Build Coastguard Worker }
1083*c9945492SAndroid Build Coastguard Worker if (!p->funcdescs) {
1084*c9945492SAndroid Build Coastguard Worker if (!runtime) a_crash();
1085*c9945492SAndroid Build Coastguard Worker error("Error allocating function descriptors for %s", p->name);
1086*c9945492SAndroid Build Coastguard Worker longjmp(*rtld_fail, 1);
1087*c9945492SAndroid Build Coastguard Worker }
1088*c9945492SAndroid Build Coastguard Worker for (i=0; i<nsym; i++) {
1089*c9945492SAndroid Build Coastguard Worker if ((p->syms[i].st_info&0xf)==STT_FUNC && p->syms[i].st_shndx) {
1090*c9945492SAndroid Build Coastguard Worker p->funcdescs[i].addr = laddr(p, p->syms[i].st_value);
1091*c9945492SAndroid Build Coastguard Worker p->funcdescs[i].got = p->got;
1092*c9945492SAndroid Build Coastguard Worker } else {
1093*c9945492SAndroid Build Coastguard Worker p->funcdescs[i].addr = 0;
1094*c9945492SAndroid Build Coastguard Worker p->funcdescs[i].got = 0;
1095*c9945492SAndroid Build Coastguard Worker }
1096*c9945492SAndroid Build Coastguard Worker }
1097*c9945492SAndroid Build Coastguard Worker }
1098*c9945492SAndroid Build Coastguard Worker
load_library(const char * name,struct dso * needed_by)1099*c9945492SAndroid Build Coastguard Worker static struct dso *load_library(const char *name, struct dso *needed_by)
1100*c9945492SAndroid Build Coastguard Worker {
1101*c9945492SAndroid Build Coastguard Worker char buf[2*NAME_MAX+2];
1102*c9945492SAndroid Build Coastguard Worker const char *pathname;
1103*c9945492SAndroid Build Coastguard Worker unsigned char *map;
1104*c9945492SAndroid Build Coastguard Worker struct dso *p, temp_dso = {0};
1105*c9945492SAndroid Build Coastguard Worker int fd;
1106*c9945492SAndroid Build Coastguard Worker struct stat st;
1107*c9945492SAndroid Build Coastguard Worker size_t alloc_size;
1108*c9945492SAndroid Build Coastguard Worker int n_th = 0;
1109*c9945492SAndroid Build Coastguard Worker int is_self = 0;
1110*c9945492SAndroid Build Coastguard Worker
1111*c9945492SAndroid Build Coastguard Worker if (!*name) {
1112*c9945492SAndroid Build Coastguard Worker errno = EINVAL;
1113*c9945492SAndroid Build Coastguard Worker return 0;
1114*c9945492SAndroid Build Coastguard Worker }
1115*c9945492SAndroid Build Coastguard Worker
1116*c9945492SAndroid Build Coastguard Worker /* Catch and block attempts to reload the implementation itself */
1117*c9945492SAndroid Build Coastguard Worker if (name[0]=='l' && name[1]=='i' && name[2]=='b') {
1118*c9945492SAndroid Build Coastguard Worker static const char reserved[] =
1119*c9945492SAndroid Build Coastguard Worker "c.c_musl.pthread.rt.m.dl.util.xnet.";
1120*c9945492SAndroid Build Coastguard Worker const char *rp, *next;
1121*c9945492SAndroid Build Coastguard Worker for (rp=reserved; *rp; rp=next) {
1122*c9945492SAndroid Build Coastguard Worker next = strchr(rp, '.') + 1;
1123*c9945492SAndroid Build Coastguard Worker if (strncmp(name+3, rp, next-rp) == 0)
1124*c9945492SAndroid Build Coastguard Worker break;
1125*c9945492SAndroid Build Coastguard Worker }
1126*c9945492SAndroid Build Coastguard Worker if (*rp) {
1127*c9945492SAndroid Build Coastguard Worker if (ldd_mode) {
1128*c9945492SAndroid Build Coastguard Worker /* Track which names have been resolved
1129*c9945492SAndroid Build Coastguard Worker * and only report each one once. */
1130*c9945492SAndroid Build Coastguard Worker static unsigned reported;
1131*c9945492SAndroid Build Coastguard Worker unsigned mask = 1U<<(rp-reserved);
1132*c9945492SAndroid Build Coastguard Worker if (!(reported & mask)) {
1133*c9945492SAndroid Build Coastguard Worker reported |= mask;
1134*c9945492SAndroid Build Coastguard Worker dprintf(1, "\t%s => %s (%p)\n",
1135*c9945492SAndroid Build Coastguard Worker name, ldso.name,
1136*c9945492SAndroid Build Coastguard Worker ldso.base);
1137*c9945492SAndroid Build Coastguard Worker }
1138*c9945492SAndroid Build Coastguard Worker }
1139*c9945492SAndroid Build Coastguard Worker is_self = 1;
1140*c9945492SAndroid Build Coastguard Worker }
1141*c9945492SAndroid Build Coastguard Worker }
1142*c9945492SAndroid Build Coastguard Worker if (!strcmp(name, ldso.name)) is_self = 1;
1143*c9945492SAndroid Build Coastguard Worker if (is_self) {
1144*c9945492SAndroid Build Coastguard Worker if (!ldso.prev) {
1145*c9945492SAndroid Build Coastguard Worker tail->next = &ldso;
1146*c9945492SAndroid Build Coastguard Worker ldso.prev = tail;
1147*c9945492SAndroid Build Coastguard Worker tail = &ldso;
1148*c9945492SAndroid Build Coastguard Worker }
1149*c9945492SAndroid Build Coastguard Worker return &ldso;
1150*c9945492SAndroid Build Coastguard Worker }
1151*c9945492SAndroid Build Coastguard Worker if (strchr(name, '/')) {
1152*c9945492SAndroid Build Coastguard Worker pathname = name;
1153*c9945492SAndroid Build Coastguard Worker fd = open(name, O_RDONLY|O_CLOEXEC);
1154*c9945492SAndroid Build Coastguard Worker } else {
1155*c9945492SAndroid Build Coastguard Worker /* Search for the name to see if it's already loaded */
1156*c9945492SAndroid Build Coastguard Worker for (p=head->next; p; p=p->next) {
1157*c9945492SAndroid Build Coastguard Worker if (p->shortname && !strcmp(p->shortname, name)) {
1158*c9945492SAndroid Build Coastguard Worker return p;
1159*c9945492SAndroid Build Coastguard Worker }
1160*c9945492SAndroid Build Coastguard Worker }
1161*c9945492SAndroid Build Coastguard Worker if (strlen(name) > NAME_MAX) return 0;
1162*c9945492SAndroid Build Coastguard Worker fd = -1;
1163*c9945492SAndroid Build Coastguard Worker if (env_path) fd = path_open_library(name, env_path, buf, sizeof buf);
1164*c9945492SAndroid Build Coastguard Worker for (p=needed_by; fd == -1 && p; p=p->needed_by) {
1165*c9945492SAndroid Build Coastguard Worker if (fixup_rpath(p, buf, sizeof buf) < 0)
1166*c9945492SAndroid Build Coastguard Worker fd = -2; /* Inhibit further search. */
1167*c9945492SAndroid Build Coastguard Worker if (p->rpath)
1168*c9945492SAndroid Build Coastguard Worker fd = path_open_library(name, p->rpath, buf, sizeof buf);
1169*c9945492SAndroid Build Coastguard Worker }
1170*c9945492SAndroid Build Coastguard Worker if (fd == -1) {
1171*c9945492SAndroid Build Coastguard Worker if (!sys_path) {
1172*c9945492SAndroid Build Coastguard Worker char *prefix = 0;
1173*c9945492SAndroid Build Coastguard Worker size_t prefix_len;
1174*c9945492SAndroid Build Coastguard Worker if (ldso.name[0]=='/') {
1175*c9945492SAndroid Build Coastguard Worker char *s, *t, *z;
1176*c9945492SAndroid Build Coastguard Worker for (s=t=z=ldso.name; *s; s++)
1177*c9945492SAndroid Build Coastguard Worker if (*s=='/') z=t, t=s;
1178*c9945492SAndroid Build Coastguard Worker prefix_len = z-ldso.name;
1179*c9945492SAndroid Build Coastguard Worker if (prefix_len < PATH_MAX)
1180*c9945492SAndroid Build Coastguard Worker prefix = ldso.name;
1181*c9945492SAndroid Build Coastguard Worker }
1182*c9945492SAndroid Build Coastguard Worker if (!prefix) {
1183*c9945492SAndroid Build Coastguard Worker prefix = "";
1184*c9945492SAndroid Build Coastguard Worker prefix_len = 0;
1185*c9945492SAndroid Build Coastguard Worker }
1186*c9945492SAndroid Build Coastguard Worker char etc_ldso_path[prefix_len + 1
1187*c9945492SAndroid Build Coastguard Worker + sizeof "/etc/ld-musl-" LDSO_ARCH ".path"];
1188*c9945492SAndroid Build Coastguard Worker snprintf(etc_ldso_path, sizeof etc_ldso_path,
1189*c9945492SAndroid Build Coastguard Worker "%.*s/etc/ld-musl-" LDSO_ARCH ".path",
1190*c9945492SAndroid Build Coastguard Worker (int)prefix_len, prefix);
1191*c9945492SAndroid Build Coastguard Worker fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
1192*c9945492SAndroid Build Coastguard Worker if (fd>=0) {
1193*c9945492SAndroid Build Coastguard Worker size_t n = 0;
1194*c9945492SAndroid Build Coastguard Worker if (!fstat(fd, &st)) n = st.st_size;
1195*c9945492SAndroid Build Coastguard Worker if ((sys_path = malloc(n+1)))
1196*c9945492SAndroid Build Coastguard Worker sys_path[n] = 0;
1197*c9945492SAndroid Build Coastguard Worker if (!sys_path || read_loop(fd, sys_path, n)<0) {
1198*c9945492SAndroid Build Coastguard Worker free(sys_path);
1199*c9945492SAndroid Build Coastguard Worker sys_path = "";
1200*c9945492SAndroid Build Coastguard Worker }
1201*c9945492SAndroid Build Coastguard Worker close(fd);
1202*c9945492SAndroid Build Coastguard Worker } else if (errno != ENOENT) {
1203*c9945492SAndroid Build Coastguard Worker sys_path = "";
1204*c9945492SAndroid Build Coastguard Worker }
1205*c9945492SAndroid Build Coastguard Worker }
1206*c9945492SAndroid Build Coastguard Worker if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
1207*c9945492SAndroid Build Coastguard Worker fd = path_open_library(name, sys_path, buf, sizeof buf);
1208*c9945492SAndroid Build Coastguard Worker }
1209*c9945492SAndroid Build Coastguard Worker pathname = buf;
1210*c9945492SAndroid Build Coastguard Worker }
1211*c9945492SAndroid Build Coastguard Worker if (fd < 0) return 0;
1212*c9945492SAndroid Build Coastguard Worker if (fstat(fd, &st) < 0) {
1213*c9945492SAndroid Build Coastguard Worker close(fd);
1214*c9945492SAndroid Build Coastguard Worker return 0;
1215*c9945492SAndroid Build Coastguard Worker }
1216*c9945492SAndroid Build Coastguard Worker for (p=head->next; p; p=p->next) {
1217*c9945492SAndroid Build Coastguard Worker if (p->dev == st.st_dev && p->ino == st.st_ino) {
1218*c9945492SAndroid Build Coastguard Worker /* If this library was previously loaded with a
1219*c9945492SAndroid Build Coastguard Worker * pathname but a search found the same inode,
1220*c9945492SAndroid Build Coastguard Worker * setup its shortname so it can be found by name. */
1221*c9945492SAndroid Build Coastguard Worker if (!p->shortname && pathname != name)
1222*c9945492SAndroid Build Coastguard Worker p->shortname = strrchr(p->name, '/')+1;
1223*c9945492SAndroid Build Coastguard Worker close(fd);
1224*c9945492SAndroid Build Coastguard Worker return p;
1225*c9945492SAndroid Build Coastguard Worker }
1226*c9945492SAndroid Build Coastguard Worker }
1227*c9945492SAndroid Build Coastguard Worker map = noload ? 0 : map_library(fd, &temp_dso);
1228*c9945492SAndroid Build Coastguard Worker close(fd);
1229*c9945492SAndroid Build Coastguard Worker if (!map) return 0;
1230*c9945492SAndroid Build Coastguard Worker
1231*c9945492SAndroid Build Coastguard Worker /* Avoid the danger of getting two versions of libc mapped into the
1232*c9945492SAndroid Build Coastguard Worker * same process when an absolute pathname was used. The symbols
1233*c9945492SAndroid Build Coastguard Worker * checked are chosen to catch both musl and glibc, and to avoid
1234*c9945492SAndroid Build Coastguard Worker * false positives from interposition-hack libraries. */
1235*c9945492SAndroid Build Coastguard Worker decode_dyn(&temp_dso);
1236*c9945492SAndroid Build Coastguard Worker if (find_sym(&temp_dso, "__libc_start_main", 1).sym &&
1237*c9945492SAndroid Build Coastguard Worker find_sym(&temp_dso, "stdin", 1).sym) {
1238*c9945492SAndroid Build Coastguard Worker unmap_library(&temp_dso);
1239*c9945492SAndroid Build Coastguard Worker return load_library(STRINGIFY(LIBC_SONAME), needed_by);
1240*c9945492SAndroid Build Coastguard Worker }
1241*c9945492SAndroid Build Coastguard Worker /* Past this point, if we haven't reached runtime yet, ldso has
1242*c9945492SAndroid Build Coastguard Worker * committed either to use the mapped library or to abort execution.
1243*c9945492SAndroid Build Coastguard Worker * Unmapping is not possible, so we can safely reclaim gaps. */
1244*c9945492SAndroid Build Coastguard Worker if (!runtime) reclaim_gaps(&temp_dso);
1245*c9945492SAndroid Build Coastguard Worker
1246*c9945492SAndroid Build Coastguard Worker /* Allocate storage for the new DSO. When there is TLS, this
1247*c9945492SAndroid Build Coastguard Worker * storage must include a reservation for all pre-existing
1248*c9945492SAndroid Build Coastguard Worker * threads to obtain copies of both the new TLS, and an
1249*c9945492SAndroid Build Coastguard Worker * extended DTV capable of storing an additional slot for
1250*c9945492SAndroid Build Coastguard Worker * the newly-loaded DSO. */
1251*c9945492SAndroid Build Coastguard Worker alloc_size = sizeof *p + strlen(pathname) + 1;
1252*c9945492SAndroid Build Coastguard Worker if (runtime && temp_dso.tls.image) {
1253*c9945492SAndroid Build Coastguard Worker size_t per_th = temp_dso.tls.size + temp_dso.tls.align
1254*c9945492SAndroid Build Coastguard Worker + sizeof(void *) * (tls_cnt+3);
1255*c9945492SAndroid Build Coastguard Worker n_th = libc.threads_minus_1 + 1;
1256*c9945492SAndroid Build Coastguard Worker if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX;
1257*c9945492SAndroid Build Coastguard Worker else alloc_size += n_th * per_th;
1258*c9945492SAndroid Build Coastguard Worker }
1259*c9945492SAndroid Build Coastguard Worker p = calloc(1, alloc_size);
1260*c9945492SAndroid Build Coastguard Worker if (!p) {
1261*c9945492SAndroid Build Coastguard Worker unmap_library(&temp_dso);
1262*c9945492SAndroid Build Coastguard Worker return 0;
1263*c9945492SAndroid Build Coastguard Worker }
1264*c9945492SAndroid Build Coastguard Worker memcpy(p, &temp_dso, sizeof temp_dso);
1265*c9945492SAndroid Build Coastguard Worker p->dev = st.st_dev;
1266*c9945492SAndroid Build Coastguard Worker p->ino = st.st_ino;
1267*c9945492SAndroid Build Coastguard Worker p->needed_by = needed_by;
1268*c9945492SAndroid Build Coastguard Worker p->name = p->buf;
1269*c9945492SAndroid Build Coastguard Worker p->runtime_loaded = runtime;
1270*c9945492SAndroid Build Coastguard Worker strcpy(p->name, pathname);
1271*c9945492SAndroid Build Coastguard Worker /* Add a shortname only if name arg was not an explicit pathname. */
1272*c9945492SAndroid Build Coastguard Worker if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
1273*c9945492SAndroid Build Coastguard Worker if (p->tls.image) {
1274*c9945492SAndroid Build Coastguard Worker p->tls_id = ++tls_cnt;
1275*c9945492SAndroid Build Coastguard Worker tls_align = MAXP2(tls_align, p->tls.align);
1276*c9945492SAndroid Build Coastguard Worker #ifdef TLS_ABOVE_TP
1277*c9945492SAndroid Build Coastguard Worker p->tls.offset = tls_offset + ( (p->tls.align-1) &
1278*c9945492SAndroid Build Coastguard Worker (-tls_offset + (uintptr_t)p->tls.image) );
1279*c9945492SAndroid Build Coastguard Worker tls_offset = p->tls.offset + p->tls.size;
1280*c9945492SAndroid Build Coastguard Worker #else
1281*c9945492SAndroid Build Coastguard Worker tls_offset += p->tls.size + p->tls.align - 1;
1282*c9945492SAndroid Build Coastguard Worker tls_offset -= (tls_offset + (uintptr_t)p->tls.image)
1283*c9945492SAndroid Build Coastguard Worker & (p->tls.align-1);
1284*c9945492SAndroid Build Coastguard Worker p->tls.offset = tls_offset;
1285*c9945492SAndroid Build Coastguard Worker #endif
1286*c9945492SAndroid Build Coastguard Worker p->new_dtv = (void *)(-sizeof(size_t) &
1287*c9945492SAndroid Build Coastguard Worker (uintptr_t)(p->name+strlen(p->name)+sizeof(size_t)));
1288*c9945492SAndroid Build Coastguard Worker p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1));
1289*c9945492SAndroid Build Coastguard Worker if (tls_tail) tls_tail->next = &p->tls;
1290*c9945492SAndroid Build Coastguard Worker else libc.tls_head = &p->tls;
1291*c9945492SAndroid Build Coastguard Worker tls_tail = &p->tls;
1292*c9945492SAndroid Build Coastguard Worker }
1293*c9945492SAndroid Build Coastguard Worker
1294*c9945492SAndroid Build Coastguard Worker tail->next = p;
1295*c9945492SAndroid Build Coastguard Worker p->prev = tail;
1296*c9945492SAndroid Build Coastguard Worker tail = p;
1297*c9945492SAndroid Build Coastguard Worker
1298*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) makefuncdescs(p);
1299*c9945492SAndroid Build Coastguard Worker
1300*c9945492SAndroid Build Coastguard Worker if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
1301*c9945492SAndroid Build Coastguard Worker
1302*c9945492SAndroid Build Coastguard Worker return p;
1303*c9945492SAndroid Build Coastguard Worker }
1304*c9945492SAndroid Build Coastguard Worker
load_direct_deps(struct dso * p)1305*c9945492SAndroid Build Coastguard Worker static void load_direct_deps(struct dso *p)
1306*c9945492SAndroid Build Coastguard Worker {
1307*c9945492SAndroid Build Coastguard Worker size_t i, cnt=0;
1308*c9945492SAndroid Build Coastguard Worker
1309*c9945492SAndroid Build Coastguard Worker if (p->deps) return;
1310*c9945492SAndroid Build Coastguard Worker /* For head, all preloads are direct pseudo-dependencies.
1311*c9945492SAndroid Build Coastguard Worker * Count and include them now to avoid realloc later. */
1312*c9945492SAndroid Build Coastguard Worker if (p==head) for (struct dso *q=p->next; q; q=q->next)
1313*c9945492SAndroid Build Coastguard Worker cnt++;
1314*c9945492SAndroid Build Coastguard Worker for (i=0; p->dynv[i]; i+=2)
1315*c9945492SAndroid Build Coastguard Worker if (p->dynv[i] == DT_NEEDED) cnt++;
1316*c9945492SAndroid Build Coastguard Worker /* Use builtin buffer for apps with no external deps, to
1317*c9945492SAndroid Build Coastguard Worker * preserve property of no runtime failure paths. */
1318*c9945492SAndroid Build Coastguard Worker p->deps = (p==head && cnt<2) ? builtin_deps :
1319*c9945492SAndroid Build Coastguard Worker calloc(cnt+1, sizeof *p->deps);
1320*c9945492SAndroid Build Coastguard Worker if (!p->deps) {
1321*c9945492SAndroid Build Coastguard Worker error("Error loading dependencies for %s", p->name);
1322*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1323*c9945492SAndroid Build Coastguard Worker }
1324*c9945492SAndroid Build Coastguard Worker cnt=0;
1325*c9945492SAndroid Build Coastguard Worker if (p==head) for (struct dso *q=p->next; q; q=q->next)
1326*c9945492SAndroid Build Coastguard Worker p->deps[cnt++] = q;
1327*c9945492SAndroid Build Coastguard Worker for (i=0; p->dynv[i]; i+=2) {
1328*c9945492SAndroid Build Coastguard Worker if (p->dynv[i] != DT_NEEDED) continue;
1329*c9945492SAndroid Build Coastguard Worker struct dso *dep = load_library(p->strings + p->dynv[i+1], p);
1330*c9945492SAndroid Build Coastguard Worker if (!dep) {
1331*c9945492SAndroid Build Coastguard Worker error("Error loading shared library %s: %m (needed by %s)",
1332*c9945492SAndroid Build Coastguard Worker p->strings + p->dynv[i+1], p->name);
1333*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1334*c9945492SAndroid Build Coastguard Worker continue;
1335*c9945492SAndroid Build Coastguard Worker }
1336*c9945492SAndroid Build Coastguard Worker p->deps[cnt++] = dep;
1337*c9945492SAndroid Build Coastguard Worker }
1338*c9945492SAndroid Build Coastguard Worker p->deps[cnt] = 0;
1339*c9945492SAndroid Build Coastguard Worker p->ndeps_direct = cnt;
1340*c9945492SAndroid Build Coastguard Worker }
1341*c9945492SAndroid Build Coastguard Worker
load_deps(struct dso * p)1342*c9945492SAndroid Build Coastguard Worker static void load_deps(struct dso *p)
1343*c9945492SAndroid Build Coastguard Worker {
1344*c9945492SAndroid Build Coastguard Worker if (p->deps) return;
1345*c9945492SAndroid Build Coastguard Worker for (; p; p=p->next)
1346*c9945492SAndroid Build Coastguard Worker load_direct_deps(p);
1347*c9945492SAndroid Build Coastguard Worker }
1348*c9945492SAndroid Build Coastguard Worker
extend_bfs_deps(struct dso * p)1349*c9945492SAndroid Build Coastguard Worker static void extend_bfs_deps(struct dso *p)
1350*c9945492SAndroid Build Coastguard Worker {
1351*c9945492SAndroid Build Coastguard Worker size_t i, j, cnt, ndeps_all;
1352*c9945492SAndroid Build Coastguard Worker struct dso **tmp;
1353*c9945492SAndroid Build Coastguard Worker
1354*c9945492SAndroid Build Coastguard Worker /* Can't use realloc if the original p->deps was allocated at
1355*c9945492SAndroid Build Coastguard Worker * program entry and malloc has been replaced, or if it's
1356*c9945492SAndroid Build Coastguard Worker * the builtin non-allocated trivial main program deps array. */
1357*c9945492SAndroid Build Coastguard Worker int no_realloc = (__malloc_replaced && !p->runtime_loaded)
1358*c9945492SAndroid Build Coastguard Worker || p->deps == builtin_deps;
1359*c9945492SAndroid Build Coastguard Worker
1360*c9945492SAndroid Build Coastguard Worker if (p->bfs_built) return;
1361*c9945492SAndroid Build Coastguard Worker ndeps_all = p->ndeps_direct;
1362*c9945492SAndroid Build Coastguard Worker
1363*c9945492SAndroid Build Coastguard Worker /* Mark existing (direct) deps so they won't be duplicated. */
1364*c9945492SAndroid Build Coastguard Worker for (i=0; p->deps[i]; i++)
1365*c9945492SAndroid Build Coastguard Worker p->deps[i]->mark = 1;
1366*c9945492SAndroid Build Coastguard Worker
1367*c9945492SAndroid Build Coastguard Worker /* For each dependency already in the list, copy its list of direct
1368*c9945492SAndroid Build Coastguard Worker * dependencies to the list, excluding any items already in the
1369*c9945492SAndroid Build Coastguard Worker * list. Note that the list this loop iterates over will grow during
1370*c9945492SAndroid Build Coastguard Worker * the loop, but since duplicates are excluded, growth is bounded. */
1371*c9945492SAndroid Build Coastguard Worker for (i=0; p->deps[i]; i++) {
1372*c9945492SAndroid Build Coastguard Worker struct dso *dep = p->deps[i];
1373*c9945492SAndroid Build Coastguard Worker for (j=cnt=0; j<dep->ndeps_direct; j++)
1374*c9945492SAndroid Build Coastguard Worker if (!dep->deps[j]->mark) cnt++;
1375*c9945492SAndroid Build Coastguard Worker tmp = no_realloc ?
1376*c9945492SAndroid Build Coastguard Worker malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) :
1377*c9945492SAndroid Build Coastguard Worker realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1));
1378*c9945492SAndroid Build Coastguard Worker if (!tmp) {
1379*c9945492SAndroid Build Coastguard Worker error("Error recording dependencies for %s", p->name);
1380*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1381*c9945492SAndroid Build Coastguard Worker continue;
1382*c9945492SAndroid Build Coastguard Worker }
1383*c9945492SAndroid Build Coastguard Worker if (no_realloc) {
1384*c9945492SAndroid Build Coastguard Worker memcpy(tmp, p->deps, sizeof(*tmp) * (ndeps_all+1));
1385*c9945492SAndroid Build Coastguard Worker no_realloc = 0;
1386*c9945492SAndroid Build Coastguard Worker }
1387*c9945492SAndroid Build Coastguard Worker p->deps = tmp;
1388*c9945492SAndroid Build Coastguard Worker for (j=0; j<dep->ndeps_direct; j++) {
1389*c9945492SAndroid Build Coastguard Worker if (dep->deps[j]->mark) continue;
1390*c9945492SAndroid Build Coastguard Worker dep->deps[j]->mark = 1;
1391*c9945492SAndroid Build Coastguard Worker p->deps[ndeps_all++] = dep->deps[j];
1392*c9945492SAndroid Build Coastguard Worker }
1393*c9945492SAndroid Build Coastguard Worker p->deps[ndeps_all] = 0;
1394*c9945492SAndroid Build Coastguard Worker }
1395*c9945492SAndroid Build Coastguard Worker p->bfs_built = 1;
1396*c9945492SAndroid Build Coastguard Worker for (p=head; p; p=p->next)
1397*c9945492SAndroid Build Coastguard Worker p->mark = 0;
1398*c9945492SAndroid Build Coastguard Worker }
1399*c9945492SAndroid Build Coastguard Worker
load_preload(char * s)1400*c9945492SAndroid Build Coastguard Worker static void load_preload(char *s)
1401*c9945492SAndroid Build Coastguard Worker {
1402*c9945492SAndroid Build Coastguard Worker int tmp;
1403*c9945492SAndroid Build Coastguard Worker char *z;
1404*c9945492SAndroid Build Coastguard Worker for (z=s; *z; s=z) {
1405*c9945492SAndroid Build Coastguard Worker for ( ; *s && (isspace(*s) || *s==':'); s++);
1406*c9945492SAndroid Build Coastguard Worker for (z=s; *z && !isspace(*z) && *z!=':'; z++);
1407*c9945492SAndroid Build Coastguard Worker tmp = *z;
1408*c9945492SAndroid Build Coastguard Worker *z = 0;
1409*c9945492SAndroid Build Coastguard Worker load_library(s, 0);
1410*c9945492SAndroid Build Coastguard Worker *z = tmp;
1411*c9945492SAndroid Build Coastguard Worker }
1412*c9945492SAndroid Build Coastguard Worker }
1413*c9945492SAndroid Build Coastguard Worker
add_syms(struct dso * p)1414*c9945492SAndroid Build Coastguard Worker static void add_syms(struct dso *p)
1415*c9945492SAndroid Build Coastguard Worker {
1416*c9945492SAndroid Build Coastguard Worker if (!p->syms_next && syms_tail != p) {
1417*c9945492SAndroid Build Coastguard Worker syms_tail->syms_next = p;
1418*c9945492SAndroid Build Coastguard Worker syms_tail = p;
1419*c9945492SAndroid Build Coastguard Worker }
1420*c9945492SAndroid Build Coastguard Worker }
1421*c9945492SAndroid Build Coastguard Worker
revert_syms(struct dso * old_tail)1422*c9945492SAndroid Build Coastguard Worker static void revert_syms(struct dso *old_tail)
1423*c9945492SAndroid Build Coastguard Worker {
1424*c9945492SAndroid Build Coastguard Worker struct dso *p, *next;
1425*c9945492SAndroid Build Coastguard Worker /* Chop off the tail of the list of dsos that participate in
1426*c9945492SAndroid Build Coastguard Worker * the global symbol table, reverting them to RTLD_LOCAL. */
1427*c9945492SAndroid Build Coastguard Worker for (p=old_tail; p; p=next) {
1428*c9945492SAndroid Build Coastguard Worker next = p->syms_next;
1429*c9945492SAndroid Build Coastguard Worker p->syms_next = 0;
1430*c9945492SAndroid Build Coastguard Worker }
1431*c9945492SAndroid Build Coastguard Worker syms_tail = old_tail;
1432*c9945492SAndroid Build Coastguard Worker }
1433*c9945492SAndroid Build Coastguard Worker
do_mips_relocs(struct dso * p,size_t * got)1434*c9945492SAndroid Build Coastguard Worker static void do_mips_relocs(struct dso *p, size_t *got)
1435*c9945492SAndroid Build Coastguard Worker {
1436*c9945492SAndroid Build Coastguard Worker size_t i, j, rel[2];
1437*c9945492SAndroid Build Coastguard Worker unsigned char *base = p->base;
1438*c9945492SAndroid Build Coastguard Worker i=0; search_vec(p->dynv, &i, DT_MIPS_LOCAL_GOTNO);
1439*c9945492SAndroid Build Coastguard Worker if (p==&ldso) {
1440*c9945492SAndroid Build Coastguard Worker got += i;
1441*c9945492SAndroid Build Coastguard Worker } else {
1442*c9945492SAndroid Build Coastguard Worker while (i--) *got++ += (size_t)base;
1443*c9945492SAndroid Build Coastguard Worker }
1444*c9945492SAndroid Build Coastguard Worker j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
1445*c9945492SAndroid Build Coastguard Worker i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
1446*c9945492SAndroid Build Coastguard Worker Sym *sym = p->syms + j;
1447*c9945492SAndroid Build Coastguard Worker rel[0] = (unsigned char *)got - base;
1448*c9945492SAndroid Build Coastguard Worker for (i-=j; i; i--, sym++, rel[0]+=sizeof(size_t)) {
1449*c9945492SAndroid Build Coastguard Worker rel[1] = R_INFO(sym-p->syms, R_MIPS_JUMP_SLOT);
1450*c9945492SAndroid Build Coastguard Worker do_relocs(p, rel, sizeof rel, 2);
1451*c9945492SAndroid Build Coastguard Worker }
1452*c9945492SAndroid Build Coastguard Worker }
1453*c9945492SAndroid Build Coastguard Worker
reloc_all(struct dso * p)1454*c9945492SAndroid Build Coastguard Worker static void reloc_all(struct dso *p)
1455*c9945492SAndroid Build Coastguard Worker {
1456*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT];
1457*c9945492SAndroid Build Coastguard Worker for (; p; p=p->next) {
1458*c9945492SAndroid Build Coastguard Worker if (p->relocated) continue;
1459*c9945492SAndroid Build Coastguard Worker decode_vec(p->dynv, dyn, DYN_CNT);
1460*c9945492SAndroid Build Coastguard Worker if (NEED_MIPS_GOT_RELOCS)
1461*c9945492SAndroid Build Coastguard Worker do_mips_relocs(p, laddr(p, dyn[DT_PLTGOT]));
1462*c9945492SAndroid Build Coastguard Worker do_relocs(p, laddr(p, dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
1463*c9945492SAndroid Build Coastguard Worker 2+(dyn[DT_PLTREL]==DT_RELA));
1464*c9945492SAndroid Build Coastguard Worker do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
1465*c9945492SAndroid Build Coastguard Worker do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
1466*c9945492SAndroid Build Coastguard Worker if (!DL_FDPIC)
1467*c9945492SAndroid Build Coastguard Worker do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);
1468*c9945492SAndroid Build Coastguard Worker
1469*c9945492SAndroid Build Coastguard Worker if (head != &ldso && p->relro_start != p->relro_end) {
1470*c9945492SAndroid Build Coastguard Worker long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
1471*c9945492SAndroid Build Coastguard Worker p->relro_end-p->relro_start, PROT_READ);
1472*c9945492SAndroid Build Coastguard Worker if (ret != 0 && ret != -ENOSYS) {
1473*c9945492SAndroid Build Coastguard Worker error("Error relocating %s: RELRO protection failed: %m",
1474*c9945492SAndroid Build Coastguard Worker p->name);
1475*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1476*c9945492SAndroid Build Coastguard Worker }
1477*c9945492SAndroid Build Coastguard Worker }
1478*c9945492SAndroid Build Coastguard Worker
1479*c9945492SAndroid Build Coastguard Worker p->relocated = 1;
1480*c9945492SAndroid Build Coastguard Worker }
1481*c9945492SAndroid Build Coastguard Worker }
1482*c9945492SAndroid Build Coastguard Worker
kernel_mapped_dso(struct dso * p)1483*c9945492SAndroid Build Coastguard Worker static void kernel_mapped_dso(struct dso *p)
1484*c9945492SAndroid Build Coastguard Worker {
1485*c9945492SAndroid Build Coastguard Worker size_t min_addr = -1, max_addr = 0, cnt;
1486*c9945492SAndroid Build Coastguard Worker Phdr *ph = p->phdr;
1487*c9945492SAndroid Build Coastguard Worker for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
1488*c9945492SAndroid Build Coastguard Worker if (ph->p_type == PT_DYNAMIC) {
1489*c9945492SAndroid Build Coastguard Worker p->dynv = laddr(p, ph->p_vaddr);
1490*c9945492SAndroid Build Coastguard Worker } else if (ph->p_type == PT_GNU_RELRO) {
1491*c9945492SAndroid Build Coastguard Worker p->relro_start = ph->p_vaddr & -PAGE_SIZE;
1492*c9945492SAndroid Build Coastguard Worker p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
1493*c9945492SAndroid Build Coastguard Worker } else if (ph->p_type == PT_GNU_STACK) {
1494*c9945492SAndroid Build Coastguard Worker if (!runtime && ph->p_memsz > __default_stacksize) {
1495*c9945492SAndroid Build Coastguard Worker __default_stacksize =
1496*c9945492SAndroid Build Coastguard Worker ph->p_memsz < DEFAULT_STACK_MAX ?
1497*c9945492SAndroid Build Coastguard Worker ph->p_memsz : DEFAULT_STACK_MAX;
1498*c9945492SAndroid Build Coastguard Worker }
1499*c9945492SAndroid Build Coastguard Worker }
1500*c9945492SAndroid Build Coastguard Worker if (ph->p_type != PT_LOAD) continue;
1501*c9945492SAndroid Build Coastguard Worker if (ph->p_vaddr < min_addr)
1502*c9945492SAndroid Build Coastguard Worker min_addr = ph->p_vaddr;
1503*c9945492SAndroid Build Coastguard Worker if (ph->p_vaddr+ph->p_memsz > max_addr)
1504*c9945492SAndroid Build Coastguard Worker max_addr = ph->p_vaddr+ph->p_memsz;
1505*c9945492SAndroid Build Coastguard Worker }
1506*c9945492SAndroid Build Coastguard Worker min_addr &= -PAGE_SIZE;
1507*c9945492SAndroid Build Coastguard Worker max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;
1508*c9945492SAndroid Build Coastguard Worker p->map = p->base + min_addr;
1509*c9945492SAndroid Build Coastguard Worker p->map_len = max_addr - min_addr;
1510*c9945492SAndroid Build Coastguard Worker p->kernel_mapped = 1;
1511*c9945492SAndroid Build Coastguard Worker }
1512*c9945492SAndroid Build Coastguard Worker
__libc_exit_fini()1513*c9945492SAndroid Build Coastguard Worker void __libc_exit_fini()
1514*c9945492SAndroid Build Coastguard Worker {
1515*c9945492SAndroid Build Coastguard Worker struct dso *p;
1516*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT];
1517*c9945492SAndroid Build Coastguard Worker pthread_t self = __pthread_self();
1518*c9945492SAndroid Build Coastguard Worker
1519*c9945492SAndroid Build Coastguard Worker /* Take both locks before setting shutting_down, so that
1520*c9945492SAndroid Build Coastguard Worker * either lock is sufficient to read its value. The lock
1521*c9945492SAndroid Build Coastguard Worker * order matches that in dlopen to avoid deadlock. */
1522*c9945492SAndroid Build Coastguard Worker pthread_rwlock_wrlock(&lock);
1523*c9945492SAndroid Build Coastguard Worker pthread_mutex_lock(&init_fini_lock);
1524*c9945492SAndroid Build Coastguard Worker shutting_down = 1;
1525*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
1526*c9945492SAndroid Build Coastguard Worker for (p=fini_head; p; p=p->fini_next) {
1527*c9945492SAndroid Build Coastguard Worker while (p->ctor_visitor && p->ctor_visitor!=self)
1528*c9945492SAndroid Build Coastguard Worker pthread_cond_wait(&ctor_cond, &init_fini_lock);
1529*c9945492SAndroid Build Coastguard Worker if (!p->constructed) continue;
1530*c9945492SAndroid Build Coastguard Worker decode_vec(p->dynv, dyn, DYN_CNT);
1531*c9945492SAndroid Build Coastguard Worker if (dyn[0] & (1<<DT_FINI_ARRAY)) {
1532*c9945492SAndroid Build Coastguard Worker size_t n = dyn[DT_FINI_ARRAYSZ]/sizeof(size_t);
1533*c9945492SAndroid Build Coastguard Worker size_t *fn = (size_t *)laddr(p, dyn[DT_FINI_ARRAY])+n;
1534*c9945492SAndroid Build Coastguard Worker while (n--) ((void (*)(void))*--fn)();
1535*c9945492SAndroid Build Coastguard Worker }
1536*c9945492SAndroid Build Coastguard Worker #ifndef NO_LEGACY_INITFINI
1537*c9945492SAndroid Build Coastguard Worker if ((dyn[0] & (1<<DT_FINI)) && dyn[DT_FINI])
1538*c9945492SAndroid Build Coastguard Worker fpaddr(p, dyn[DT_FINI])();
1539*c9945492SAndroid Build Coastguard Worker #endif
1540*c9945492SAndroid Build Coastguard Worker }
1541*c9945492SAndroid Build Coastguard Worker }
1542*c9945492SAndroid Build Coastguard Worker
__ldso_atfork(int who)1543*c9945492SAndroid Build Coastguard Worker void __ldso_atfork(int who)
1544*c9945492SAndroid Build Coastguard Worker {
1545*c9945492SAndroid Build Coastguard Worker if (who<0) {
1546*c9945492SAndroid Build Coastguard Worker pthread_rwlock_wrlock(&lock);
1547*c9945492SAndroid Build Coastguard Worker pthread_mutex_lock(&init_fini_lock);
1548*c9945492SAndroid Build Coastguard Worker } else {
1549*c9945492SAndroid Build Coastguard Worker pthread_mutex_unlock(&init_fini_lock);
1550*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
1551*c9945492SAndroid Build Coastguard Worker }
1552*c9945492SAndroid Build Coastguard Worker }
1553*c9945492SAndroid Build Coastguard Worker
queue_ctors(struct dso * dso)1554*c9945492SAndroid Build Coastguard Worker static struct dso **queue_ctors(struct dso *dso)
1555*c9945492SAndroid Build Coastguard Worker {
1556*c9945492SAndroid Build Coastguard Worker size_t cnt, qpos, spos, i;
1557*c9945492SAndroid Build Coastguard Worker struct dso *p, **queue, **stack;
1558*c9945492SAndroid Build Coastguard Worker
1559*c9945492SAndroid Build Coastguard Worker if (ldd_mode) return 0;
1560*c9945492SAndroid Build Coastguard Worker
1561*c9945492SAndroid Build Coastguard Worker /* Bound on queue size is the total number of indirect deps.
1562*c9945492SAndroid Build Coastguard Worker * If a bfs deps list was built, we can use it. Otherwise,
1563*c9945492SAndroid Build Coastguard Worker * bound by the total number of DSOs, which is always safe and
1564*c9945492SAndroid Build Coastguard Worker * is reasonable we use it (for main app at startup). */
1565*c9945492SAndroid Build Coastguard Worker if (dso->bfs_built) {
1566*c9945492SAndroid Build Coastguard Worker for (cnt=0; dso->deps[cnt]; cnt++)
1567*c9945492SAndroid Build Coastguard Worker dso->deps[cnt]->mark = 0;
1568*c9945492SAndroid Build Coastguard Worker cnt++; /* self, not included in deps */
1569*c9945492SAndroid Build Coastguard Worker } else {
1570*c9945492SAndroid Build Coastguard Worker for (cnt=0, p=head; p; cnt++, p=p->next)
1571*c9945492SAndroid Build Coastguard Worker p->mark = 0;
1572*c9945492SAndroid Build Coastguard Worker }
1573*c9945492SAndroid Build Coastguard Worker cnt++; /* termination slot */
1574*c9945492SAndroid Build Coastguard Worker if (dso==head && cnt <= countof(builtin_ctor_queue))
1575*c9945492SAndroid Build Coastguard Worker queue = builtin_ctor_queue;
1576*c9945492SAndroid Build Coastguard Worker else
1577*c9945492SAndroid Build Coastguard Worker queue = calloc(cnt, sizeof *queue);
1578*c9945492SAndroid Build Coastguard Worker
1579*c9945492SAndroid Build Coastguard Worker if (!queue) {
1580*c9945492SAndroid Build Coastguard Worker error("Error allocating constructor queue: %m\n");
1581*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1582*c9945492SAndroid Build Coastguard Worker return 0;
1583*c9945492SAndroid Build Coastguard Worker }
1584*c9945492SAndroid Build Coastguard Worker
1585*c9945492SAndroid Build Coastguard Worker /* Opposite ends of the allocated buffer serve as an output queue
1586*c9945492SAndroid Build Coastguard Worker * and a working stack. Setup initial stack with just the argument
1587*c9945492SAndroid Build Coastguard Worker * dso and initial queue empty... */
1588*c9945492SAndroid Build Coastguard Worker stack = queue;
1589*c9945492SAndroid Build Coastguard Worker qpos = 0;
1590*c9945492SAndroid Build Coastguard Worker spos = cnt;
1591*c9945492SAndroid Build Coastguard Worker stack[--spos] = dso;
1592*c9945492SAndroid Build Coastguard Worker dso->next_dep = 0;
1593*c9945492SAndroid Build Coastguard Worker dso->mark = 1;
1594*c9945492SAndroid Build Coastguard Worker
1595*c9945492SAndroid Build Coastguard Worker /* Then perform pseudo-DFS sort, but ignoring circular deps. */
1596*c9945492SAndroid Build Coastguard Worker while (spos<cnt) {
1597*c9945492SAndroid Build Coastguard Worker p = stack[spos++];
1598*c9945492SAndroid Build Coastguard Worker while (p->next_dep < p->ndeps_direct) {
1599*c9945492SAndroid Build Coastguard Worker if (p->deps[p->next_dep]->mark) {
1600*c9945492SAndroid Build Coastguard Worker p->next_dep++;
1601*c9945492SAndroid Build Coastguard Worker } else {
1602*c9945492SAndroid Build Coastguard Worker stack[--spos] = p;
1603*c9945492SAndroid Build Coastguard Worker p = p->deps[p->next_dep];
1604*c9945492SAndroid Build Coastguard Worker p->next_dep = 0;
1605*c9945492SAndroid Build Coastguard Worker p->mark = 1;
1606*c9945492SAndroid Build Coastguard Worker }
1607*c9945492SAndroid Build Coastguard Worker }
1608*c9945492SAndroid Build Coastguard Worker queue[qpos++] = p;
1609*c9945492SAndroid Build Coastguard Worker }
1610*c9945492SAndroid Build Coastguard Worker queue[qpos] = 0;
1611*c9945492SAndroid Build Coastguard Worker for (i=0; i<qpos; i++) queue[i]->mark = 0;
1612*c9945492SAndroid Build Coastguard Worker for (i=0; i<qpos; i++)
1613*c9945492SAndroid Build Coastguard Worker if (queue[i]->ctor_visitor && queue[i]->ctor_visitor->tid < 0) {
1614*c9945492SAndroid Build Coastguard Worker error("State of %s is inconsistent due to multithreaded fork\n",
1615*c9945492SAndroid Build Coastguard Worker queue[i]->name);
1616*c9945492SAndroid Build Coastguard Worker free(queue);
1617*c9945492SAndroid Build Coastguard Worker if (runtime) longjmp(*rtld_fail, 1);
1618*c9945492SAndroid Build Coastguard Worker }
1619*c9945492SAndroid Build Coastguard Worker
1620*c9945492SAndroid Build Coastguard Worker return queue;
1621*c9945492SAndroid Build Coastguard Worker }
1622*c9945492SAndroid Build Coastguard Worker
do_init_fini(struct dso ** queue)1623*c9945492SAndroid Build Coastguard Worker static void do_init_fini(struct dso **queue)
1624*c9945492SAndroid Build Coastguard Worker {
1625*c9945492SAndroid Build Coastguard Worker struct dso *p;
1626*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT], i;
1627*c9945492SAndroid Build Coastguard Worker pthread_t self = __pthread_self();
1628*c9945492SAndroid Build Coastguard Worker
1629*c9945492SAndroid Build Coastguard Worker pthread_mutex_lock(&init_fini_lock);
1630*c9945492SAndroid Build Coastguard Worker for (i=0; (p=queue[i]); i++) {
1631*c9945492SAndroid Build Coastguard Worker while ((p->ctor_visitor && p->ctor_visitor!=self) || shutting_down)
1632*c9945492SAndroid Build Coastguard Worker pthread_cond_wait(&ctor_cond, &init_fini_lock);
1633*c9945492SAndroid Build Coastguard Worker if (p->ctor_visitor || p->constructed)
1634*c9945492SAndroid Build Coastguard Worker continue;
1635*c9945492SAndroid Build Coastguard Worker p->ctor_visitor = self;
1636*c9945492SAndroid Build Coastguard Worker
1637*c9945492SAndroid Build Coastguard Worker decode_vec(p->dynv, dyn, DYN_CNT);
1638*c9945492SAndroid Build Coastguard Worker if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
1639*c9945492SAndroid Build Coastguard Worker p->fini_next = fini_head;
1640*c9945492SAndroid Build Coastguard Worker fini_head = p;
1641*c9945492SAndroid Build Coastguard Worker }
1642*c9945492SAndroid Build Coastguard Worker
1643*c9945492SAndroid Build Coastguard Worker pthread_mutex_unlock(&init_fini_lock);
1644*c9945492SAndroid Build Coastguard Worker
1645*c9945492SAndroid Build Coastguard Worker #ifndef NO_LEGACY_INITFINI
1646*c9945492SAndroid Build Coastguard Worker if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT])
1647*c9945492SAndroid Build Coastguard Worker fpaddr(p, dyn[DT_INIT])();
1648*c9945492SAndroid Build Coastguard Worker #endif
1649*c9945492SAndroid Build Coastguard Worker if (dyn[0] & (1<<DT_INIT_ARRAY)) {
1650*c9945492SAndroid Build Coastguard Worker size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t);
1651*c9945492SAndroid Build Coastguard Worker size_t *fn = laddr(p, dyn[DT_INIT_ARRAY]);
1652*c9945492SAndroid Build Coastguard Worker while (n--) ((void (*)(void))*fn++)();
1653*c9945492SAndroid Build Coastguard Worker }
1654*c9945492SAndroid Build Coastguard Worker
1655*c9945492SAndroid Build Coastguard Worker pthread_mutex_lock(&init_fini_lock);
1656*c9945492SAndroid Build Coastguard Worker p->ctor_visitor = 0;
1657*c9945492SAndroid Build Coastguard Worker p->constructed = 1;
1658*c9945492SAndroid Build Coastguard Worker pthread_cond_broadcast(&ctor_cond);
1659*c9945492SAndroid Build Coastguard Worker }
1660*c9945492SAndroid Build Coastguard Worker pthread_mutex_unlock(&init_fini_lock);
1661*c9945492SAndroid Build Coastguard Worker }
1662*c9945492SAndroid Build Coastguard Worker
__libc_start_init(void)1663*c9945492SAndroid Build Coastguard Worker void __libc_start_init(void)
1664*c9945492SAndroid Build Coastguard Worker {
1665*c9945492SAndroid Build Coastguard Worker do_init_fini(main_ctor_queue);
1666*c9945492SAndroid Build Coastguard Worker if (!__malloc_replaced && main_ctor_queue != builtin_ctor_queue)
1667*c9945492SAndroid Build Coastguard Worker free(main_ctor_queue);
1668*c9945492SAndroid Build Coastguard Worker main_ctor_queue = 0;
1669*c9945492SAndroid Build Coastguard Worker }
1670*c9945492SAndroid Build Coastguard Worker
dl_debug_state(void)1671*c9945492SAndroid Build Coastguard Worker static void dl_debug_state(void)
1672*c9945492SAndroid Build Coastguard Worker {
1673*c9945492SAndroid Build Coastguard Worker if (exe_dl_debug_state)
1674*c9945492SAndroid Build Coastguard Worker exe_dl_debug_state();
1675*c9945492SAndroid Build Coastguard Worker }
1676*c9945492SAndroid Build Coastguard Worker
1677*c9945492SAndroid Build Coastguard Worker weak_alias(dl_debug_state, _dl_debug_state);
1678*c9945492SAndroid Build Coastguard Worker
__init_tls(size_t * auxv)1679*c9945492SAndroid Build Coastguard Worker void __init_tls(size_t *auxv)
1680*c9945492SAndroid Build Coastguard Worker {
1681*c9945492SAndroid Build Coastguard Worker }
1682*c9945492SAndroid Build Coastguard Worker
update_tls_size()1683*c9945492SAndroid Build Coastguard Worker static void update_tls_size()
1684*c9945492SAndroid Build Coastguard Worker {
1685*c9945492SAndroid Build Coastguard Worker libc.tls_cnt = tls_cnt;
1686*c9945492SAndroid Build Coastguard Worker libc.tls_align = tls_align;
1687*c9945492SAndroid Build Coastguard Worker libc.tls_size = ALIGN(
1688*c9945492SAndroid Build Coastguard Worker (1+tls_cnt) * sizeof(void *) +
1689*c9945492SAndroid Build Coastguard Worker tls_offset +
1690*c9945492SAndroid Build Coastguard Worker sizeof(struct pthread) +
1691*c9945492SAndroid Build Coastguard Worker tls_align * 2,
1692*c9945492SAndroid Build Coastguard Worker tls_align);
1693*c9945492SAndroid Build Coastguard Worker }
1694*c9945492SAndroid Build Coastguard Worker
install_new_tls(void)1695*c9945492SAndroid Build Coastguard Worker static void install_new_tls(void)
1696*c9945492SAndroid Build Coastguard Worker {
1697*c9945492SAndroid Build Coastguard Worker sigset_t set;
1698*c9945492SAndroid Build Coastguard Worker pthread_t self = __pthread_self(), td;
1699*c9945492SAndroid Build Coastguard Worker struct dso *dtv_provider = container_of(tls_tail, struct dso, tls);
1700*c9945492SAndroid Build Coastguard Worker uintptr_t (*newdtv)[tls_cnt+1] = (void *)dtv_provider->new_dtv;
1701*c9945492SAndroid Build Coastguard Worker struct dso *p;
1702*c9945492SAndroid Build Coastguard Worker size_t i, j;
1703*c9945492SAndroid Build Coastguard Worker size_t old_cnt = self->dtv[0];
1704*c9945492SAndroid Build Coastguard Worker
1705*c9945492SAndroid Build Coastguard Worker __block_app_sigs(&set);
1706*c9945492SAndroid Build Coastguard Worker __tl_lock();
1707*c9945492SAndroid Build Coastguard Worker /* Copy existing dtv contents from all existing threads. */
1708*c9945492SAndroid Build Coastguard Worker for (i=0, td=self; !i || td!=self; i++, td=td->next) {
1709*c9945492SAndroid Build Coastguard Worker memcpy(newdtv+i, td->dtv,
1710*c9945492SAndroid Build Coastguard Worker (old_cnt+1)*sizeof(uintptr_t));
1711*c9945492SAndroid Build Coastguard Worker newdtv[i][0] = tls_cnt;
1712*c9945492SAndroid Build Coastguard Worker }
1713*c9945492SAndroid Build Coastguard Worker /* Install new dtls into the enlarged, uninstalled dtv copies. */
1714*c9945492SAndroid Build Coastguard Worker for (p=head; ; p=p->next) {
1715*c9945492SAndroid Build Coastguard Worker if (p->tls_id <= old_cnt) continue;
1716*c9945492SAndroid Build Coastguard Worker unsigned char *mem = p->new_tls;
1717*c9945492SAndroid Build Coastguard Worker for (j=0; j<i; j++) {
1718*c9945492SAndroid Build Coastguard Worker unsigned char *new = mem;
1719*c9945492SAndroid Build Coastguard Worker new += ((uintptr_t)p->tls.image - (uintptr_t)mem)
1720*c9945492SAndroid Build Coastguard Worker & (p->tls.align-1);
1721*c9945492SAndroid Build Coastguard Worker memcpy(new, p->tls.image, p->tls.len);
1722*c9945492SAndroid Build Coastguard Worker newdtv[j][p->tls_id] =
1723*c9945492SAndroid Build Coastguard Worker (uintptr_t)new + DTP_OFFSET;
1724*c9945492SAndroid Build Coastguard Worker mem += p->tls.size + p->tls.align;
1725*c9945492SAndroid Build Coastguard Worker }
1726*c9945492SAndroid Build Coastguard Worker if (p->tls_id == tls_cnt) break;
1727*c9945492SAndroid Build Coastguard Worker }
1728*c9945492SAndroid Build Coastguard Worker
1729*c9945492SAndroid Build Coastguard Worker /* Broadcast barrier to ensure contents of new dtv is visible
1730*c9945492SAndroid Build Coastguard Worker * if the new dtv pointer is. The __membarrier function has a
1731*c9945492SAndroid Build Coastguard Worker * fallback emulation using signals for kernels that lack the
1732*c9945492SAndroid Build Coastguard Worker * feature at the syscall level. */
1733*c9945492SAndroid Build Coastguard Worker
1734*c9945492SAndroid Build Coastguard Worker __membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0);
1735*c9945492SAndroid Build Coastguard Worker
1736*c9945492SAndroid Build Coastguard Worker /* Install new dtv for each thread. */
1737*c9945492SAndroid Build Coastguard Worker for (j=0, td=self; !j || td!=self; j++, td=td->next) {
1738*c9945492SAndroid Build Coastguard Worker td->dtv = newdtv[j];
1739*c9945492SAndroid Build Coastguard Worker }
1740*c9945492SAndroid Build Coastguard Worker
1741*c9945492SAndroid Build Coastguard Worker __tl_unlock();
1742*c9945492SAndroid Build Coastguard Worker __restore_sigs(&set);
1743*c9945492SAndroid Build Coastguard Worker }
1744*c9945492SAndroid Build Coastguard Worker
1745*c9945492SAndroid Build Coastguard Worker /* Stage 1 of the dynamic linker is defined in dlstart.c. It calls the
1746*c9945492SAndroid Build Coastguard Worker * following stage 2 and stage 3 functions via primitive symbolic lookup
1747*c9945492SAndroid Build Coastguard Worker * since it does not have access to their addresses to begin with. */
1748*c9945492SAndroid Build Coastguard Worker
1749*c9945492SAndroid Build Coastguard Worker /* Stage 2 of the dynamic linker is called after relative relocations
1750*c9945492SAndroid Build Coastguard Worker * have been processed. It can make function calls to static functions
1751*c9945492SAndroid Build Coastguard Worker * and access string literals and static data, but cannot use extern
1752*c9945492SAndroid Build Coastguard Worker * symbols. Its job is to perform symbolic relocations on the dynamic
1753*c9945492SAndroid Build Coastguard Worker * linker itself, but some of the relocations performed may need to be
1754*c9945492SAndroid Build Coastguard Worker * replaced later due to copy relocations in the main program. */
1755*c9945492SAndroid Build Coastguard Worker
__dls2(unsigned char * base,size_t * sp)1756*c9945492SAndroid Build Coastguard Worker hidden void __dls2(unsigned char *base, size_t *sp)
1757*c9945492SAndroid Build Coastguard Worker {
1758*c9945492SAndroid Build Coastguard Worker size_t *auxv;
1759*c9945492SAndroid Build Coastguard Worker for (auxv=sp+1+*sp+1; *auxv; auxv++);
1760*c9945492SAndroid Build Coastguard Worker auxv++;
1761*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) {
1762*c9945492SAndroid Build Coastguard Worker void *p1 = (void *)sp[-2];
1763*c9945492SAndroid Build Coastguard Worker void *p2 = (void *)sp[-1];
1764*c9945492SAndroid Build Coastguard Worker if (!p1) {
1765*c9945492SAndroid Build Coastguard Worker size_t aux[AUX_CNT];
1766*c9945492SAndroid Build Coastguard Worker decode_vec(auxv, aux, AUX_CNT);
1767*c9945492SAndroid Build Coastguard Worker if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE];
1768*c9945492SAndroid Build Coastguard Worker else ldso.base = (void *)(aux[AT_PHDR] & -4096);
1769*c9945492SAndroid Build Coastguard Worker }
1770*c9945492SAndroid Build Coastguard Worker app_loadmap = p2 ? p1 : 0;
1771*c9945492SAndroid Build Coastguard Worker ldso.loadmap = p2 ? p2 : p1;
1772*c9945492SAndroid Build Coastguard Worker ldso.base = laddr(&ldso, 0);
1773*c9945492SAndroid Build Coastguard Worker } else {
1774*c9945492SAndroid Build Coastguard Worker ldso.base = base;
1775*c9945492SAndroid Build Coastguard Worker }
1776*c9945492SAndroid Build Coastguard Worker Ehdr *ehdr = __ehdr_start ? (void *)__ehdr_start : (void *)ldso.base;
1777*c9945492SAndroid Build Coastguard Worker ldso.name = ldso.shortname = STRINGIFY(LIBC_SONAME);
1778*c9945492SAndroid Build Coastguard Worker ldso.phnum = ehdr->e_phnum;
1779*c9945492SAndroid Build Coastguard Worker ldso.phdr = laddr(&ldso, ehdr->e_phoff);
1780*c9945492SAndroid Build Coastguard Worker ldso.phentsize = ehdr->e_phentsize;
1781*c9945492SAndroid Build Coastguard Worker ldso.elfmachine = ehdr->e_machine;
1782*c9945492SAndroid Build Coastguard Worker ldso.elfclass = ehdr->e_ident[EI_CLASS];
1783*c9945492SAndroid Build Coastguard Worker search_vec(auxv, &ldso_page_size, AT_PAGESZ);
1784*c9945492SAndroid Build Coastguard Worker kernel_mapped_dso(&ldso);
1785*c9945492SAndroid Build Coastguard Worker decode_dyn(&ldso);
1786*c9945492SAndroid Build Coastguard Worker
1787*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) makefuncdescs(&ldso);
1788*c9945492SAndroid Build Coastguard Worker
1789*c9945492SAndroid Build Coastguard Worker /* Prepare storage for to save clobbered REL addends so they
1790*c9945492SAndroid Build Coastguard Worker * can be reused in stage 3. There should be very few. If
1791*c9945492SAndroid Build Coastguard Worker * something goes wrong and there are a huge number, abort
1792*c9945492SAndroid Build Coastguard Worker * instead of risking stack overflow. */
1793*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT];
1794*c9945492SAndroid Build Coastguard Worker decode_vec(ldso.dynv, dyn, DYN_CNT);
1795*c9945492SAndroid Build Coastguard Worker size_t *rel = laddr(&ldso, dyn[DT_REL]);
1796*c9945492SAndroid Build Coastguard Worker size_t rel_size = dyn[DT_RELSZ];
1797*c9945492SAndroid Build Coastguard Worker size_t symbolic_rel_cnt = 0;
1798*c9945492SAndroid Build Coastguard Worker apply_addends_to = rel;
1799*c9945492SAndroid Build Coastguard Worker for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t))
1800*c9945492SAndroid Build Coastguard Worker if (!IS_RELATIVE(rel[1], ldso.syms)) symbolic_rel_cnt++;
1801*c9945492SAndroid Build Coastguard Worker if (symbolic_rel_cnt >= ADDEND_LIMIT) a_crash();
1802*c9945492SAndroid Build Coastguard Worker size_t addends[symbolic_rel_cnt+1];
1803*c9945492SAndroid Build Coastguard Worker saved_addends = addends;
1804*c9945492SAndroid Build Coastguard Worker
1805*c9945492SAndroid Build Coastguard Worker head = &ldso;
1806*c9945492SAndroid Build Coastguard Worker reloc_all(&ldso);
1807*c9945492SAndroid Build Coastguard Worker
1808*c9945492SAndroid Build Coastguard Worker ldso.relocated = 0;
1809*c9945492SAndroid Build Coastguard Worker
1810*c9945492SAndroid Build Coastguard Worker /* Call dynamic linker stage-2b, __dls2b, looking it up
1811*c9945492SAndroid Build Coastguard Worker * symbolically as a barrier against moving the address
1812*c9945492SAndroid Build Coastguard Worker * load across the above relocation processing. */
1813*c9945492SAndroid Build Coastguard Worker struct symdef dls2b_def = find_sym(&ldso, "__dls2b", 0);
1814*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls2b_def.sym-ldso.syms])(sp, auxv);
1815*c9945492SAndroid Build Coastguard Worker else ((stage3_func)laddr(&ldso, dls2b_def.sym->st_value))(sp, auxv);
1816*c9945492SAndroid Build Coastguard Worker }
1817*c9945492SAndroid Build Coastguard Worker
1818*c9945492SAndroid Build Coastguard Worker /* Stage 2b sets up a valid thread pointer, which requires relocations
1819*c9945492SAndroid Build Coastguard Worker * completed in stage 2, and on which stage 3 is permitted to depend.
1820*c9945492SAndroid Build Coastguard Worker * This is done as a separate stage, with symbolic lookup as a barrier,
1821*c9945492SAndroid Build Coastguard Worker * so that loads of the thread pointer and &errno can be pure/const and
1822*c9945492SAndroid Build Coastguard Worker * thereby hoistable. */
1823*c9945492SAndroid Build Coastguard Worker
__dls2b(size_t * sp,size_t * auxv)1824*c9945492SAndroid Build Coastguard Worker void __dls2b(size_t *sp, size_t *auxv)
1825*c9945492SAndroid Build Coastguard Worker {
1826*c9945492SAndroid Build Coastguard Worker /* Setup early thread pointer in builtin_tls for ldso/libc itself to
1827*c9945492SAndroid Build Coastguard Worker * use during dynamic linking. If possible it will also serve as the
1828*c9945492SAndroid Build Coastguard Worker * thread pointer at runtime. */
1829*c9945492SAndroid Build Coastguard Worker search_vec(auxv, &__hwcap, AT_HWCAP);
1830*c9945492SAndroid Build Coastguard Worker libc.auxv = auxv;
1831*c9945492SAndroid Build Coastguard Worker libc.tls_size = sizeof builtin_tls;
1832*c9945492SAndroid Build Coastguard Worker libc.tls_align = tls_align;
1833*c9945492SAndroid Build Coastguard Worker if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) {
1834*c9945492SAndroid Build Coastguard Worker a_crash();
1835*c9945492SAndroid Build Coastguard Worker }
1836*c9945492SAndroid Build Coastguard Worker
1837*c9945492SAndroid Build Coastguard Worker struct symdef dls3_def = find_sym(&ldso, "__dls3", 0);
1838*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp, auxv);
1839*c9945492SAndroid Build Coastguard Worker else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp, auxv);
1840*c9945492SAndroid Build Coastguard Worker }
1841*c9945492SAndroid Build Coastguard Worker
1842*c9945492SAndroid Build Coastguard Worker /* Stage 3 of the dynamic linker is called with the dynamic linker/libc
1843*c9945492SAndroid Build Coastguard Worker * fully functional. Its job is to load (if not already loaded) and
1844*c9945492SAndroid Build Coastguard Worker * process dependencies and relocations for the main application and
1845*c9945492SAndroid Build Coastguard Worker * transfer control to its entry point. */
1846*c9945492SAndroid Build Coastguard Worker
__dls3(size_t * sp,size_t * auxv)1847*c9945492SAndroid Build Coastguard Worker void __dls3(size_t *sp, size_t *auxv)
1848*c9945492SAndroid Build Coastguard Worker {
1849*c9945492SAndroid Build Coastguard Worker static struct dso app, vdso;
1850*c9945492SAndroid Build Coastguard Worker size_t aux[AUX_CNT];
1851*c9945492SAndroid Build Coastguard Worker size_t i;
1852*c9945492SAndroid Build Coastguard Worker char *env_preload=0;
1853*c9945492SAndroid Build Coastguard Worker char *replace_argv0=0;
1854*c9945492SAndroid Build Coastguard Worker size_t vdso_base;
1855*c9945492SAndroid Build Coastguard Worker int argc = *sp;
1856*c9945492SAndroid Build Coastguard Worker char **argv = (void *)(sp+1);
1857*c9945492SAndroid Build Coastguard Worker char **argv_orig = argv;
1858*c9945492SAndroid Build Coastguard Worker char **envp = argv+argc+1;
1859*c9945492SAndroid Build Coastguard Worker
1860*c9945492SAndroid Build Coastguard Worker /* Find aux vector just past environ[] and use it to initialize
1861*c9945492SAndroid Build Coastguard Worker * global data that may be needed before we can make syscalls. */
1862*c9945492SAndroid Build Coastguard Worker __environ = envp;
1863*c9945492SAndroid Build Coastguard Worker decode_vec(auxv, aux, AUX_CNT);
1864*c9945492SAndroid Build Coastguard Worker search_vec(auxv, &__sysinfo, AT_SYSINFO);
1865*c9945492SAndroid Build Coastguard Worker __pthread_self()->sysinfo = __sysinfo;
1866*c9945492SAndroid Build Coastguard Worker libc.page_size = aux[AT_PAGESZ];
1867*c9945492SAndroid Build Coastguard Worker libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
1868*c9945492SAndroid Build Coastguard Worker || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]);
1869*c9945492SAndroid Build Coastguard Worker
1870*c9945492SAndroid Build Coastguard Worker /* Only trust user/env if kernel says we're not suid/sgid */
1871*c9945492SAndroid Build Coastguard Worker if (!libc.secure) {
1872*c9945492SAndroid Build Coastguard Worker env_path = getenv("LD_LIBRARY_PATH");
1873*c9945492SAndroid Build Coastguard Worker env_preload = getenv("LD_PRELOAD");
1874*c9945492SAndroid Build Coastguard Worker }
1875*c9945492SAndroid Build Coastguard Worker
1876*c9945492SAndroid Build Coastguard Worker /* Activate error handler function */
1877*c9945492SAndroid Build Coastguard Worker error = error_impl;
1878*c9945492SAndroid Build Coastguard Worker
1879*c9945492SAndroid Build Coastguard Worker /* If the main program was already loaded by the kernel,
1880*c9945492SAndroid Build Coastguard Worker * AT_PHDR will point to some location other than the dynamic
1881*c9945492SAndroid Build Coastguard Worker * linker's program headers. */
1882*c9945492SAndroid Build Coastguard Worker if (aux[AT_PHDR] != (size_t)ldso.phdr) {
1883*c9945492SAndroid Build Coastguard Worker size_t interp_off = 0;
1884*c9945492SAndroid Build Coastguard Worker size_t tls_image = 0;
1885*c9945492SAndroid Build Coastguard Worker /* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
1886*c9945492SAndroid Build Coastguard Worker Phdr *phdr = app.phdr = (void *)aux[AT_PHDR];
1887*c9945492SAndroid Build Coastguard Worker app.phnum = aux[AT_PHNUM];
1888*c9945492SAndroid Build Coastguard Worker app.phentsize = aux[AT_PHENT];
1889*c9945492SAndroid Build Coastguard Worker for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
1890*c9945492SAndroid Build Coastguard Worker if (phdr->p_type == PT_PHDR)
1891*c9945492SAndroid Build Coastguard Worker app.base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
1892*c9945492SAndroid Build Coastguard Worker else if (phdr->p_type == PT_INTERP)
1893*c9945492SAndroid Build Coastguard Worker interp_off = (size_t)phdr->p_vaddr;
1894*c9945492SAndroid Build Coastguard Worker else if (phdr->p_type == PT_TLS) {
1895*c9945492SAndroid Build Coastguard Worker tls_image = phdr->p_vaddr;
1896*c9945492SAndroid Build Coastguard Worker app.tls.len = phdr->p_filesz;
1897*c9945492SAndroid Build Coastguard Worker app.tls.size = phdr->p_memsz;
1898*c9945492SAndroid Build Coastguard Worker app.tls.align = phdr->p_align;
1899*c9945492SAndroid Build Coastguard Worker }
1900*c9945492SAndroid Build Coastguard Worker }
1901*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) app.loadmap = app_loadmap;
1902*c9945492SAndroid Build Coastguard Worker if (app.tls.size) app.tls.image = laddr(&app, tls_image);
1903*c9945492SAndroid Build Coastguard Worker if (interp_off) ldso.name = laddr(&app, interp_off);
1904*c9945492SAndroid Build Coastguard Worker if ((aux[0] & (1UL<<AT_EXECFN))
1905*c9945492SAndroid Build Coastguard Worker && strncmp((char *)aux[AT_EXECFN], "/proc/", 6))
1906*c9945492SAndroid Build Coastguard Worker app.name = (char *)aux[AT_EXECFN];
1907*c9945492SAndroid Build Coastguard Worker else
1908*c9945492SAndroid Build Coastguard Worker app.name = argv[0];
1909*c9945492SAndroid Build Coastguard Worker kernel_mapped_dso(&app);
1910*c9945492SAndroid Build Coastguard Worker } else {
1911*c9945492SAndroid Build Coastguard Worker int fd;
1912*c9945492SAndroid Build Coastguard Worker char *ldname = argv[0];
1913*c9945492SAndroid Build Coastguard Worker size_t l = strlen(ldname);
1914*c9945492SAndroid Build Coastguard Worker if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
1915*c9945492SAndroid Build Coastguard Worker argv++;
1916*c9945492SAndroid Build Coastguard Worker while (argv[0] && argv[0][0]=='-' && argv[0][1]=='-') {
1917*c9945492SAndroid Build Coastguard Worker char *opt = argv[0]+2;
1918*c9945492SAndroid Build Coastguard Worker *argv++ = (void *)-1;
1919*c9945492SAndroid Build Coastguard Worker if (!*opt) {
1920*c9945492SAndroid Build Coastguard Worker break;
1921*c9945492SAndroid Build Coastguard Worker } else if (!memcmp(opt, "list", 5)) {
1922*c9945492SAndroid Build Coastguard Worker ldd_mode = 1;
1923*c9945492SAndroid Build Coastguard Worker } else if (!memcmp(opt, "library-path", 12)) {
1924*c9945492SAndroid Build Coastguard Worker if (opt[12]=='=') env_path = opt+13;
1925*c9945492SAndroid Build Coastguard Worker else if (opt[12]) *argv = 0;
1926*c9945492SAndroid Build Coastguard Worker else if (*argv) env_path = *argv++;
1927*c9945492SAndroid Build Coastguard Worker } else if (!memcmp(opt, "preload", 7)) {
1928*c9945492SAndroid Build Coastguard Worker if (opt[7]=='=') env_preload = opt+8;
1929*c9945492SAndroid Build Coastguard Worker else if (opt[7]) *argv = 0;
1930*c9945492SAndroid Build Coastguard Worker else if (*argv) env_preload = *argv++;
1931*c9945492SAndroid Build Coastguard Worker } else if (!memcmp(opt, "argv0", 5)) {
1932*c9945492SAndroid Build Coastguard Worker if (opt[5]=='=') replace_argv0 = opt+6;
1933*c9945492SAndroid Build Coastguard Worker else if (opt[5]) *argv = 0;
1934*c9945492SAndroid Build Coastguard Worker else if (*argv) replace_argv0 = *argv++;
1935*c9945492SAndroid Build Coastguard Worker } else {
1936*c9945492SAndroid Build Coastguard Worker argv[0] = 0;
1937*c9945492SAndroid Build Coastguard Worker }
1938*c9945492SAndroid Build Coastguard Worker }
1939*c9945492SAndroid Build Coastguard Worker argv[-1] = (void *)(argc - (argv-argv_orig));
1940*c9945492SAndroid Build Coastguard Worker if (!argv[0]) {
1941*c9945492SAndroid Build Coastguard Worker dprintf(2, "musl libc (" LDSO_ARCH ")\n"
1942*c9945492SAndroid Build Coastguard Worker "Version %s\n"
1943*c9945492SAndroid Build Coastguard Worker "Dynamic Program Loader\n"
1944*c9945492SAndroid Build Coastguard Worker "Usage: %s [options] [--] pathname%s\n",
1945*c9945492SAndroid Build Coastguard Worker __libc_version, ldname,
1946*c9945492SAndroid Build Coastguard Worker ldd_mode ? "" : " [args]");
1947*c9945492SAndroid Build Coastguard Worker _exit(1);
1948*c9945492SAndroid Build Coastguard Worker }
1949*c9945492SAndroid Build Coastguard Worker fd = open(argv[0], O_RDONLY);
1950*c9945492SAndroid Build Coastguard Worker if (fd < 0) {
1951*c9945492SAndroid Build Coastguard Worker dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
1952*c9945492SAndroid Build Coastguard Worker _exit(1);
1953*c9945492SAndroid Build Coastguard Worker }
1954*c9945492SAndroid Build Coastguard Worker Ehdr *ehdr = map_library(fd, &app);
1955*c9945492SAndroid Build Coastguard Worker if (!ehdr) {
1956*c9945492SAndroid Build Coastguard Worker dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
1957*c9945492SAndroid Build Coastguard Worker _exit(1);
1958*c9945492SAndroid Build Coastguard Worker }
1959*c9945492SAndroid Build Coastguard Worker close(fd);
1960*c9945492SAndroid Build Coastguard Worker ldso.name = ldname;
1961*c9945492SAndroid Build Coastguard Worker app.name = argv[0];
1962*c9945492SAndroid Build Coastguard Worker aux[AT_ENTRY] = (size_t)laddr(&app, ehdr->e_entry);
1963*c9945492SAndroid Build Coastguard Worker /* Find the name that would have been used for the dynamic
1964*c9945492SAndroid Build Coastguard Worker * linker had ldd not taken its place. */
1965*c9945492SAndroid Build Coastguard Worker if (ldd_mode) {
1966*c9945492SAndroid Build Coastguard Worker for (i=0; i<app.phnum; i++) {
1967*c9945492SAndroid Build Coastguard Worker if (app.phdr[i].p_type == PT_INTERP)
1968*c9945492SAndroid Build Coastguard Worker ldso.name = laddr(&app, app.phdr[i].p_vaddr);
1969*c9945492SAndroid Build Coastguard Worker }
1970*c9945492SAndroid Build Coastguard Worker dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base);
1971*c9945492SAndroid Build Coastguard Worker }
1972*c9945492SAndroid Build Coastguard Worker }
1973*c9945492SAndroid Build Coastguard Worker if (app.tls.size) {
1974*c9945492SAndroid Build Coastguard Worker libc.tls_head = tls_tail = &app.tls;
1975*c9945492SAndroid Build Coastguard Worker app.tls_id = tls_cnt = 1;
1976*c9945492SAndroid Build Coastguard Worker #ifdef TLS_ABOVE_TP
1977*c9945492SAndroid Build Coastguard Worker app.tls.offset = GAP_ABOVE_TP;
1978*c9945492SAndroid Build Coastguard Worker app.tls.offset += (-GAP_ABOVE_TP + (uintptr_t)app.tls.image)
1979*c9945492SAndroid Build Coastguard Worker & (app.tls.align-1);
1980*c9945492SAndroid Build Coastguard Worker tls_offset = app.tls.offset + app.tls.size;
1981*c9945492SAndroid Build Coastguard Worker #else
1982*c9945492SAndroid Build Coastguard Worker tls_offset = app.tls.offset = app.tls.size
1983*c9945492SAndroid Build Coastguard Worker + ( -((uintptr_t)app.tls.image + app.tls.size)
1984*c9945492SAndroid Build Coastguard Worker & (app.tls.align-1) );
1985*c9945492SAndroid Build Coastguard Worker #endif
1986*c9945492SAndroid Build Coastguard Worker tls_align = MAXP2(tls_align, app.tls.align);
1987*c9945492SAndroid Build Coastguard Worker }
1988*c9945492SAndroid Build Coastguard Worker decode_dyn(&app);
1989*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) {
1990*c9945492SAndroid Build Coastguard Worker makefuncdescs(&app);
1991*c9945492SAndroid Build Coastguard Worker if (!app.loadmap) {
1992*c9945492SAndroid Build Coastguard Worker app.loadmap = (void *)&app_dummy_loadmap;
1993*c9945492SAndroid Build Coastguard Worker app.loadmap->nsegs = 1;
1994*c9945492SAndroid Build Coastguard Worker app.loadmap->segs[0].addr = (size_t)app.map;
1995*c9945492SAndroid Build Coastguard Worker app.loadmap->segs[0].p_vaddr = (size_t)app.map
1996*c9945492SAndroid Build Coastguard Worker - (size_t)app.base;
1997*c9945492SAndroid Build Coastguard Worker app.loadmap->segs[0].p_memsz = app.map_len;
1998*c9945492SAndroid Build Coastguard Worker }
1999*c9945492SAndroid Build Coastguard Worker argv[-3] = (void *)app.loadmap;
2000*c9945492SAndroid Build Coastguard Worker }
2001*c9945492SAndroid Build Coastguard Worker
2002*c9945492SAndroid Build Coastguard Worker /* Initial dso chain consists only of the app. */
2003*c9945492SAndroid Build Coastguard Worker head = tail = syms_tail = &app;
2004*c9945492SAndroid Build Coastguard Worker
2005*c9945492SAndroid Build Coastguard Worker /* Donate unused parts of app and library mapping to malloc */
2006*c9945492SAndroid Build Coastguard Worker reclaim_gaps(&app);
2007*c9945492SAndroid Build Coastguard Worker reclaim_gaps(&ldso);
2008*c9945492SAndroid Build Coastguard Worker
2009*c9945492SAndroid Build Coastguard Worker /* Load preload/needed libraries, add symbols to global namespace. */
2010*c9945492SAndroid Build Coastguard Worker ldso.deps = (struct dso **)no_deps;
2011*c9945492SAndroid Build Coastguard Worker if (env_preload) load_preload(env_preload);
2012*c9945492SAndroid Build Coastguard Worker load_deps(&app);
2013*c9945492SAndroid Build Coastguard Worker for (struct dso *p=head; p; p=p->next)
2014*c9945492SAndroid Build Coastguard Worker add_syms(p);
2015*c9945492SAndroid Build Coastguard Worker
2016*c9945492SAndroid Build Coastguard Worker /* Attach to vdso, if provided by the kernel, last so that it does
2017*c9945492SAndroid Build Coastguard Worker * not become part of the global namespace. */
2018*c9945492SAndroid Build Coastguard Worker if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR) && vdso_base) {
2019*c9945492SAndroid Build Coastguard Worker Ehdr *ehdr = (void *)vdso_base;
2020*c9945492SAndroid Build Coastguard Worker Phdr *phdr = vdso.phdr = (void *)(vdso_base + ehdr->e_phoff);
2021*c9945492SAndroid Build Coastguard Worker vdso.phnum = ehdr->e_phnum;
2022*c9945492SAndroid Build Coastguard Worker vdso.phentsize = ehdr->e_phentsize;
2023*c9945492SAndroid Build Coastguard Worker for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
2024*c9945492SAndroid Build Coastguard Worker if (phdr->p_type == PT_DYNAMIC)
2025*c9945492SAndroid Build Coastguard Worker vdso.dynv = (void *)(vdso_base + phdr->p_offset);
2026*c9945492SAndroid Build Coastguard Worker if (phdr->p_type == PT_LOAD)
2027*c9945492SAndroid Build Coastguard Worker vdso.base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
2028*c9945492SAndroid Build Coastguard Worker }
2029*c9945492SAndroid Build Coastguard Worker vdso.name = "";
2030*c9945492SAndroid Build Coastguard Worker vdso.shortname = "linux-gate.so.1";
2031*c9945492SAndroid Build Coastguard Worker vdso.relocated = 1;
2032*c9945492SAndroid Build Coastguard Worker vdso.deps = (struct dso **)no_deps;
2033*c9945492SAndroid Build Coastguard Worker decode_dyn(&vdso);
2034*c9945492SAndroid Build Coastguard Worker vdso.prev = tail;
2035*c9945492SAndroid Build Coastguard Worker tail->next = &vdso;
2036*c9945492SAndroid Build Coastguard Worker tail = &vdso;
2037*c9945492SAndroid Build Coastguard Worker }
2038*c9945492SAndroid Build Coastguard Worker
2039*c9945492SAndroid Build Coastguard Worker for (i=0; app.dynv[i]; i+=2) {
2040*c9945492SAndroid Build Coastguard Worker if (!DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG)
2041*c9945492SAndroid Build Coastguard Worker app.dynv[i+1] = (size_t)&debug;
2042*c9945492SAndroid Build Coastguard Worker if (DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG_INDIRECT) {
2043*c9945492SAndroid Build Coastguard Worker size_t *ptr = (size_t *) app.dynv[i+1];
2044*c9945492SAndroid Build Coastguard Worker *ptr = (size_t)&debug;
2045*c9945492SAndroid Build Coastguard Worker }
2046*c9945492SAndroid Build Coastguard Worker if (app.dynv[i]==DT_DEBUG_INDIRECT_REL) {
2047*c9945492SAndroid Build Coastguard Worker size_t *ptr = (size_t *)((size_t)&app.dynv[i] + app.dynv[i+1]);
2048*c9945492SAndroid Build Coastguard Worker *ptr = (size_t)&debug;
2049*c9945492SAndroid Build Coastguard Worker }
2050*c9945492SAndroid Build Coastguard Worker }
2051*c9945492SAndroid Build Coastguard Worker
2052*c9945492SAndroid Build Coastguard Worker /* This must be done before final relocations, since it calls
2053*c9945492SAndroid Build Coastguard Worker * malloc, which may be provided by the application. Calling any
2054*c9945492SAndroid Build Coastguard Worker * application code prior to the jump to its entry point is not
2055*c9945492SAndroid Build Coastguard Worker * valid in our model and does not work with FDPIC, where there
2056*c9945492SAndroid Build Coastguard Worker * are additional relocation-like fixups that only the entry point
2057*c9945492SAndroid Build Coastguard Worker * code can see to perform. */
2058*c9945492SAndroid Build Coastguard Worker main_ctor_queue = queue_ctors(&app);
2059*c9945492SAndroid Build Coastguard Worker
2060*c9945492SAndroid Build Coastguard Worker /* Initial TLS must also be allocated before final relocations
2061*c9945492SAndroid Build Coastguard Worker * might result in calloc being a call to application code. */
2062*c9945492SAndroid Build Coastguard Worker update_tls_size();
2063*c9945492SAndroid Build Coastguard Worker void *initial_tls = builtin_tls;
2064*c9945492SAndroid Build Coastguard Worker if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) {
2065*c9945492SAndroid Build Coastguard Worker initial_tls = calloc(libc.tls_size, 1);
2066*c9945492SAndroid Build Coastguard Worker if (!initial_tls) {
2067*c9945492SAndroid Build Coastguard Worker dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
2068*c9945492SAndroid Build Coastguard Worker argv[0], libc.tls_size);
2069*c9945492SAndroid Build Coastguard Worker _exit(127);
2070*c9945492SAndroid Build Coastguard Worker }
2071*c9945492SAndroid Build Coastguard Worker }
2072*c9945492SAndroid Build Coastguard Worker static_tls_cnt = tls_cnt;
2073*c9945492SAndroid Build Coastguard Worker
2074*c9945492SAndroid Build Coastguard Worker /* The main program must be relocated LAST since it may contain
2075*c9945492SAndroid Build Coastguard Worker * copy relocations which depend on libraries' relocations. */
2076*c9945492SAndroid Build Coastguard Worker reloc_all(app.next);
2077*c9945492SAndroid Build Coastguard Worker reloc_all(&app);
2078*c9945492SAndroid Build Coastguard Worker
2079*c9945492SAndroid Build Coastguard Worker /* Actual copying to new TLS needs to happen after relocations,
2080*c9945492SAndroid Build Coastguard Worker * since the TLS images might have contained relocated addresses. */
2081*c9945492SAndroid Build Coastguard Worker if (initial_tls != builtin_tls) {
2082*c9945492SAndroid Build Coastguard Worker if (__init_tp(__copy_tls(initial_tls)) < 0) {
2083*c9945492SAndroid Build Coastguard Worker a_crash();
2084*c9945492SAndroid Build Coastguard Worker }
2085*c9945492SAndroid Build Coastguard Worker } else {
2086*c9945492SAndroid Build Coastguard Worker size_t tmp_tls_size = libc.tls_size;
2087*c9945492SAndroid Build Coastguard Worker pthread_t self = __pthread_self();
2088*c9945492SAndroid Build Coastguard Worker /* Temporarily set the tls size to the full size of
2089*c9945492SAndroid Build Coastguard Worker * builtin_tls so that __copy_tls will use the same layout
2090*c9945492SAndroid Build Coastguard Worker * as it did for before. Then check, just to be safe. */
2091*c9945492SAndroid Build Coastguard Worker libc.tls_size = sizeof builtin_tls;
2092*c9945492SAndroid Build Coastguard Worker if (__copy_tls((void*)builtin_tls) != self) a_crash();
2093*c9945492SAndroid Build Coastguard Worker libc.tls_size = tmp_tls_size;
2094*c9945492SAndroid Build Coastguard Worker }
2095*c9945492SAndroid Build Coastguard Worker
2096*c9945492SAndroid Build Coastguard Worker if (ldso_fail) _exit(127);
2097*c9945492SAndroid Build Coastguard Worker if (ldd_mode) _exit(0);
2098*c9945492SAndroid Build Coastguard Worker
2099*c9945492SAndroid Build Coastguard Worker /* Determine if malloc was interposed by a replacement implementation
2100*c9945492SAndroid Build Coastguard Worker * so that calloc and the memalign family can harden against the
2101*c9945492SAndroid Build Coastguard Worker * possibility of incomplete replacement. */
2102*c9945492SAndroid Build Coastguard Worker if (find_sym(head, "malloc", 1).dso != &ldso)
2103*c9945492SAndroid Build Coastguard Worker __malloc_replaced = 1;
2104*c9945492SAndroid Build Coastguard Worker if (find_sym(head, "aligned_alloc", 1).dso != &ldso)
2105*c9945492SAndroid Build Coastguard Worker __aligned_alloc_replaced = 1;
2106*c9945492SAndroid Build Coastguard Worker
2107*c9945492SAndroid Build Coastguard Worker /* Determine if another DSO is providing the _dl_debug_state symbol
2108*c9945492SAndroid Build Coastguard Worker * and forward calls to it. */
2109*c9945492SAndroid Build Coastguard Worker struct symdef debug_sym = find_sym(head, "_dl_debug_state", 1);
2110*c9945492SAndroid Build Coastguard Worker if (debug_sym.dso != &ldso)
2111*c9945492SAndroid Build Coastguard Worker exe_dl_debug_state = (void (*)(void))laddr(debug_sym.dso, debug_sym.sym->st_value);
2112*c9945492SAndroid Build Coastguard Worker
2113*c9945492SAndroid Build Coastguard Worker /* Switch to runtime mode: any further failures in the dynamic
2114*c9945492SAndroid Build Coastguard Worker * linker are a reportable failure rather than a fatal startup
2115*c9945492SAndroid Build Coastguard Worker * error. */
2116*c9945492SAndroid Build Coastguard Worker runtime = 1;
2117*c9945492SAndroid Build Coastguard Worker
2118*c9945492SAndroid Build Coastguard Worker debug.ver = 1;
2119*c9945492SAndroid Build Coastguard Worker debug.bp = dl_debug_state;
2120*c9945492SAndroid Build Coastguard Worker debug.head = head;
2121*c9945492SAndroid Build Coastguard Worker debug.base = ldso.base;
2122*c9945492SAndroid Build Coastguard Worker debug.state = RT_CONSISTENT;
2123*c9945492SAndroid Build Coastguard Worker _dl_debug_state();
2124*c9945492SAndroid Build Coastguard Worker
2125*c9945492SAndroid Build Coastguard Worker if (replace_argv0) argv[0] = replace_argv0;
2126*c9945492SAndroid Build Coastguard Worker
2127*c9945492SAndroid Build Coastguard Worker errno = 0;
2128*c9945492SAndroid Build Coastguard Worker
2129*c9945492SAndroid Build Coastguard Worker CRTJMP((void *)aux[AT_ENTRY], argv-1);
2130*c9945492SAndroid Build Coastguard Worker for(;;);
2131*c9945492SAndroid Build Coastguard Worker }
2132*c9945492SAndroid Build Coastguard Worker
prepare_lazy(struct dso * p)2133*c9945492SAndroid Build Coastguard Worker static void prepare_lazy(struct dso *p)
2134*c9945492SAndroid Build Coastguard Worker {
2135*c9945492SAndroid Build Coastguard Worker size_t dyn[DYN_CNT], n, flags1=0;
2136*c9945492SAndroid Build Coastguard Worker decode_vec(p->dynv, dyn, DYN_CNT);
2137*c9945492SAndroid Build Coastguard Worker search_vec(p->dynv, &flags1, DT_FLAGS_1);
2138*c9945492SAndroid Build Coastguard Worker if (dyn[DT_BIND_NOW] || (dyn[DT_FLAGS] & DF_BIND_NOW) || (flags1 & DF_1_NOW))
2139*c9945492SAndroid Build Coastguard Worker return;
2140*c9945492SAndroid Build Coastguard Worker n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + 1;
2141*c9945492SAndroid Build Coastguard Worker if (NEED_MIPS_GOT_RELOCS) {
2142*c9945492SAndroid Build Coastguard Worker size_t j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
2143*c9945492SAndroid Build Coastguard Worker size_t i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
2144*c9945492SAndroid Build Coastguard Worker n += i-j;
2145*c9945492SAndroid Build Coastguard Worker }
2146*c9945492SAndroid Build Coastguard Worker p->lazy = calloc(n, 3*sizeof(size_t));
2147*c9945492SAndroid Build Coastguard Worker if (!p->lazy) {
2148*c9945492SAndroid Build Coastguard Worker error("Error preparing lazy relocation for %s: %m", p->name);
2149*c9945492SAndroid Build Coastguard Worker longjmp(*rtld_fail, 1);
2150*c9945492SAndroid Build Coastguard Worker }
2151*c9945492SAndroid Build Coastguard Worker p->lazy_next = lazy_head;
2152*c9945492SAndroid Build Coastguard Worker lazy_head = p;
2153*c9945492SAndroid Build Coastguard Worker }
2154*c9945492SAndroid Build Coastguard Worker
dlopen(const char * file,int mode)2155*c9945492SAndroid Build Coastguard Worker void *dlopen(const char *file, int mode)
2156*c9945492SAndroid Build Coastguard Worker {
2157*c9945492SAndroid Build Coastguard Worker struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next;
2158*c9945492SAndroid Build Coastguard Worker struct tls_module *orig_tls_tail;
2159*c9945492SAndroid Build Coastguard Worker size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
2160*c9945492SAndroid Build Coastguard Worker size_t i;
2161*c9945492SAndroid Build Coastguard Worker int cs;
2162*c9945492SAndroid Build Coastguard Worker jmp_buf jb;
2163*c9945492SAndroid Build Coastguard Worker struct dso **volatile ctor_queue = 0;
2164*c9945492SAndroid Build Coastguard Worker
2165*c9945492SAndroid Build Coastguard Worker if (!file) return head;
2166*c9945492SAndroid Build Coastguard Worker
2167*c9945492SAndroid Build Coastguard Worker pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
2168*c9945492SAndroid Build Coastguard Worker pthread_rwlock_wrlock(&lock);
2169*c9945492SAndroid Build Coastguard Worker __inhibit_ptc();
2170*c9945492SAndroid Build Coastguard Worker
2171*c9945492SAndroid Build Coastguard Worker debug.state = RT_ADD;
2172*c9945492SAndroid Build Coastguard Worker _dl_debug_state();
2173*c9945492SAndroid Build Coastguard Worker
2174*c9945492SAndroid Build Coastguard Worker p = 0;
2175*c9945492SAndroid Build Coastguard Worker if (shutting_down) {
2176*c9945492SAndroid Build Coastguard Worker error("Cannot dlopen while program is exiting.");
2177*c9945492SAndroid Build Coastguard Worker goto end;
2178*c9945492SAndroid Build Coastguard Worker }
2179*c9945492SAndroid Build Coastguard Worker orig_tls_tail = tls_tail;
2180*c9945492SAndroid Build Coastguard Worker orig_tls_cnt = tls_cnt;
2181*c9945492SAndroid Build Coastguard Worker orig_tls_offset = tls_offset;
2182*c9945492SAndroid Build Coastguard Worker orig_tls_align = tls_align;
2183*c9945492SAndroid Build Coastguard Worker orig_lazy_head = lazy_head;
2184*c9945492SAndroid Build Coastguard Worker orig_syms_tail = syms_tail;
2185*c9945492SAndroid Build Coastguard Worker orig_tail = tail;
2186*c9945492SAndroid Build Coastguard Worker noload = mode & RTLD_NOLOAD;
2187*c9945492SAndroid Build Coastguard Worker
2188*c9945492SAndroid Build Coastguard Worker rtld_fail = &jb;
2189*c9945492SAndroid Build Coastguard Worker if (setjmp(*rtld_fail)) {
2190*c9945492SAndroid Build Coastguard Worker /* Clean up anything new that was (partially) loaded */
2191*c9945492SAndroid Build Coastguard Worker revert_syms(orig_syms_tail);
2192*c9945492SAndroid Build Coastguard Worker for (p=orig_tail->next; p; p=next) {
2193*c9945492SAndroid Build Coastguard Worker next = p->next;
2194*c9945492SAndroid Build Coastguard Worker while (p->td_index) {
2195*c9945492SAndroid Build Coastguard Worker void *tmp = p->td_index->next;
2196*c9945492SAndroid Build Coastguard Worker free(p->td_index);
2197*c9945492SAndroid Build Coastguard Worker p->td_index = tmp;
2198*c9945492SAndroid Build Coastguard Worker }
2199*c9945492SAndroid Build Coastguard Worker free(p->funcdescs);
2200*c9945492SAndroid Build Coastguard Worker if (p->rpath != p->rpath_orig)
2201*c9945492SAndroid Build Coastguard Worker free(p->rpath);
2202*c9945492SAndroid Build Coastguard Worker free(p->deps);
2203*c9945492SAndroid Build Coastguard Worker unmap_library(p);
2204*c9945492SAndroid Build Coastguard Worker free(p);
2205*c9945492SAndroid Build Coastguard Worker }
2206*c9945492SAndroid Build Coastguard Worker free(ctor_queue);
2207*c9945492SAndroid Build Coastguard Worker ctor_queue = 0;
2208*c9945492SAndroid Build Coastguard Worker if (!orig_tls_tail) libc.tls_head = 0;
2209*c9945492SAndroid Build Coastguard Worker tls_tail = orig_tls_tail;
2210*c9945492SAndroid Build Coastguard Worker if (tls_tail) tls_tail->next = 0;
2211*c9945492SAndroid Build Coastguard Worker tls_cnt = orig_tls_cnt;
2212*c9945492SAndroid Build Coastguard Worker tls_offset = orig_tls_offset;
2213*c9945492SAndroid Build Coastguard Worker tls_align = orig_tls_align;
2214*c9945492SAndroid Build Coastguard Worker lazy_head = orig_lazy_head;
2215*c9945492SAndroid Build Coastguard Worker tail = orig_tail;
2216*c9945492SAndroid Build Coastguard Worker tail->next = 0;
2217*c9945492SAndroid Build Coastguard Worker p = 0;
2218*c9945492SAndroid Build Coastguard Worker goto end;
2219*c9945492SAndroid Build Coastguard Worker } else p = load_library(file, head);
2220*c9945492SAndroid Build Coastguard Worker
2221*c9945492SAndroid Build Coastguard Worker if (!p) {
2222*c9945492SAndroid Build Coastguard Worker error(noload ?
2223*c9945492SAndroid Build Coastguard Worker "Library %s is not already loaded" :
2224*c9945492SAndroid Build Coastguard Worker "Error loading shared library %s: %m",
2225*c9945492SAndroid Build Coastguard Worker file);
2226*c9945492SAndroid Build Coastguard Worker goto end;
2227*c9945492SAndroid Build Coastguard Worker }
2228*c9945492SAndroid Build Coastguard Worker
2229*c9945492SAndroid Build Coastguard Worker /* First load handling */
2230*c9945492SAndroid Build Coastguard Worker load_deps(p);
2231*c9945492SAndroid Build Coastguard Worker extend_bfs_deps(p);
2232*c9945492SAndroid Build Coastguard Worker pthread_mutex_lock(&init_fini_lock);
2233*c9945492SAndroid Build Coastguard Worker int constructed = p->constructed;
2234*c9945492SAndroid Build Coastguard Worker pthread_mutex_unlock(&init_fini_lock);
2235*c9945492SAndroid Build Coastguard Worker if (!constructed) ctor_queue = queue_ctors(p);
2236*c9945492SAndroid Build Coastguard Worker if (!p->relocated && (mode & RTLD_LAZY)) {
2237*c9945492SAndroid Build Coastguard Worker prepare_lazy(p);
2238*c9945492SAndroid Build Coastguard Worker for (i=0; p->deps[i]; i++)
2239*c9945492SAndroid Build Coastguard Worker if (!p->deps[i]->relocated)
2240*c9945492SAndroid Build Coastguard Worker prepare_lazy(p->deps[i]);
2241*c9945492SAndroid Build Coastguard Worker }
2242*c9945492SAndroid Build Coastguard Worker if (!p->relocated || (mode & RTLD_GLOBAL)) {
2243*c9945492SAndroid Build Coastguard Worker /* Make new symbols global, at least temporarily, so we can do
2244*c9945492SAndroid Build Coastguard Worker * relocations. If not RTLD_GLOBAL, this is reverted below. */
2245*c9945492SAndroid Build Coastguard Worker add_syms(p);
2246*c9945492SAndroid Build Coastguard Worker for (i=0; p->deps[i]; i++)
2247*c9945492SAndroid Build Coastguard Worker add_syms(p->deps[i]);
2248*c9945492SAndroid Build Coastguard Worker }
2249*c9945492SAndroid Build Coastguard Worker if (!p->relocated) {
2250*c9945492SAndroid Build Coastguard Worker reloc_all(p);
2251*c9945492SAndroid Build Coastguard Worker }
2252*c9945492SAndroid Build Coastguard Worker
2253*c9945492SAndroid Build Coastguard Worker /* If RTLD_GLOBAL was not specified, undo any new additions
2254*c9945492SAndroid Build Coastguard Worker * to the global symbol table. This is a nop if the library was
2255*c9945492SAndroid Build Coastguard Worker * previously loaded and already global. */
2256*c9945492SAndroid Build Coastguard Worker if (!(mode & RTLD_GLOBAL))
2257*c9945492SAndroid Build Coastguard Worker revert_syms(orig_syms_tail);
2258*c9945492SAndroid Build Coastguard Worker
2259*c9945492SAndroid Build Coastguard Worker /* Processing of deferred lazy relocations must not happen until
2260*c9945492SAndroid Build Coastguard Worker * the new libraries are committed; otherwise we could end up with
2261*c9945492SAndroid Build Coastguard Worker * relocations resolved to symbol definitions that get removed. */
2262*c9945492SAndroid Build Coastguard Worker redo_lazy_relocs();
2263*c9945492SAndroid Build Coastguard Worker
2264*c9945492SAndroid Build Coastguard Worker update_tls_size();
2265*c9945492SAndroid Build Coastguard Worker if (tls_cnt != orig_tls_cnt)
2266*c9945492SAndroid Build Coastguard Worker install_new_tls();
2267*c9945492SAndroid Build Coastguard Worker orig_tail = tail;
2268*c9945492SAndroid Build Coastguard Worker end:
2269*c9945492SAndroid Build Coastguard Worker debug.state = RT_CONSISTENT;
2270*c9945492SAndroid Build Coastguard Worker _dl_debug_state();
2271*c9945492SAndroid Build Coastguard Worker __release_ptc();
2272*c9945492SAndroid Build Coastguard Worker if (p) gencnt++;
2273*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
2274*c9945492SAndroid Build Coastguard Worker if (ctor_queue) {
2275*c9945492SAndroid Build Coastguard Worker do_init_fini(ctor_queue);
2276*c9945492SAndroid Build Coastguard Worker free(ctor_queue);
2277*c9945492SAndroid Build Coastguard Worker }
2278*c9945492SAndroid Build Coastguard Worker pthread_setcancelstate(cs, 0);
2279*c9945492SAndroid Build Coastguard Worker return p;
2280*c9945492SAndroid Build Coastguard Worker }
2281*c9945492SAndroid Build Coastguard Worker
__dl_invalid_handle(void * h)2282*c9945492SAndroid Build Coastguard Worker hidden int __dl_invalid_handle(void *h)
2283*c9945492SAndroid Build Coastguard Worker {
2284*c9945492SAndroid Build Coastguard Worker struct dso *p;
2285*c9945492SAndroid Build Coastguard Worker for (p=head; p; p=p->next) if (h==p) return 0;
2286*c9945492SAndroid Build Coastguard Worker error("Invalid library handle %p", (void *)h);
2287*c9945492SAndroid Build Coastguard Worker return 1;
2288*c9945492SAndroid Build Coastguard Worker }
2289*c9945492SAndroid Build Coastguard Worker
addr2dso(size_t a)2290*c9945492SAndroid Build Coastguard Worker static void *addr2dso(size_t a)
2291*c9945492SAndroid Build Coastguard Worker {
2292*c9945492SAndroid Build Coastguard Worker struct dso *p;
2293*c9945492SAndroid Build Coastguard Worker size_t i;
2294*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) for (p=head; p; p=p->next) {
2295*c9945492SAndroid Build Coastguard Worker i = count_syms(p);
2296*c9945492SAndroid Build Coastguard Worker if (a-(size_t)p->funcdescs < i*sizeof(*p->funcdescs))
2297*c9945492SAndroid Build Coastguard Worker return p;
2298*c9945492SAndroid Build Coastguard Worker }
2299*c9945492SAndroid Build Coastguard Worker for (p=head; p; p=p->next) {
2300*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC && p->loadmap) {
2301*c9945492SAndroid Build Coastguard Worker for (i=0; i<p->loadmap->nsegs; i++) {
2302*c9945492SAndroid Build Coastguard Worker if (a-p->loadmap->segs[i].p_vaddr
2303*c9945492SAndroid Build Coastguard Worker < p->loadmap->segs[i].p_memsz)
2304*c9945492SAndroid Build Coastguard Worker return p;
2305*c9945492SAndroid Build Coastguard Worker }
2306*c9945492SAndroid Build Coastguard Worker } else {
2307*c9945492SAndroid Build Coastguard Worker Phdr *ph = p->phdr;
2308*c9945492SAndroid Build Coastguard Worker size_t phcnt = p->phnum;
2309*c9945492SAndroid Build Coastguard Worker size_t entsz = p->phentsize;
2310*c9945492SAndroid Build Coastguard Worker size_t base = (size_t)p->base;
2311*c9945492SAndroid Build Coastguard Worker for (; phcnt--; ph=(void *)((char *)ph+entsz)) {
2312*c9945492SAndroid Build Coastguard Worker if (ph->p_type != PT_LOAD) continue;
2313*c9945492SAndroid Build Coastguard Worker if (a-base-ph->p_vaddr < ph->p_memsz)
2314*c9945492SAndroid Build Coastguard Worker return p;
2315*c9945492SAndroid Build Coastguard Worker }
2316*c9945492SAndroid Build Coastguard Worker if (a-(size_t)p->map < p->map_len)
2317*c9945492SAndroid Build Coastguard Worker return 0;
2318*c9945492SAndroid Build Coastguard Worker }
2319*c9945492SAndroid Build Coastguard Worker }
2320*c9945492SAndroid Build Coastguard Worker return 0;
2321*c9945492SAndroid Build Coastguard Worker }
2322*c9945492SAndroid Build Coastguard Worker
do_dlsym(struct dso * p,const char * s,void * ra)2323*c9945492SAndroid Build Coastguard Worker static void *do_dlsym(struct dso *p, const char *s, void *ra)
2324*c9945492SAndroid Build Coastguard Worker {
2325*c9945492SAndroid Build Coastguard Worker int use_deps = 0;
2326*c9945492SAndroid Build Coastguard Worker if (p == head || p == RTLD_DEFAULT) {
2327*c9945492SAndroid Build Coastguard Worker p = head;
2328*c9945492SAndroid Build Coastguard Worker } else if (p == RTLD_NEXT) {
2329*c9945492SAndroid Build Coastguard Worker p = addr2dso((size_t)ra);
2330*c9945492SAndroid Build Coastguard Worker if (!p) p=head;
2331*c9945492SAndroid Build Coastguard Worker p = p->next;
2332*c9945492SAndroid Build Coastguard Worker } else if (__dl_invalid_handle(p)) {
2333*c9945492SAndroid Build Coastguard Worker return 0;
2334*c9945492SAndroid Build Coastguard Worker } else
2335*c9945492SAndroid Build Coastguard Worker use_deps = 1;
2336*c9945492SAndroid Build Coastguard Worker struct symdef def = find_sym2(p, s, 0, use_deps);
2337*c9945492SAndroid Build Coastguard Worker if (!def.sym) {
2338*c9945492SAndroid Build Coastguard Worker error("Symbol not found: %s", s);
2339*c9945492SAndroid Build Coastguard Worker return 0;
2340*c9945492SAndroid Build Coastguard Worker }
2341*c9945492SAndroid Build Coastguard Worker if ((def.sym->st_info&0xf) == STT_TLS)
2342*c9945492SAndroid Build Coastguard Worker return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value-DTP_OFFSET});
2343*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC)
2344*c9945492SAndroid Build Coastguard Worker return def.dso->funcdescs + (def.sym - def.dso->syms);
2345*c9945492SAndroid Build Coastguard Worker return laddr(def.dso, def.sym->st_value);
2346*c9945492SAndroid Build Coastguard Worker }
2347*c9945492SAndroid Build Coastguard Worker
dladdr(const void * addr_arg,Dl_info * info)2348*c9945492SAndroid Build Coastguard Worker int dladdr(const void *addr_arg, Dl_info *info)
2349*c9945492SAndroid Build Coastguard Worker {
2350*c9945492SAndroid Build Coastguard Worker size_t addr = (size_t)addr_arg;
2351*c9945492SAndroid Build Coastguard Worker struct dso *p;
2352*c9945492SAndroid Build Coastguard Worker Sym *sym, *bestsym;
2353*c9945492SAndroid Build Coastguard Worker uint32_t nsym;
2354*c9945492SAndroid Build Coastguard Worker char *strings;
2355*c9945492SAndroid Build Coastguard Worker size_t best = 0;
2356*c9945492SAndroid Build Coastguard Worker size_t besterr = -1;
2357*c9945492SAndroid Build Coastguard Worker
2358*c9945492SAndroid Build Coastguard Worker pthread_rwlock_rdlock(&lock);
2359*c9945492SAndroid Build Coastguard Worker p = addr2dso(addr);
2360*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
2361*c9945492SAndroid Build Coastguard Worker
2362*c9945492SAndroid Build Coastguard Worker if (!p) return 0;
2363*c9945492SAndroid Build Coastguard Worker
2364*c9945492SAndroid Build Coastguard Worker sym = p->syms;
2365*c9945492SAndroid Build Coastguard Worker strings = p->strings;
2366*c9945492SAndroid Build Coastguard Worker nsym = count_syms(p);
2367*c9945492SAndroid Build Coastguard Worker
2368*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC) {
2369*c9945492SAndroid Build Coastguard Worker size_t idx = (addr-(size_t)p->funcdescs)
2370*c9945492SAndroid Build Coastguard Worker / sizeof(*p->funcdescs);
2371*c9945492SAndroid Build Coastguard Worker if (idx < nsym && (sym[idx].st_info&0xf) == STT_FUNC) {
2372*c9945492SAndroid Build Coastguard Worker best = (size_t)(p->funcdescs + idx);
2373*c9945492SAndroid Build Coastguard Worker bestsym = sym + idx;
2374*c9945492SAndroid Build Coastguard Worker besterr = 0;
2375*c9945492SAndroid Build Coastguard Worker }
2376*c9945492SAndroid Build Coastguard Worker }
2377*c9945492SAndroid Build Coastguard Worker
2378*c9945492SAndroid Build Coastguard Worker if (!best) for (; nsym; nsym--, sym++) {
2379*c9945492SAndroid Build Coastguard Worker if (sym->st_value
2380*c9945492SAndroid Build Coastguard Worker && (1<<(sym->st_info&0xf) & OK_TYPES)
2381*c9945492SAndroid Build Coastguard Worker && (1<<(sym->st_info>>4) & OK_BINDS)) {
2382*c9945492SAndroid Build Coastguard Worker size_t symaddr = (size_t)laddr(p, sym->st_value);
2383*c9945492SAndroid Build Coastguard Worker if (symaddr > addr || symaddr <= best)
2384*c9945492SAndroid Build Coastguard Worker continue;
2385*c9945492SAndroid Build Coastguard Worker best = symaddr;
2386*c9945492SAndroid Build Coastguard Worker bestsym = sym;
2387*c9945492SAndroid Build Coastguard Worker besterr = addr - symaddr;
2388*c9945492SAndroid Build Coastguard Worker if (addr == symaddr)
2389*c9945492SAndroid Build Coastguard Worker break;
2390*c9945492SAndroid Build Coastguard Worker }
2391*c9945492SAndroid Build Coastguard Worker }
2392*c9945492SAndroid Build Coastguard Worker
2393*c9945492SAndroid Build Coastguard Worker if (best && besterr > bestsym->st_size-1) {
2394*c9945492SAndroid Build Coastguard Worker best = 0;
2395*c9945492SAndroid Build Coastguard Worker bestsym = 0;
2396*c9945492SAndroid Build Coastguard Worker }
2397*c9945492SAndroid Build Coastguard Worker
2398*c9945492SAndroid Build Coastguard Worker info->dli_fname = p->name;
2399*c9945492SAndroid Build Coastguard Worker info->dli_fbase = p->map;
2400*c9945492SAndroid Build Coastguard Worker
2401*c9945492SAndroid Build Coastguard Worker if (!best) {
2402*c9945492SAndroid Build Coastguard Worker info->dli_sname = 0;
2403*c9945492SAndroid Build Coastguard Worker info->dli_saddr = 0;
2404*c9945492SAndroid Build Coastguard Worker return 1;
2405*c9945492SAndroid Build Coastguard Worker }
2406*c9945492SAndroid Build Coastguard Worker
2407*c9945492SAndroid Build Coastguard Worker if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
2408*c9945492SAndroid Build Coastguard Worker best = (size_t)(p->funcdescs + (bestsym - p->syms));
2409*c9945492SAndroid Build Coastguard Worker info->dli_sname = strings + bestsym->st_name;
2410*c9945492SAndroid Build Coastguard Worker info->dli_saddr = (void *)best;
2411*c9945492SAndroid Build Coastguard Worker
2412*c9945492SAndroid Build Coastguard Worker return 1;
2413*c9945492SAndroid Build Coastguard Worker }
2414*c9945492SAndroid Build Coastguard Worker
__dlsym(void * restrict p,const char * restrict s,void * restrict ra)2415*c9945492SAndroid Build Coastguard Worker hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
2416*c9945492SAndroid Build Coastguard Worker {
2417*c9945492SAndroid Build Coastguard Worker void *res;
2418*c9945492SAndroid Build Coastguard Worker pthread_rwlock_rdlock(&lock);
2419*c9945492SAndroid Build Coastguard Worker res = do_dlsym(p, s, ra);
2420*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
2421*c9945492SAndroid Build Coastguard Worker return res;
2422*c9945492SAndroid Build Coastguard Worker }
2423*c9945492SAndroid Build Coastguard Worker
__dlsym_redir_time64(void * restrict p,const char * restrict s,void * restrict ra)2424*c9945492SAndroid Build Coastguard Worker hidden void *__dlsym_redir_time64(void *restrict p, const char *restrict s, void *restrict ra)
2425*c9945492SAndroid Build Coastguard Worker {
2426*c9945492SAndroid Build Coastguard Worker #if _REDIR_TIME64
2427*c9945492SAndroid Build Coastguard Worker const char *suffix, *suffix2 = "";
2428*c9945492SAndroid Build Coastguard Worker char redir[36];
2429*c9945492SAndroid Build Coastguard Worker
2430*c9945492SAndroid Build Coastguard Worker /* Map the symbol name to a time64 version of itself according to the
2431*c9945492SAndroid Build Coastguard Worker * pattern used for naming the redirected time64 symbols. */
2432*c9945492SAndroid Build Coastguard Worker size_t l = strnlen(s, sizeof redir);
2433*c9945492SAndroid Build Coastguard Worker if (l<4 || l==sizeof redir) goto no_redir;
2434*c9945492SAndroid Build Coastguard Worker if (s[l-2]=='_' && s[l-1]=='r') {
2435*c9945492SAndroid Build Coastguard Worker l -= 2;
2436*c9945492SAndroid Build Coastguard Worker suffix2 = s+l;
2437*c9945492SAndroid Build Coastguard Worker }
2438*c9945492SAndroid Build Coastguard Worker if (l<4) goto no_redir;
2439*c9945492SAndroid Build Coastguard Worker if (!strcmp(s+l-4, "time")) suffix = "64";
2440*c9945492SAndroid Build Coastguard Worker else suffix = "_time64";
2441*c9945492SAndroid Build Coastguard Worker
2442*c9945492SAndroid Build Coastguard Worker /* Use the presence of the remapped symbol name in libc to determine
2443*c9945492SAndroid Build Coastguard Worker * whether it's one that requires time64 redirection; replace if so. */
2444*c9945492SAndroid Build Coastguard Worker snprintf(redir, sizeof redir, "__%.*s%s%s", (int)l, s, suffix, suffix2);
2445*c9945492SAndroid Build Coastguard Worker if (find_sym(&ldso, redir, 1).sym) s = redir;
2446*c9945492SAndroid Build Coastguard Worker no_redir:
2447*c9945492SAndroid Build Coastguard Worker #endif
2448*c9945492SAndroid Build Coastguard Worker return __dlsym(p, s, ra);
2449*c9945492SAndroid Build Coastguard Worker }
2450*c9945492SAndroid Build Coastguard Worker
dl_iterate_phdr(int (* callback)(struct dl_phdr_info * info,size_t size,void * data),void * data)2451*c9945492SAndroid Build Coastguard Worker int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
2452*c9945492SAndroid Build Coastguard Worker {
2453*c9945492SAndroid Build Coastguard Worker struct dso *current;
2454*c9945492SAndroid Build Coastguard Worker struct dl_phdr_info info;
2455*c9945492SAndroid Build Coastguard Worker int ret = 0;
2456*c9945492SAndroid Build Coastguard Worker for(current = head; current;) {
2457*c9945492SAndroid Build Coastguard Worker info.dlpi_addr = (uintptr_t)current->base;
2458*c9945492SAndroid Build Coastguard Worker info.dlpi_name = current->name;
2459*c9945492SAndroid Build Coastguard Worker info.dlpi_phdr = current->phdr;
2460*c9945492SAndroid Build Coastguard Worker info.dlpi_phnum = current->phnum;
2461*c9945492SAndroid Build Coastguard Worker info.dlpi_adds = gencnt;
2462*c9945492SAndroid Build Coastguard Worker info.dlpi_subs = 0;
2463*c9945492SAndroid Build Coastguard Worker info.dlpi_tls_modid = current->tls_id;
2464*c9945492SAndroid Build Coastguard Worker info.dlpi_tls_data = !current->tls_id ? 0 :
2465*c9945492SAndroid Build Coastguard Worker __tls_get_addr((tls_mod_off_t[]){current->tls_id,0});
2466*c9945492SAndroid Build Coastguard Worker
2467*c9945492SAndroid Build Coastguard Worker ret = (callback)(&info, sizeof (info), data);
2468*c9945492SAndroid Build Coastguard Worker
2469*c9945492SAndroid Build Coastguard Worker if (ret != 0) break;
2470*c9945492SAndroid Build Coastguard Worker
2471*c9945492SAndroid Build Coastguard Worker pthread_rwlock_rdlock(&lock);
2472*c9945492SAndroid Build Coastguard Worker current = current->next;
2473*c9945492SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock);
2474*c9945492SAndroid Build Coastguard Worker }
2475*c9945492SAndroid Build Coastguard Worker return ret;
2476*c9945492SAndroid Build Coastguard Worker }
2477*c9945492SAndroid Build Coastguard Worker
error_impl(const char * fmt,...)2478*c9945492SAndroid Build Coastguard Worker static void error_impl(const char *fmt, ...)
2479*c9945492SAndroid Build Coastguard Worker {
2480*c9945492SAndroid Build Coastguard Worker va_list ap;
2481*c9945492SAndroid Build Coastguard Worker va_start(ap, fmt);
2482*c9945492SAndroid Build Coastguard Worker if (!runtime) {
2483*c9945492SAndroid Build Coastguard Worker vdprintf(2, fmt, ap);
2484*c9945492SAndroid Build Coastguard Worker dprintf(2, "\n");
2485*c9945492SAndroid Build Coastguard Worker ldso_fail = 1;
2486*c9945492SAndroid Build Coastguard Worker va_end(ap);
2487*c9945492SAndroid Build Coastguard Worker return;
2488*c9945492SAndroid Build Coastguard Worker }
2489*c9945492SAndroid Build Coastguard Worker __dl_vseterr(fmt, ap);
2490*c9945492SAndroid Build Coastguard Worker va_end(ap);
2491*c9945492SAndroid Build Coastguard Worker }
2492*c9945492SAndroid Build Coastguard Worker
error_noop(const char * fmt,...)2493*c9945492SAndroid Build Coastguard Worker static void error_noop(const char *fmt, ...)
2494*c9945492SAndroid Build Coastguard Worker {
2495*c9945492SAndroid Build Coastguard Worker }
2496