Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | /* |
2 | * Copyright (C) 2008, 2009 The Android Open Source Project | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * * Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * * Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in | |
12 | * the documentation and/or other materials provided with the | |
13 | * distribution. | |
14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 | * SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #include <linux/auxvec.h> | |
30 | ||
31 | #include <stdio.h> | |
32 | #include <stdlib.h> | |
33 | #include <string.h> | |
34 | #include <unistd.h> | |
35 | #include <fcntl.h> | |
36 | #include <errno.h> | |
37 | #include <dlfcn.h> | |
38 | #include <sys/stat.h> | |
39 | ||
40 | #include <pthread.h> | |
41 | ||
42 | #include <sys/mman.h> | |
43 | ||
44 | /* special private C library header - see Android.mk */ | |
45 | #include "bionic_tls.h" | |
46 | ||
47 | #include "linker.h" | |
48 | #include "linker_debug.h" | |
49 | #include "linker_environ.h" | |
50 | #include "linker_format.h" | |
51 | ||
52 | #define ALLOW_SYMBOLS_FROM_MAIN 1 | |
53 | #define SO_MAX 128 | |
54 | ||
55 | /* Assume average path length of 64 and max 8 paths */ | |
56 | #define LDPATH_BUFSIZE 512 | |
57 | #define LDPATH_MAX 8 | |
58 | ||
59 | #define LDPRELOAD_BUFSIZE 512 | |
60 | #define LDPRELOAD_MAX 8 | |
61 | ||
62 | /* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<< | |
63 | * | |
64 | * Do NOT use malloc() and friends or pthread_*() code here. | |
65 | * Don't use printf() either; it's caused mysterious memory | |
66 | * corruption in the past. | |
67 | * The linker runs before we bring up libc and it's easiest | |
68 | * to make sure it does not depend on any complex libc features | |
69 | * | |
70 | * open issues / todo: | |
71 | * | |
72 | * - are we doing everything we should for ARM_COPY relocations? | |
73 | * - cleaner error reporting | |
74 | * - after linking, set as much stuff as possible to READONLY | |
75 | * and NOEXEC | |
76 | * - linker hardcodes PAGE_SIZE and PAGE_MASK because the kernel | |
77 | * headers provide versions that are negative... | |
78 | * - allocate space for soinfo structs dynamically instead of | |
79 | * having a hard limit (64) | |
80 | */ | |
81 | ||
82 | ||
83 | static int link_image(soinfo *si, unsigned wr_offset); | |
84 | ||
85 | static int socount = 0; | |
86 | static soinfo sopool[SO_MAX]; | |
87 | static soinfo *freelist = NULL; | |
88 | static soinfo *solist = &libdl_info; | |
89 | static soinfo *sonext = &libdl_info; | |
90 | #if ALLOW_SYMBOLS_FROM_MAIN | |
91 | static soinfo *somain; /* main process, always the one after libdl_info */ | |
92 | #endif | |
93 | ||
94 | ||
95 | static inline int validate_soinfo(soinfo *si) | |
96 | { | |
97 | return (si >= sopool && si < sopool + SO_MAX) || | |
98 | si == &libdl_info; | |
99 | } | |
100 | ||
101 | static char ldpaths_buf[LDPATH_BUFSIZE]; | |
102 | static const char *ldpaths[LDPATH_MAX + 1]; | |
103 | ||
104 | static char ldpreloads_buf[LDPRELOAD_BUFSIZE]; | |
105 | static const char *ldpreload_names[LDPRELOAD_MAX + 1]; | |
106 | ||
107 | static soinfo *preloads[LDPRELOAD_MAX + 1]; | |
108 | ||
109 | #if LINKER_DEBUG | |
110 | int debug_verbosity; | |
111 | #endif | |
112 | ||
113 | static int pid; | |
114 | ||
115 | /* This boolean is set if the program being loaded is setuid */ | |
116 | static int program_is_setuid; | |
117 | ||
118 | #if STATS | |
119 | struct _link_stats linker_stats; | |
120 | #endif | |
121 | ||
122 | #if COUNT_PAGES | |
123 | unsigned bitmask[4096]; | |
124 | #endif | |
125 | ||
126 | #ifndef PT_ARM_EXIDX | |
127 | #define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ | |
128 | #endif | |
129 | ||
130 | static char tmp_err_buf[768]; | |
131 | static char __linker_dl_err_buf[768]; | |
132 | #define DL_ERR(fmt, x...) \ | |
133 | do { \ | |
134 | format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \ | |
135 | "%s[%d]: " fmt, __func__, __LINE__, ##x); \ | |
136 | ERROR(fmt "\n", ##x); \ | |
137 | } while(0) | |
138 | ||
139 | const char *linker_get_error(void) | |
140 | { | |
141 | return (const char *)&__linker_dl_err_buf[0]; | |
142 | } | |
143 | ||
144 | /* | |
145 | * This function is an empty stub where GDB locates a breakpoint to get notified | |
146 | * about linker activity. | |
147 | */ | |
148 | extern void __attribute__((noinline)) rtld_db_dlactivity(void); | |
149 | ||
150 | static struct r_debug _r_debug = {1, NULL, &rtld_db_dlactivity, | |
151 | RT_CONSISTENT, 0}; | |
152 | static struct link_map *r_debug_tail = 0; | |
153 | ||
154 | static pthread_mutex_t _r_debug_lock = PTHREAD_MUTEX_INITIALIZER; | |
155 | ||
156 | static void insert_soinfo_into_debug_map(soinfo * info) | |
157 | { | |
158 | struct link_map * map; | |
159 | ||
160 | /* Copy the necessary fields into the debug structure. | |
161 | */ | |
162 | map = &(info->linkmap); | |
163 | map->l_addr = info->base; | |
164 | map->l_name = (char*) info->name; | |
165 | map->l_ld = (uintptr_t)info->dynamic; | |
166 | ||
167 | /* Stick the new library at the end of the list. | |
168 | * gdb tends to care more about libc than it does | |
169 | * about leaf libraries, and ordering it this way | |
170 | * reduces the back-and-forth over the wire. | |
171 | */ | |
172 | if (r_debug_tail) { | |
173 | r_debug_tail->l_next = map; | |
174 | map->l_prev = r_debug_tail; | |
175 | map->l_next = 0; | |
176 | } else { | |
177 | _r_debug.r_map = map; | |
178 | map->l_prev = 0; | |
179 | map->l_next = 0; | |
180 | } | |
181 | r_debug_tail = map; | |
182 | } | |
183 | ||
184 | static void remove_soinfo_from_debug_map(soinfo * info) | |
185 | { | |
186 | struct link_map * map = &(info->linkmap); | |
187 | ||
188 | if (r_debug_tail == map) | |
189 | r_debug_tail = map->l_prev; | |
190 | ||
191 | if (map->l_prev) map->l_prev->l_next = map->l_next; | |
192 | if (map->l_next) map->l_next->l_prev = map->l_prev; | |
193 | } | |
194 | ||
195 | void notify_gdb_of_load(soinfo * info) | |
196 | { | |
197 | if (info->flags & FLAG_EXE) { | |
198 | // GDB already knows about the main executable | |
199 | return; | |
200 | } | |
201 | ||
202 | pthread_mutex_lock(&_r_debug_lock); | |
203 | ||
204 | _r_debug.r_state = RT_ADD; | |
205 | rtld_db_dlactivity(); | |
206 | ||
207 | insert_soinfo_into_debug_map(info); | |
208 | ||
209 | _r_debug.r_state = RT_CONSISTENT; | |
210 | rtld_db_dlactivity(); | |
211 | ||
212 | pthread_mutex_unlock(&_r_debug_lock); | |
213 | } | |
214 | ||
215 | void notify_gdb_of_unload(soinfo * info) | |
216 | { | |
217 | if (info->flags & FLAG_EXE) { | |
218 | // GDB already knows about the main executable | |
219 | return; | |
220 | } | |
221 | ||
222 | pthread_mutex_lock(&_r_debug_lock); | |
223 | ||
224 | _r_debug.r_state = RT_DELETE; | |
225 | rtld_db_dlactivity(); | |
226 | ||
227 | remove_soinfo_from_debug_map(info); | |
228 | ||
229 | _r_debug.r_state = RT_CONSISTENT; | |
230 | rtld_db_dlactivity(); | |
231 | ||
232 | pthread_mutex_unlock(&_r_debug_lock); | |
233 | } | |
234 | ||
235 | void notify_gdb_of_libraries() | |
236 | { | |
237 | _r_debug.r_state = RT_ADD; | |
238 | rtld_db_dlactivity(); | |
239 | _r_debug.r_state = RT_CONSISTENT; | |
240 | rtld_db_dlactivity(); | |
241 | } | |
242 | ||
243 | static soinfo *alloc_info(const char *name) | |
244 | { | |
245 | soinfo *si; | |
246 | ||
247 | if(strlen(name) >= SOINFO_NAME_LEN) { | |
248 | DL_ERR("%5d library name %s too long", pid, name); | |
249 | return NULL; | |
250 | } | |
251 | ||
252 | /* The freelist is populated when we call free_info(), which in turn is | |
253 | done only by dlclose(), which is not likely to be used. | |
254 | */ | |
255 | if (!freelist) { | |
256 | if(socount == SO_MAX) { | |
257 | DL_ERR("%5d too many libraries when loading %s", pid, name); | |
258 | return NULL; | |
259 | } | |
260 | freelist = sopool + socount++; | |
261 | freelist->next = NULL; | |
262 | } | |
263 | ||
264 | si = freelist; | |
265 | freelist = freelist->next; | |
266 | ||
267 | /* Make sure we get a clean block of soinfo */ | |
268 | memset(si, 0, sizeof(soinfo)); | |
269 | strlcpy((char*) si->name, name, sizeof(si->name)); | |
270 | sonext->next = si; | |
271 | si->next = NULL; | |
272 | si->refcount = 0; | |
273 | sonext = si; | |
274 | ||
275 | TRACE("%5d name %s: allocated soinfo @ %p\n", pid, name, si); | |
276 | return si; | |
277 | } | |
278 | ||
279 | static void free_info(soinfo *si) | |
280 | { | |
281 | soinfo *prev = NULL, *trav; | |
282 | ||
283 | TRACE("%5d name %s: freeing soinfo @ %p\n", pid, si->name, si); | |
284 | ||
285 | for(trav = solist; trav != NULL; trav = trav->next){ | |
286 | if (trav == si) | |
287 | break; | |
288 | prev = trav; | |
289 | } | |
290 | if (trav == NULL) { | |
291 | /* si was not ni solist */ | |
292 | DL_ERR("%5d name %s is not in solist!", pid, si->name); | |
293 | return; | |
294 | } | |
295 | ||
296 | /* prev will never be NULL, because the first entry in solist is | |
297 | always the static libdl_info. | |
298 | */ | |
299 | prev->next = si->next; | |
300 | if (si == sonext) sonext = prev; | |
301 | si->next = freelist; | |
302 | freelist = si; | |
303 | } | |
304 | ||
305 | const char *addr_to_name(unsigned addr) | |
306 | { | |
307 | soinfo *si; | |
308 | ||
309 | for(si = solist; si != 0; si = si->next){ | |
310 | if((addr >= si->base) && (addr < (si->base + si->size))) { | |
311 | return si->name; | |
312 | } | |
313 | } | |
314 | ||
315 | return ""; | |
316 | } | |
317 | ||
318 | /* For a given PC, find the .so that it belongs to. | |
319 | * Returns the base address of the .ARM.exidx section | |
320 | * for that .so, and the number of 8-byte entries | |
321 | * in that section (via *pcount). | |
322 | * | |
323 | * Intended to be called by libc's __gnu_Unwind_Find_exidx(). | |
324 | * | |
325 | * This function is exposed via dlfcn.c and libdl.so. | |
326 | */ | |
327 | #ifdef ANDROID_ARM_LINKER | |
328 | _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount) | |
329 | { | |
330 | soinfo *si; | |
331 | unsigned addr = (unsigned)pc; | |
332 | ||
333 | for (si = solist; si != 0; si = si->next){ | |
334 | if ((addr >= si->base) && (addr < (si->base + si->size))) { | |
335 | *pcount = si->ARM_exidx_count; | |
336 | return (_Unwind_Ptr)(si->base + (unsigned long)si->ARM_exidx); | |
337 | } | |
338 | } | |
339 | *pcount = 0; | |
340 | return NULL; | |
341 | } | |
342 | #elif defined(ANDROID_X86_LINKER) | |
343 | /* Here, we only have to provide a callback to iterate across all the | |
344 | * loaded libraries. gcc_eh does the rest. */ | |
345 | int | |
346 | android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), | |
347 | void *data) | |
348 | { | |
349 | soinfo *si; | |
350 | struct dl_phdr_info dl_info; | |
351 | int rv = 0; | |
352 | ||
353 | for (si = solist; si != NULL; si = si->next) { | |
354 | dl_info.dlpi_addr = si->linkmap.l_addr; | |
355 | dl_info.dlpi_name = si->linkmap.l_name; | |
356 | dl_info.dlpi_phdr = si->phdr; | |
357 | dl_info.dlpi_phnum = si->phnum; | |
358 | rv = cb(&dl_info, sizeof (struct dl_phdr_info), data); | |
359 | if (rv != 0) | |
360 | break; | |
361 | } | |
362 | return rv; | |
363 | } | |
364 | #endif | |
365 | ||
366 | static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) | |
367 | { | |
368 | Elf32_Sym *s; | |
369 | Elf32_Sym *symtab = si->symtab; | |
370 | const char *strtab = si->strtab; | |
371 | unsigned n; | |
372 | ||
373 | TRACE_TYPE(LOOKUP, "%5d SEARCH %s in %s@0x%08x %08x %d\n", pid, | |
374 | name, si->name, si->base, hash, hash % si->nbucket); | |
375 | n = hash % si->nbucket; | |
376 | ||
377 | for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){ | |
378 | s = symtab + n; | |
379 | if(strcmp(strtab + s->st_name, name)) continue; | |
380 | ||
381 | /* only concern ourselves with global and weak symbol definitions */ | |
382 | switch(ELF32_ST_BIND(s->st_info)){ | |
383 | case STB_GLOBAL: | |
384 | case STB_WEAK: | |
385 | /* no section == undefined */ | |
386 | if(s->st_shndx == 0) continue; | |
387 | ||
388 | TRACE_TYPE(LOOKUP, "%5d FOUND %s in %s (%08x) %d\n", pid, | |
389 | name, si->name, s->st_value, s->st_size); | |
390 | return s; | |
391 | } | |
392 | } | |
393 | ||
394 | return NULL; | |
395 | } | |
396 | ||
397 | static unsigned elfhash(const char *_name) | |
398 | { | |
399 | const unsigned char *name = (const unsigned char *) _name; | |
400 | unsigned h = 0, g; | |
401 | ||
402 | while(*name) { | |
403 | h = (h << 4) + *name++; | |
404 | g = h & 0xf0000000; | |
405 | h ^= g; | |
406 | h ^= g >> 24; | |
407 | } | |
408 | return h; | |
409 | } | |
410 | ||
411 | static Elf32_Sym * | |
412 | _do_lookup(soinfo *si, const char *name, unsigned *base) | |
413 | { | |
414 | unsigned elf_hash = elfhash(name); | |
415 | Elf32_Sym *s; | |
416 | unsigned *d; | |
417 | soinfo *lsi = si; | |
418 | int i; | |
419 | ||
420 | /* Look for symbols in the local scope first (the object who is | |
421 | * searching). This happens with C++ templates on i386 for some | |
422 | * reason. | |
423 | * | |
424 | * Notes on weak symbols: | |
425 | * The ELF specs are ambigious about treatment of weak definitions in | |
426 | * dynamic linking. Some systems return the first definition found | |
427 | * and some the first non-weak definition. This is system dependent. | |
428 | * Here we return the first definition found for simplicity. */ | |
429 | s = _elf_lookup(si, elf_hash, name); | |
430 | if(s != NULL) | |
431 | goto done; | |
432 | ||
433 | /* Next, look for it in the preloads list */ | |
434 | for(i = 0; preloads[i] != NULL; i++) { | |
435 | lsi = preloads[i]; | |
436 | s = _elf_lookup(lsi, elf_hash, name); | |
437 | if(s != NULL) | |
438 | goto done; | |
439 | } | |
440 | ||
441 | for(d = si->dynamic; *d; d += 2) { | |
442 | if(d[0] == DT_NEEDED){ | |
443 | lsi = (soinfo *)d[1]; | |
444 | if (!validate_soinfo(lsi)) { | |
445 | DL_ERR("%5d bad DT_NEEDED pointer in %s", | |
446 | pid, si->name); | |
447 | return NULL; | |
448 | } | |
449 | ||
450 | DEBUG("%5d %s: looking up %s in %s\n", | |
451 | pid, si->name, name, lsi->name); | |
452 | s = _elf_lookup(lsi, elf_hash, name); | |
453 | if ((s != NULL) && (s->st_shndx != SHN_UNDEF)) | |
454 | goto done; | |
455 | } | |
456 | } | |
457 | ||
458 | #if ALLOW_SYMBOLS_FROM_MAIN | |
459 | /* If we are resolving relocations while dlopen()ing a library, it's OK for | |
460 | * the library to resolve a symbol that's defined in the executable itself, | |
461 | * although this is rare and is generally a bad idea. | |
462 | */ | |
463 | if (somain) { | |
464 | lsi = somain; | |
465 | DEBUG("%5d %s: looking up %s in executable %s\n", | |
466 | pid, si->name, name, lsi->name); | |
467 | s = _elf_lookup(lsi, elf_hash, name); | |
468 | } | |
469 | #endif | |
470 | ||
471 | done: | |
472 | if(s != NULL) { | |
473 | TRACE_TYPE(LOOKUP, "%5d si %s sym %s s->st_value = 0x%08x, " | |
474 | "found in %s, base = 0x%08x\n", | |
475 | pid, si->name, name, s->st_value, lsi->name, lsi->base); | |
476 | *base = lsi->base; | |
477 | return s; | |
478 | } | |
479 | ||
480 | return NULL; | |
481 | } | |
482 | ||
483 | /* This is used by dl_sym(). It performs symbol lookup only within the | |
484 | specified soinfo object and not in any of its dependencies. | |
485 | */ | |
486 | Elf32_Sym *lookup_in_library(soinfo *si, const char *name) | |
487 | { | |
488 | return _elf_lookup(si, elfhash(name), name); | |
489 | } | |
490 | ||
491 | /* This is used by dl_sym(). It performs a global symbol lookup. | |
492 | */ | |
493 | Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) | |
494 | { | |
495 | unsigned elf_hash = elfhash(name); | |
496 | Elf32_Sym *s = NULL; | |
497 | soinfo *si; | |
498 | ||
499 | if(start == NULL) { | |
500 | start = solist; | |
501 | } | |
502 | ||
503 | for(si = start; (s == NULL) && (si != NULL); si = si->next) | |
504 | { | |
505 | if(si->flags & FLAG_ERROR) | |
506 | continue; | |
507 | s = _elf_lookup(si, elf_hash, name); | |
508 | if (s != NULL) { | |
509 | *found = si; | |
510 | break; | |
511 | } | |
512 | } | |
513 | ||
514 | if(s != NULL) { | |
515 | TRACE_TYPE(LOOKUP, "%5d %s s->st_value = 0x%08x, " | |
516 | "si->base = 0x%08x\n", pid, name, s->st_value, si->base); | |
517 | return s; | |
518 | } | |
519 | ||
520 | return NULL; | |
521 | } | |
522 | ||
523 | soinfo *find_containing_library(const void *addr) | |
524 | { | |
525 | soinfo *si; | |
526 | ||
527 | for(si = solist; si != NULL; si = si->next) | |
528 | { | |
529 | if((unsigned)addr >= si->base && (unsigned)addr - si->base < si->size) { | |
530 | return si; | |
531 | } | |
532 | } | |
533 | ||
534 | return NULL; | |
535 | } | |
536 | ||
537 | Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) | |
538 | { | |
539 | unsigned int i; | |
540 | unsigned soaddr = (unsigned)addr - si->base; | |
541 | ||
542 | /* Search the library's symbol table for any defined symbol which | |
543 | * contains this address */ | |
544 | for(i=0; i<si->nchain; i++) { | |
545 | Elf32_Sym *sym = &si->symtab[i]; | |
546 | ||
547 | if(sym->st_shndx != SHN_UNDEF && | |
548 | soaddr >= sym->st_value && | |
549 | soaddr < sym->st_value + sym->st_size) { | |
550 | return sym; | |
551 | } | |
552 | } | |
553 | ||
554 | return NULL; | |
555 | } | |
556 | ||
557 | #if 0 | |
558 | static void dump(soinfo *si) | |
559 | { | |
560 | Elf32_Sym *s = si->symtab; | |
561 | unsigned n; | |
562 | ||
563 | for(n = 0; n < si->nchain; n++) { | |
564 | TRACE("%5d %04d> %08x: %02x %04x %08x %08x %s\n", pid, n, s, | |
565 | s->st_info, s->st_shndx, s->st_value, s->st_size, | |
566 | si->strtab + s->st_name); | |
567 | s++; | |
568 | } | |
569 | } | |
570 | #endif | |
571 | ||
572 | static const char *sopaths[] = { | |
573 | "/vendor/lib", | |
574 | "/system/lib", | |
575 | 0 | |
576 | }; | |
577 | ||
578 | static int _open_lib(const char *name) | |
579 | { | |
580 | int fd; | |
581 | struct stat filestat; | |
582 | ||
583 | if ((stat(name, &filestat) >= 0) && S_ISREG(filestat.st_mode)) { | |
584 | if ((fd = open(name, O_RDONLY)) >= 0) | |
585 | return fd; | |
586 | } | |
587 | ||
588 | return -1; | |
589 | } | |
590 | ||
591 | static int open_library(const char *name) | |
592 | { | |
593 | int fd; | |
594 | char buf[512]; | |
595 | const char **path; | |
596 | int n; | |
597 | ||
598 | TRACE("[ %5d opening %s ]\n", pid, name); | |
599 | ||
600 | if(name == 0) return -1; | |
601 | if(strlen(name) > 256) return -1; | |
602 | ||
603 | if ((name[0] == '/') && ((fd = _open_lib(name)) >= 0)) | |
604 | return fd; | |
605 | ||
606 | for (path = ldpaths; *path; path++) { | |
607 | n = format_buffer(buf, sizeof(buf), "%s/%s", *path, name); | |
608 | if (n < 0 || n >= (int)sizeof(buf)) { | |
609 | WARN("Ignoring very long library path: %s/%s\n", *path, name); | |
610 | continue; | |
611 | } | |
612 | if ((fd = _open_lib(buf)) >= 0) | |
613 | return fd; | |
614 | } | |
615 | for (path = sopaths; *path; path++) { | |
616 | n = format_buffer(buf, sizeof(buf), "%s/%s", *path, name); | |
617 | if (n < 0 || n >= (int)sizeof(buf)) { | |
618 | WARN("Ignoring very long library path: %s/%s\n", *path, name); | |
619 | continue; | |
620 | } | |
621 | if ((fd = _open_lib(buf)) >= 0) | |
622 | return fd; | |
623 | } | |
624 | ||
625 | return -1; | |
626 | } | |
627 | ||
628 | /* temporary space for holding the first page of the shared lib | |
629 | * which contains the elf header (with the pht). */ | |
630 | static unsigned char __header[PAGE_SIZE]; | |
631 | ||
632 | typedef struct { | |
633 | long mmap_addr; | |
634 | char tag[4]; /* 'P', 'R', 'E', ' ' */ | |
635 | } prelink_info_t; | |
636 | ||
637 | /* Returns the requested base address if the library is prelinked, | |
638 | * and 0 otherwise. */ | |
639 | static unsigned long | |
640 | is_prelinked(int fd, const char *name) | |
641 | { | |
642 | off_t sz; | |
643 | prelink_info_t info; | |
644 | ||
645 | sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END); | |
646 | if (sz < 0) { | |
647 | DL_ERR("lseek() failed!"); | |
648 | return 0; | |
649 | } | |
650 | ||
651 | if (read(fd, &info, sizeof(info)) != sizeof(info)) { | |
652 | WARN("Could not read prelink_info_t structure for `%s`\n", name); | |
653 | return 0; | |
654 | } | |
655 | ||
656 | if (strncmp(info.tag, "PRE ", 4)) { | |
657 | WARN("`%s` is not a prelinked library\n", name); | |
658 | return 0; | |
659 | } | |
660 | ||
661 | return (unsigned long)info.mmap_addr; | |
662 | } | |
663 | ||
664 | /* verify_elf_object | |
665 | * Verifies if the object @ base is a valid ELF object | |
666 | * | |
667 | * Args: | |
668 | * | |
669 | * Returns: | |
670 | * 0 on success | |
671 | * -1 if no valid ELF object is found @ base. | |
672 | */ | |
673 | static int | |
674 | verify_elf_object(void *base, const char *name) | |
675 | { | |
676 | Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; | |
677 | ||
678 | if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; | |
679 | if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; | |
680 | if (hdr->e_ident[EI_MAG2] != ELFMAG2) return -1; | |
681 | if (hdr->e_ident[EI_MAG3] != ELFMAG3) return -1; | |
682 | ||
683 | /* TODO: Should we verify anything else in the header? */ | |
684 | #ifdef ANDROID_ARM_LINKER | |
685 | if (hdr->e_machine != EM_ARM) return -1; | |
686 | #elif defined(ANDROID_X86_LINKER) | |
687 | if (hdr->e_machine != EM_386) return -1; | |
688 | #endif | |
689 | return 0; | |
690 | } | |
691 | ||
692 | ||
693 | /* get_lib_extents | |
694 | * Retrieves the base (*base) address where the ELF object should be | |
695 | * mapped and its overall memory size (*total_sz). | |
696 | * | |
697 | * Args: | |
698 | * fd: Opened file descriptor for the library | |
699 | * name: The name of the library | |
700 | * _hdr: Pointer to the header page of the library | |
701 | * total_sz: Total size of the memory that should be allocated for | |
702 | * this library | |
703 | * | |
704 | * Returns: | |
705 | * -1 if there was an error while trying to get the lib extents. | |
706 | * The possible reasons are: | |
707 | * - Could not determine if the library was prelinked. | |
708 | * - The library provided is not a valid ELF object | |
709 | * 0 if the library did not request a specific base offset (normal | |
710 | * for non-prelinked libs) | |
711 | * > 0 if the library requests a specific address to be mapped to. | |
712 | * This indicates a pre-linked library. | |
713 | */ | |
714 | static unsigned | |
715 | get_lib_extents(int fd, const char *name, void *__hdr, unsigned *total_sz) | |
716 | { | |
717 | unsigned req_base; | |
718 | unsigned min_vaddr = 0xffffffff; | |
719 | unsigned max_vaddr = 0; | |
720 | unsigned char *_hdr = (unsigned char *)__hdr; | |
721 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; | |
722 | Elf32_Phdr *phdr; | |
723 | int cnt; | |
724 | ||
725 | TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); | |
726 | if (verify_elf_object(_hdr, name) < 0) { | |
727 | DL_ERR("%5d - %s is not a valid ELF object", pid, name); | |
728 | return (unsigned)-1; | |
729 | } | |
730 | ||
731 | req_base = (unsigned) is_prelinked(fd, name); | |
732 | if (req_base == (unsigned)-1) | |
733 | return -1; | |
734 | else if (req_base != 0) { | |
735 | TRACE("[ %5d - Prelinked library '%s' requesting base @ 0x%08x ]\n", | |
736 | pid, name, req_base); | |
737 | } else { | |
738 | TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); | |
739 | } | |
740 | ||
741 | phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); | |
742 | ||
743 | /* find the min/max p_vaddrs from all the PT_LOAD segments so we can | |
744 | * get the range. */ | |
745 | for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { | |
746 | if (phdr->p_type == PT_LOAD) { | |
747 | if ((phdr->p_vaddr + phdr->p_memsz) > max_vaddr) | |
748 | max_vaddr = phdr->p_vaddr + phdr->p_memsz; | |
749 | if (phdr->p_vaddr < min_vaddr) | |
750 | min_vaddr = phdr->p_vaddr; | |
751 | } | |
752 | } | |
753 | ||
754 | if ((min_vaddr == 0xffffffff) && (max_vaddr == 0)) { | |
755 | DL_ERR("%5d - No loadable segments found in %s.", pid, name); | |
756 | return (unsigned)-1; | |
757 | } | |
758 | ||
759 | /* truncate min_vaddr down to page boundary */ | |
760 | min_vaddr &= ~PAGE_MASK; | |
761 | ||
762 | /* round max_vaddr up to the next page */ | |
763 | max_vaddr = (max_vaddr + PAGE_SIZE - 1) & ~PAGE_MASK; | |
764 | ||
765 | *total_sz = (max_vaddr - min_vaddr); | |
766 | return (unsigned)req_base; | |
767 | } | |
768 | ||
769 | /* alloc_mem_region | |
770 | * | |
771 | * This function reserves a chunk of memory to be used for mapping in | |
772 | * the shared library. We reserve the entire memory region here, and | |
773 | * then the rest of the linker will relocate the individual loadable | |
774 | * segments into the correct locations within this memory range. | |
775 | * | |
776 | * Args: | |
777 | * si->base: The requested base of the allocation. If 0, a sane one will be | |
778 | * chosen in the range LIBBASE <= base < LIBLAST. | |
779 | * si->size: The size of the allocation. | |
780 | * | |
781 | * Returns: | |
782 | * -1 on failure, and 0 on success. On success, si->base will contain | |
783 | * the virtual address at which the library will be mapped. | |
784 | */ | |
785 | ||
786 | static int reserve_mem_region(soinfo *si) | |
787 | { | |
788 | void *base = mmap((void *)si->base, si->size, PROT_READ | PROT_EXEC, | |
789 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
790 | if (base == MAP_FAILED) { | |
791 | DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x " | |
792 | "as requested, will try general pool: %d (%s)", | |
793 | pid, (si->base ? "" : "non-"), si->name, si->base, | |
794 | errno, strerror(errno)); | |
795 | return -1; | |
796 | } else if (base != (void *)si->base) { | |
797 | DL_ERR("OOPS: %5d %sprelinked library '%s' mapped at 0x%08x, " | |
798 | "not at 0x%08x", pid, (si->base ? "" : "non-"), | |
799 | si->name, (unsigned)base, si->base); | |
800 | munmap(base, si->size); | |
801 | return -1; | |
802 | } | |
803 | return 0; | |
804 | } | |
805 | ||
806 | static int | |
807 | alloc_mem_region(soinfo *si) | |
808 | { | |
809 | if (si->base) { | |
810 | /* Attempt to mmap a prelinked library. */ | |
811 | return reserve_mem_region(si); | |
812 | } | |
813 | ||
814 | /* This is not a prelinked library, so we use the kernel's default | |
815 | allocator. | |
816 | */ | |
817 | ||
818 | void *base = mmap(NULL, si->size, PROT_READ | PROT_EXEC, | |
819 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
820 | if (base == MAP_FAILED) { | |
821 | DL_ERR("%5d mmap of library '%s' failed: %d (%s)\n", | |
822 | pid, si->name, | |
823 | errno, strerror(errno)); | |
824 | goto err; | |
825 | } | |
826 | si->base = (unsigned) base; | |
827 | PRINT("%5d mapped library '%s' to %08x via kernel allocator.\n", | |
828 | pid, si->name, si->base); | |
829 | return 0; | |
830 | ||
831 | err: | |
832 | DL_ERR("OOPS: %5d cannot map library '%s'. no vspace available.", | |
833 | pid, si->name); | |
834 | return -1; | |
835 | } | |
836 | ||
837 | #define MAYBE_MAP_FLAG(x,from,to) (((x) & (from)) ? (to) : 0) | |
838 | #define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ | |
839 | MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ | |
840 | MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) | |
841 | /* load_segments | |
842 | * | |
843 | * This function loads all the loadable (PT_LOAD) segments into memory | |
844 | * at their appropriate memory offsets off the base address. | |
845 | * | |
846 | * Args: | |
847 | * fd: Open file descriptor to the library to load. | |
848 | * header: Pointer to a header page that contains the ELF header. | |
849 | * This is needed since we haven't mapped in the real file yet. | |
850 | * si: ptr to soinfo struct describing the shared object. | |
851 | * | |
852 | * Returns: | |
853 | * 0 on success, -1 on failure. | |
854 | */ | |
855 | static int | |
856 | load_segments(int fd, void *header, soinfo *si) | |
857 | { | |
858 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; | |
859 | Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); | |
860 | unsigned char *base = (Elf32_Addr) si->base; | |
861 | int cnt; | |
862 | unsigned len; | |
863 | unsigned char *tmp; | |
864 | unsigned char *pbase; | |
865 | unsigned char *extra_base; | |
866 | unsigned extra_len; | |
867 | unsigned total_sz = 0; | |
868 | ||
869 | si->wrprotect_start = 0xffffffff; | |
870 | si->wrprotect_end = 0; | |
871 | ||
872 | TRACE("[ %5d - Begin loading segments for '%s' @ 0x%08x ]\n", | |
873 | pid, si->name, (unsigned)si->base); | |
874 | /* Now go through all the PT_LOAD segments and map them into memory | |
875 | * at the appropriate locations. */ | |
876 | for (cnt = 0; cnt < ehdr->e_phnum; ++cnt, ++phdr) { | |
877 | if (phdr->p_type == PT_LOAD) { | |
878 | DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid); | |
879 | /* we want to map in the segment on a page boundary */ | |
880 | tmp = base + (phdr->p_vaddr & (~PAGE_MASK)); | |
881 | /* add the # of bytes we masked off above to the total length. */ | |
882 | len = phdr->p_filesz + (phdr->p_vaddr & PAGE_MASK); | |
883 | ||
884 | TRACE("[ %d - Trying to load segment from '%s' @ 0x%08x " | |
885 | "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x ]\n", pid, si->name, | |
886 | (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); | |
887 | pbase = mmap(tmp, len, PFLAGS_TO_PROT(phdr->p_flags), | |
888 | MAP_PRIVATE | MAP_FIXED, fd, | |
889 | phdr->p_offset & (~PAGE_MASK)); | |
890 | if (pbase == MAP_FAILED) { | |
891 | DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " | |
892 | "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, | |
893 | (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); | |
894 | goto fail; | |
895 | } | |
896 | ||
897 | /* If 'len' didn't end on page boundary, and it's a writable | |
898 | * segment, zero-fill the rest. */ | |
899 | if ((len & PAGE_MASK) && (phdr->p_flags & PF_W)) | |
900 | memset((void *)(pbase + len), 0, PAGE_SIZE - (len & PAGE_MASK)); | |
901 | ||
902 | /* Check to see if we need to extend the map for this segment to | |
903 | * cover the diff between filesz and memsz (i.e. for bss). | |
904 | * | |
905 | * base _+---------------------+ page boundary | |
906 | * . . | |
907 | * | | | |
908 | * . . | |
909 | * pbase _+---------------------+ page boundary | |
910 | * | | | |
911 | * . . | |
912 | * base + p_vaddr _| | | |
913 | * . \ \ . | |
914 | * . | filesz | . | |
915 | * pbase + len _| / | | | |
916 | * <0 pad> . . . | |
917 | * extra_base _+------------|--------+ page boundary | |
918 | * / . . . | |
919 | * | . . . | |
920 | * | +------------|--------+ page boundary | |
921 | * extra_len-> | | | | | |
922 | * | . | memsz . | |
923 | * | . | . | |
924 | * \ _| / | | |
925 | * . . | |
926 | * | | | |
927 | * _+---------------------+ page boundary | |
928 | */ | |
929 | tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & | |
930 | (~PAGE_MASK)); | |
931 | if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { | |
932 | extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; | |
933 | TRACE("[ %5d - Need to extend segment from '%s' @ 0x%08x " | |
934 | "(0x%08x) ]\n", pid, si->name, (unsigned)tmp, extra_len); | |
935 | /* map in the extra page(s) as anonymous into the range. | |
936 | * This is probably not necessary as we already mapped in | |
937 | * the entire region previously, but we just want to be | |
938 | * sure. This will also set the right flags on the region | |
939 | * (though we can probably accomplish the same thing with | |
940 | * mprotect). | |
941 | */ | |
942 | extra_base = mmap((void *)tmp, extra_len, | |
943 | PFLAGS_TO_PROT(phdr->p_flags), | |
944 | MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, | |
945 | -1, 0); | |
946 | if (extra_base == MAP_FAILED) { | |
947 | DL_ERR("[ %5d - failed to extend segment from '%s' @ 0x%08x" | |
948 | " (0x%08x) ]", pid, si->name, (unsigned)tmp, | |
949 | extra_len); | |
950 | goto fail; | |
951 | } | |
952 | /* TODO: Check if we need to memset-0 this region. | |
953 | * Anonymous mappings are zero-filled copy-on-writes, so we | |
954 | * shouldn't need to. */ | |
955 | TRACE("[ %5d - Segment from '%s' extended @ 0x%08x " | |
956 | "(0x%08x)\n", pid, si->name, (unsigned)extra_base, | |
957 | extra_len); | |
958 | } | |
959 | /* set the len here to show the full extent of the segment we | |
960 | * just loaded, mostly for debugging */ | |
961 | len = (((unsigned)base + phdr->p_vaddr + phdr->p_memsz + | |
962 | PAGE_SIZE - 1) & (~PAGE_MASK)) - (unsigned)pbase; | |
963 | TRACE("[ %5d - Successfully loaded segment from '%s' @ 0x%08x " | |
964 | "(0x%08x). p_vaddr=0x%08x p_offset=0x%08x\n", pid, si->name, | |
965 | (unsigned)pbase, len, phdr->p_vaddr, phdr->p_offset); | |
966 | total_sz += len; | |
967 | /* Make the section writable just in case we'll have to write to | |
968 | * it during relocation (i.e. text segment). However, we will | |
969 | * remember what range of addresses should be write protected. | |
970 | * | |
971 | */ | |
972 | if (!(phdr->p_flags & PF_W)) { | |
973 | if ((unsigned)pbase < si->wrprotect_start) | |
974 | si->wrprotect_start = (unsigned)pbase; | |
975 | if (((unsigned)pbase + len) > si->wrprotect_end) | |
976 | si->wrprotect_end = (unsigned)pbase + len; | |
977 | mprotect(pbase, len, | |
978 | PFLAGS_TO_PROT(phdr->p_flags) | PROT_WRITE); | |
979 | } | |
980 | } else if (phdr->p_type == PT_DYNAMIC) { | |
981 | DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid); | |
982 | /* this segment contains the dynamic linking information */ | |
983 | si->dynamic = (unsigned *)(base + phdr->p_vaddr); | |
984 | } else { | |
985 | #ifdef ANDROID_ARM_LINKER | |
986 | if (phdr->p_type == PT_ARM_EXIDX) { | |
987 | DEBUG_DUMP_PHDR(phdr, "PT_ARM_EXIDX", pid); | |
988 | /* exidx entries (used for stack unwinding) are 8 bytes each. | |
989 | */ | |
990 | si->ARM_exidx = (unsigned *)phdr->p_vaddr; | |
991 | si->ARM_exidx_count = phdr->p_memsz / 8; | |
992 | } | |
993 | #endif | |
994 | } | |
995 | ||
996 | } | |
997 | ||
998 | /* Sanity check */ | |
999 | if (total_sz > si->size) { | |
1000 | DL_ERR("%5d - Total length (0x%08x) of mapped segments from '%s' is " | |
1001 | "greater than what was allocated (0x%08x). THIS IS BAD!", | |
1002 | pid, total_sz, si->name, si->size); | |
1003 | goto fail; | |
1004 | } | |
1005 | ||
1006 | TRACE("[ %5d - Finish loading segments for '%s' @ 0x%08x. " | |
1007 | "Total memory footprint: 0x%08x bytes ]\n", pid, si->name, | |
1008 | (unsigned)si->base, si->size); | |
1009 | return 0; | |
1010 | ||
1011 | fail: | |
1012 | /* We can just blindly unmap the entire region even though some things | |
1013 | * were mapped in originally with anonymous and others could have been | |
1014 | * been mapped in from the file before we failed. The kernel will unmap | |
1015 | * all the pages in the range, irrespective of how they got there. | |
1016 | */ | |
1017 | munmap((void *)si->base, si->size); | |
1018 | si->flags |= FLAG_ERROR; | |
1019 | return -1; | |
1020 | } | |
1021 | ||
1022 | /* TODO: Implement this to take care of the fact that Android ARM | |
1023 | * ELF objects shove everything into a single loadable segment that has the | |
1024 | * write bit set. wr_offset is then used to set non-(data|bss) pages to be | |
1025 | * non-writable. | |
1026 | */ | |
1027 | #if 0 | |
1028 | static unsigned | |
1029 | get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) | |
1030 | { | |
1031 | Elf32_Shdr *shdr_start; | |
1032 | Elf32_Shdr *shdr; | |
1033 | int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); | |
1034 | int cnt; | |
1035 | unsigned wr_offset = 0xffffffff; | |
1036 | ||
1037 | shdr_start = mmap(0, shdr_sz, PROT_READ, MAP_PRIVATE, fd, | |
1038 | ehdr->e_shoff & (~PAGE_MASK)); | |
1039 | if (shdr_start == MAP_FAILED) { | |
1040 | WARN("%5d - Could not read section header info from '%s'. Will not " | |
1041 | "not be able to determine write-protect offset.\n", pid, name); | |
1042 | return (unsigned)-1; | |
1043 | } | |
1044 | ||
1045 | for(cnt = 0, shdr = shdr_start; cnt < ehdr->e_shnum; ++cnt, ++shdr) { | |
1046 | if ((shdr->sh_type != SHT_NULL) && (shdr->sh_flags & SHF_WRITE) && | |
1047 | (shdr->sh_addr < wr_offset)) { | |
1048 | wr_offset = shdr->sh_addr; | |
1049 | } | |
1050 | } | |
1051 | ||
1052 | munmap(shdr_start, shdr_sz); | |
1053 | return wr_offset; | |
1054 | } | |
1055 | #endif | |
1056 | ||
1057 | static soinfo * | |
1058 | load_library(const char *name) | |
1059 | { | |
1060 | int fd = open_library(name); | |
1061 | int cnt; | |
1062 | unsigned ext_sz; | |
1063 | unsigned req_base; | |
1064 | const char *bname; | |
1065 | soinfo *si = NULL; | |
1066 | Elf32_Ehdr *hdr; | |
1067 | ||
1068 | if(fd == -1) { | |
1069 | DL_ERR("Library '%s' not found", name); | |
1070 | return NULL; | |
1071 | } | |
1072 | ||
1073 | /* We have to read the ELF header to figure out what to do with this image | |
1074 | */ | |
1075 | if (lseek(fd, 0, SEEK_SET) < 0) { | |
1076 | DL_ERR("lseek() failed!"); | |
1077 | goto fail; | |
1078 | } | |
1079 | ||
1080 | if ((cnt = read(fd, &__header[0], PAGE_SIZE)) < 0) { | |
1081 | DL_ERR("read() failed!"); | |
1082 | goto fail; | |
1083 | } | |
1084 | ||
1085 | /* Parse the ELF header and get the size of the memory footprint for | |
1086 | * the library */ | |
1087 | req_base = get_lib_extents(fd, name, &__header[0], &ext_sz); | |
1088 | if (req_base == (unsigned)-1) | |
1089 | goto fail; | |
1090 | TRACE("[ %5d - '%s' (%s) wants base=0x%08x sz=0x%08x ]\n", pid, name, | |
1091 | (req_base ? "prelinked" : "not pre-linked"), req_base, ext_sz); | |
1092 | ||
1093 | /* Now configure the soinfo struct where we'll store all of our data | |
1094 | * for the ELF object. If the loading fails, we waste the entry, but | |
1095 | * same thing would happen if we failed during linking. Configuring the | |
1096 | * soinfo struct here is a lot more convenient. | |
1097 | */ | |
1098 | bname = strrchr(name, '/'); | |
1099 | si = alloc_info(bname ? bname + 1 : name); | |
1100 | if (si == NULL) | |
1101 | goto fail; | |
1102 | ||
1103 | /* Carve out a chunk of memory where we will map in the individual | |
1104 | * segments */ | |
1105 | si->base = req_base; | |
1106 | si->size = ext_sz; | |
1107 | si->flags = 0; | |
1108 | si->entry = 0; | |
1109 | si->dynamic = (unsigned *)-1; | |
1110 | if (alloc_mem_region(si) < 0) | |
1111 | goto fail; | |
1112 | ||
1113 | TRACE("[ %5d allocated memory for %s @ %p (0x%08x) ]\n", | |
1114 | pid, name, (void *)si->base, (unsigned) ext_sz); | |
1115 | ||
1116 | /* Now actually load the library's segments into right places in memory */ | |
1117 | if (load_segments(fd, &__header[0], si) < 0) { | |
1118 | goto fail; | |
1119 | } | |
1120 | ||
1121 | /* this might not be right. Technically, we don't even need this info | |
1122 | * once we go through 'load_segments'. */ | |
1123 | hdr = (Elf32_Ehdr *)si->base; | |
1124 | si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); | |
1125 | si->phnum = hdr->e_phnum; | |
1126 | /**/ | |
1127 | ||
1128 | close(fd); | |
1129 | return si; | |
1130 | ||
1131 | fail: | |
1132 | if (si) free_info(si); | |
1133 | close(fd); | |
1134 | return NULL; | |
1135 | } | |
1136 | ||
1137 | static soinfo * | |
1138 | init_library(soinfo *si) | |
1139 | { | |
1140 | unsigned wr_offset = 0xffffffff; | |
1141 | ||
1142 | /* At this point we know that whatever is loaded @ base is a valid ELF | |
1143 | * shared library whose segments are properly mapped in. */ | |
1144 | TRACE("[ %5d init_library base=0x%08x sz=0x%08x name='%s') ]\n", | |
1145 | pid, si->base, si->size, si->name); | |
1146 | ||
1147 | if(link_image(si, wr_offset)) { | |
1148 | /* We failed to link. However, we can only restore libbase | |
1149 | ** if no additional libraries have moved it since we updated it. | |
1150 | */ | |
1151 | munmap((void *)si->base, si->size); | |
1152 | return NULL; | |
1153 | } | |
1154 | ||
1155 | return si; | |
1156 | } | |
1157 | ||
1158 | soinfo *find_library(const char *name) | |
1159 | { | |
1160 | soinfo *si; | |
1161 | const char *bname; | |
1162 | ||
1163 | #if ALLOW_SYMBOLS_FROM_MAIN | |
1164 | if (name == NULL) | |
1165 | return somain; | |
1166 | #else | |
1167 | if (name == NULL) | |
1168 | return NULL; | |
1169 | #endif | |
1170 | ||
1171 | bname = strrchr(name, '/'); | |
1172 | bname = bname ? bname + 1 : name; | |
1173 | ||
1174 | for(si = solist; si != 0; si = si->next){ | |
1175 | if(!strcmp(bname, si->name)) { | |
1176 | if(si->flags & FLAG_ERROR) { | |
1177 | DL_ERR("%5d '%s' failed to load previously", pid, bname); | |
1178 | return NULL; | |
1179 | } | |
1180 | if(si->flags & FLAG_LINKED) return si; | |
1181 | DL_ERR("OOPS: %5d recursive link to '%s'", pid, si->name); | |
1182 | return NULL; | |
1183 | } | |
1184 | } | |
1185 | ||
1186 | TRACE("[ %5d '%s' has not been loaded yet. Locating...]\n", pid, name); | |
1187 | si = load_library(name); | |
1188 | if(si == NULL) | |
1189 | return NULL; | |
1190 | return init_library(si); | |
1191 | } | |
1192 | ||
1193 | /* TODO: | |
1194 | * notify gdb of unload | |
1195 | * for non-prelinked libraries, find a way to decrement libbase | |
1196 | */ | |
1197 | static void call_destructors(soinfo *si); | |
1198 | unsigned unload_library(soinfo *si) | |
1199 | { | |
1200 | unsigned *d; | |
1201 | if (si->refcount == 1) { | |
1202 | TRACE("%5d unloading '%s'\n", pid, si->name); | |
1203 | call_destructors(si); | |
1204 | ||
1205 | ||
1206 | for(d = si->dynamic; *d; d += 2) { | |
1207 | if(d[0] == DT_NEEDED){ | |
1208 | soinfo *lsi = (soinfo *)d[1]; | |
1209 | d[1] = 0; | |
1210 | if (validate_soinfo(lsi)) { | |
1211 | TRACE("%5d %s needs to unload %s\n", pid, | |
1212 | si->name, lsi->name); | |
1213 | unload_library(lsi); | |
1214 | } | |
1215 | else | |
1216 | DL_ERR("%5d %s: could not unload dependent library", | |
1217 | pid, si->name); | |
1218 | } | |
1219 | } | |
1220 | ||
1221 | munmap((char *)si->base, si->size); | |
1222 | notify_gdb_of_unload(si); | |
1223 | free_info(si); | |
1224 | si->refcount = 0; | |
1225 | } | |
1226 | else { | |
1227 | si->refcount--; | |
1228 | PRINT("%5d not unloading '%s', decrementing refcount to %d\n", | |
1229 | pid, si->name, si->refcount); | |
1230 | } | |
1231 | return si->refcount; | |
1232 | } | |
1233 | ||
1234 | /* TODO: don't use unsigned for addrs below. It works, but is not | |
1235 | * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned | |
1236 | * long. | |
1237 | */ | |
1238 | static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) | |
1239 | { | |
1240 | Elf32_Sym *symtab = si->symtab; | |
1241 | const char *strtab = si->strtab; | |
1242 | Elf32_Sym *s; | |
1243 | unsigned base; | |
1244 | Elf32_Rel *start = rel; | |
1245 | unsigned idx; | |
1246 | ||
1247 | for (idx = 0; idx < count; ++idx) { | |
1248 | unsigned type = ELF32_R_TYPE(rel->r_info); | |
1249 | unsigned sym = ELF32_R_SYM(rel->r_info); | |
1250 | unsigned reloc = (unsigned)(rel->r_offset + si->base); | |
1251 | unsigned sym_addr = 0; | |
1252 | char *sym_name = NULL; | |
1253 | ||
1254 | //printf("%5d Processing '%s' relocation at index %d\n", pid, | |
1255 | // si->name, idx); | |
1256 | if(sym != 0) { | |
1257 | sym_name = (char *)(strtab + symtab[sym].st_name); | |
1258 | //printf("Sym name =%s\n",sym_name); | |
1259 | sym_addr = NULL; | |
1260 | if ((sym_addr = get_hooked_symbol(sym_name)) != NULL) { | |
1261 | //printf("hooked symbol %s to %x\n", sym_name, sym_addr); | |
1262 | } | |
1263 | else | |
1264 | { | |
1265 | s = _do_lookup(si, sym_name, &base); | |
1266 | } | |
1267 | if(sym_addr != NULL) | |
1268 | { | |
1269 | } else | |
1270 | if(s == NULL) { | |
1271 | /* We only allow an undefined symbol if this is a weak | |
1272 | reference.. */ | |
1273 | s = &symtab[sym]; | |
1274 | if (ELF32_ST_BIND(s->st_info) != STB_WEAK) { | |
1275 | DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name); | |
1276 | return -1; | |
1277 | } | |
1278 | ||
1279 | /* IHI0044C AAELF 4.5.1.1: | |
1280 | ||
1281 | Libraries are not searched to resolve weak references. | |
1282 | It is not an error for a weak reference to remain | |
1283 | unsatisfied. | |
1284 | ||
1285 | During linking, the value of an undefined weak reference is: | |
1286 | - Zero if the relocation type is absolute | |
1287 | - The address of the place if the relocation is pc-relative | |
1288 | - The address of nominial base address if the relocation | |
1289 | type is base-relative. | |
1290 | */ | |
1291 | ||
1292 | switch (type) { | |
1293 | #if defined(ANDROID_ARM_LINKER) | |
1294 | case R_ARM_JUMP_SLOT: | |
1295 | case R_ARM_GLOB_DAT: | |
1296 | case R_ARM_ABS32: | |
1297 | case R_ARM_RELATIVE: /* Don't care. */ | |
1298 | case R_ARM_NONE: /* Don't care. */ | |
1299 | #elif defined(ANDROID_X86_LINKER) | |
1300 | case R_386_JUMP_SLOT: | |
1301 | case R_386_GLOB_DAT: | |
1302 | case R_386_32: | |
1303 | case R_386_RELATIVE: /* Dont' care. */ | |
1304 | #endif /* ANDROID_*_LINKER */ | |
1305 | /* sym_addr was initialized to be zero above or relocation | |
1306 | code below does not care about value of sym_addr. | |
1307 | No need to do anything. */ | |
1308 | break; | |
1309 | ||
1310 | #if defined(ANDROID_X86_LINKER) | |
1311 | case R_386_PC32: | |
1312 | sym_addr = reloc; | |
1313 | break; | |
1314 | #endif /* ANDROID_X86_LINKER */ | |
1315 | ||
1316 | #if defined(ANDROID_ARM_LINKER) | |
1317 | case R_ARM_COPY: | |
1318 | /* Fall through. Can't really copy if weak symbol is | |
1319 | not found in run-time. */ | |
1320 | #endif /* ANDROID_ARM_LINKER */ | |
1321 | default: | |
1322 | DL_ERR("%5d unknown weak reloc type %d @ %p (%d)\n", | |
1323 | pid, type, rel, (int) (rel - start)); | |
1324 | return -1; | |
1325 | } | |
1326 | } else { | |
1327 | /* We got a definition. */ | |
1328 | #if 0 | |
1329 | if((base == 0) && (si->base != 0)){ | |
1330 | /* linking from libraries to main image is bad */ | |
1331 | DL_ERR("%5d cannot locate '%s'...", | |
1332 | pid, strtab + symtab[sym].st_name); | |
1333 | return -1; | |
1334 | } | |
1335 | #endif | |
1336 | sym_addr = (unsigned)(s->st_value + base); | |
1337 | } | |
1338 | COUNT_RELOC(RELOC_SYMBOL); | |
1339 | } else { | |
1340 | s = NULL; | |
1341 | } | |
1342 | ||
1343 | /* TODO: This is ugly. Split up the relocations by arch into | |
1344 | * different files. | |
1345 | */ | |
1346 | switch(type){ | |
1347 | #if defined(ANDROID_ARM_LINKER) | |
1348 | case R_ARM_JUMP_SLOT: | |
1349 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1350 | MARK(rel->r_offset); | |
1351 | TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid, | |
1352 | reloc, sym_addr, sym_name); | |
1353 | *((unsigned*)reloc) = sym_addr; | |
1354 | break; | |
1355 | case R_ARM_GLOB_DAT: | |
1356 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1357 | MARK(rel->r_offset); | |
1358 | TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid, | |
1359 | reloc, sym_addr, sym_name); | |
1360 | *((unsigned*)reloc) = sym_addr; | |
1361 | break; | |
1362 | case R_ARM_ABS32: | |
1363 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1364 | MARK(rel->r_offset); | |
1365 | TRACE_TYPE(RELO, "%5d RELO ABS %08x <- %08x %s\n", pid, | |
1366 | reloc, sym_addr, sym_name); | |
1367 | *((unsigned*)reloc) += sym_addr; | |
1368 | break; | |
1369 | case R_ARM_REL32: | |
1370 | COUNT_RELOC(RELOC_RELATIVE); | |
1371 | MARK(rel->r_offset); | |
1372 | TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x - %08x %s\n", pid, | |
1373 | reloc, sym_addr, rel->r_offset, sym_name); | |
1374 | *((unsigned*)reloc) += sym_addr - rel->r_offset; | |
1375 | break; | |
1376 | #elif defined(ANDROID_X86_LINKER) | |
1377 | case R_386_JUMP_SLOT: | |
1378 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1379 | MARK(rel->r_offset); | |
1380 | TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid, | |
1381 | reloc, sym_addr, sym_name); | |
1382 | *((unsigned*)reloc) = sym_addr; | |
1383 | break; | |
1384 | case R_386_GLOB_DAT: | |
1385 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1386 | MARK(rel->r_offset); | |
1387 | TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid, | |
1388 | reloc, sym_addr, sym_name); | |
1389 | *((unsigned*)reloc) = sym_addr; | |
1390 | break; | |
1391 | #endif /* ANDROID_*_LINKER */ | |
1392 | ||
1393 | #if defined(ANDROID_ARM_LINKER) | |
1394 | case R_ARM_RELATIVE: | |
1395 | #elif defined(ANDROID_X86_LINKER) | |
1396 | case R_386_RELATIVE: | |
1397 | #endif /* ANDROID_*_LINKER */ | |
1398 | COUNT_RELOC(RELOC_RELATIVE); | |
1399 | MARK(rel->r_offset); | |
1400 | if(sym){ | |
1401 | DL_ERR("%5d odd RELATIVE form...", pid); | |
1402 | return -1; | |
1403 | } | |
1404 | TRACE_TYPE(RELO, "%5d RELO RELATIVE %08x <- +%08x\n", pid, | |
1405 | reloc, si->base); | |
1406 | *((unsigned*)reloc) += si->base; | |
1407 | break; | |
1408 | ||
1409 | #if defined(ANDROID_X86_LINKER) | |
1410 | case R_386_32: | |
1411 | COUNT_RELOC(RELOC_RELATIVE); | |
1412 | MARK(rel->r_offset); | |
1413 | ||
1414 | TRACE_TYPE(RELO, "%5d RELO R_386_32 %08x <- +%08x %s\n", pid, | |
1415 | reloc, sym_addr, sym_name); | |
1416 | *((unsigned *)reloc) += (unsigned)sym_addr; | |
1417 | break; | |
1418 | ||
1419 | case R_386_PC32: | |
1420 | COUNT_RELOC(RELOC_RELATIVE); | |
1421 | MARK(rel->r_offset); | |
1422 | TRACE_TYPE(RELO, "%5d RELO R_386_PC32 %08x <- " | |
1423 | "+%08x (%08x - %08x) %s\n", pid, reloc, | |
1424 | (sym_addr - reloc), sym_addr, reloc, sym_name); | |
1425 | *((unsigned *)reloc) += (unsigned)(sym_addr - reloc); | |
1426 | break; | |
1427 | #endif /* ANDROID_X86_LINKER */ | |
1428 | ||
1429 | #ifdef ANDROID_ARM_LINKER | |
1430 | case R_ARM_COPY: | |
1431 | COUNT_RELOC(RELOC_COPY); | |
1432 | MARK(rel->r_offset); | |
1433 | TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid, | |
1434 | reloc, s->st_size, sym_addr, sym_name); | |
1435 | memcpy((void*)reloc, (void*)sym_addr, s->st_size); | |
1436 | break; | |
1437 | case R_ARM_NONE: | |
1438 | break; | |
1439 | #endif /* ANDROID_ARM_LINKER */ | |
1440 | ||
1441 | default: | |
1442 | DL_ERR("%5d unknown reloc type %d @ %p (%d)", | |
1443 | pid, type, rel, (int) (rel - start)); | |
1444 | return -1; | |
1445 | } | |
1446 | rel++; | |
1447 | } | |
1448 | return 0; | |
1449 | } | |
1450 | ||
1451 | #if defined(ANDROID_SH_LINKER) | |
1452 | static int reloc_library_a(soinfo *si, Elf32_Rela *rela, unsigned count) | |
1453 | { | |
1454 | Elf32_Sym *symtab = si->symtab; | |
1455 | const char *strtab = si->strtab; | |
1456 | Elf32_Sym *s; | |
1457 | unsigned base; | |
1458 | Elf32_Rela *start = rela; | |
1459 | unsigned idx; | |
1460 | ||
1461 | for (idx = 0; idx < count; ++idx) { | |
1462 | unsigned type = ELF32_R_TYPE(rela->r_info); | |
1463 | unsigned sym = ELF32_R_SYM(rela->r_info); | |
1464 | unsigned reloc = (unsigned)(rela->r_offset + si->base); | |
1465 | unsigned sym_addr = 0; | |
1466 | char *sym_name = NULL; | |
1467 | ||
1468 | DEBUG("%5d Processing '%s' relocation at index %d\n", pid, | |
1469 | si->name, idx); | |
1470 | if(sym != 0) { | |
1471 | sym_name = (char *)(strtab + symtab[sym].st_name); | |
1472 | s = _do_lookup(si, sym_name, &base); | |
1473 | if(s == 0) { | |
1474 | DL_ERR("%5d cannot locate '%s'...", pid, sym_name); | |
1475 | return -1; | |
1476 | } | |
1477 | #if 0 | |
1478 | if((base == 0) && (si->base != 0)){ | |
1479 | /* linking from libraries to main image is bad */ | |
1480 | DL_ERR("%5d cannot locate '%s'...", | |
1481 | pid, strtab + symtab[sym].st_name); | |
1482 | return -1; | |
1483 | } | |
1484 | #endif | |
1485 | if ((s->st_shndx == SHN_UNDEF) && (s->st_value != 0)) { | |
1486 | DL_ERR("%5d In '%s', shndx=%d && value=0x%08x. We do not " | |
1487 | "handle this yet", pid, si->name, s->st_shndx, | |
1488 | s->st_value); | |
1489 | return -1; | |
1490 | } | |
1491 | sym_addr = (unsigned)(s->st_value + base); | |
1492 | COUNT_RELOC(RELOC_SYMBOL); | |
1493 | } else { | |
1494 | s = 0; | |
1495 | } | |
1496 | ||
1497 | /* TODO: This is ugly. Split up the relocations by arch into | |
1498 | * different files. | |
1499 | */ | |
1500 | switch(type){ | |
1501 | case R_SH_JUMP_SLOT: | |
1502 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1503 | MARK(rela->r_offset); | |
1504 | TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid, | |
1505 | reloc, sym_addr, sym_name); | |
1506 | *((unsigned*)reloc) = sym_addr; | |
1507 | break; | |
1508 | case R_SH_GLOB_DAT: | |
1509 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1510 | MARK(rela->r_offset); | |
1511 | TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid, | |
1512 | reloc, sym_addr, sym_name); | |
1513 | *((unsigned*)reloc) = sym_addr; | |
1514 | break; | |
1515 | case R_SH_DIR32: | |
1516 | COUNT_RELOC(RELOC_ABSOLUTE); | |
1517 | MARK(rela->r_offset); | |
1518 | TRACE_TYPE(RELO, "%5d RELO DIR32 %08x <- %08x %s\n", pid, | |
1519 | reloc, sym_addr, sym_name); | |
1520 | *((unsigned*)reloc) += sym_addr; | |
1521 | break; | |
1522 | case R_SH_RELATIVE: | |
1523 | COUNT_RELOC(RELOC_RELATIVE); | |
1524 | MARK(rela->r_offset); | |
1525 | if(sym){ | |
1526 | DL_ERR("%5d odd RELATIVE form...", pid); | |
1527 | return -1; | |
1528 | } | |
1529 | TRACE_TYPE(RELO, "%5d RELO RELATIVE %08x <- +%08x\n", pid, | |
1530 | reloc, si->base); | |
1531 | *((unsigned*)reloc) += si->base; | |
1532 | break; | |
1533 | ||
1534 | default: | |
1535 | DL_ERR("%5d unknown reloc type %d @ %p (%d)", | |
1536 | pid, type, rela, (int) (rela - start)); | |
1537 | return -1; | |
1538 | } | |
1539 | rela++; | |
1540 | } | |
1541 | return 0; | |
1542 | } | |
1543 | #endif /* ANDROID_SH_LINKER */ | |
1544 | ||
1545 | ||
1546 | /* Please read the "Initialization and Termination functions" functions. | |
1547 | * of the linker design note in bionic/linker/README.TXT to understand | |
1548 | * what the following code is doing. | |
1549 | * | |
1550 | * The important things to remember are: | |
1551 | * | |
1552 | * DT_PREINIT_ARRAY must be called first for executables, and should | |
1553 | * not appear in shared libraries. | |
1554 | * | |
1555 | * DT_INIT should be called before DT_INIT_ARRAY if both are present | |
1556 | * | |
1557 | * DT_FINI should be called after DT_FINI_ARRAY if both are present | |
1558 | * | |
1559 | * DT_FINI_ARRAY must be parsed in reverse order. | |
1560 | */ | |
1561 | ||
1562 | static void call_array(unsigned *ctor, int count, int reverse) | |
1563 | { | |
1564 | int n, inc = 1; | |
1565 | ||
1566 | if (reverse) { | |
1567 | ctor += (count-1); | |
1568 | inc = -1; | |
1569 | } | |
1570 | ||
1571 | for(n = count; n > 0; n--) { | |
1572 | TRACE("[ %5d Looking at %s *0x%08x == 0x%08x ]\n", pid, | |
1573 | reverse ? "dtor" : "ctor", | |
1574 | (unsigned)ctor, (unsigned)*ctor); | |
1575 | void (*func)() = (void (*)()) *ctor; | |
1576 | ctor += inc; | |
1577 | if(((int) func == 0) || ((int) func == -1)) continue; | |
1578 | TRACE("[ %5d Calling func @ 0x%08x ]\n", pid, (unsigned)func); | |
1579 | func(); | |
1580 | } | |
1581 | } | |
1582 | ||
1583 | static void call_constructors(soinfo *si) | |
1584 | { | |
1585 | #if 0 | |
1586 | if (strcmp(si->name,"libc.so") == 0) { | |
1587 | printf("=============> Skipping libc.so\n"); | |
1588 | return; | |
1589 | } | |
1590 | #endif | |
1591 | ||
1592 | if (si->flags & FLAG_EXE) { | |
1593 | TRACE("[ %5d Calling preinit_array @ 0x%08x [%d] for '%s' ]\n", | |
1594 | pid, (unsigned)si->preinit_array, si->preinit_array_count, | |
1595 | si->name); | |
1596 | call_array(si->preinit_array, si->preinit_array_count, 0); | |
1597 | TRACE("[ %5d Done calling preinit_array for '%s' ]\n", pid, si->name); | |
1598 | } else { | |
1599 | if (si->preinit_array) { | |
1600 | DL_ERR("%5d Shared library '%s' has a preinit_array table @ 0x%08x." | |
1601 | " This is INVALID.", pid, si->name, | |
1602 | (unsigned)si->preinit_array); | |
1603 | } | |
1604 | } | |
1605 | ||
1606 | if (si->init_func) { | |
1607 | TRACE("[ %5d Calling init_func @ 0x%08x for '%s' ]\n", pid, | |
1608 | (unsigned)si->init_func, si->name); | |
1609 | si->init_func(); | |
1610 | TRACE("[ %5d Done calling init_func for '%s' ]\n", pid, si->name); | |
1611 | } | |
1612 | ||
1613 | if (si->init_array) { | |
1614 | TRACE("[ %5d Calling init_array @ 0x%08x [%d] for '%s' ]\n", pid, | |
1615 | (unsigned)si->init_array, si->init_array_count, si->name); | |
1616 | call_array(si->init_array, si->init_array_count, 0); | |
1617 | TRACE("[ %5d Done calling init_array for '%s' ]\n", pid, si->name); | |
1618 | } | |
1619 | } | |
1620 | ||
1621 | ||
1622 | static void call_destructors(soinfo *si) | |
1623 | { | |
1624 | if (si->fini_array) { | |
1625 | TRACE("[ %5d Calling fini_array @ 0x%08x [%d] for '%s' ]\n", pid, | |
1626 | (unsigned)si->fini_array, si->fini_array_count, si->name); | |
1627 | call_array(si->fini_array, si->fini_array_count, 1); | |
1628 | TRACE("[ %5d Done calling fini_array for '%s' ]\n", pid, si->name); | |
1629 | } | |
1630 | ||
1631 | if (si->fini_func) { | |
1632 | TRACE("[ %5d Calling fini_func @ 0x%08x for '%s' ]\n", pid, | |
1633 | (unsigned)si->fini_func, si->name); | |
1634 | si->fini_func(); | |
1635 | TRACE("[ %5d Done calling fini_func for '%s' ]\n", pid, si->name); | |
1636 | } | |
1637 | } | |
1638 | ||
1639 | /* Force any of the closed stdin, stdout and stderr to be associated with | |
1640 | /dev/null. */ | |
1641 | static int nullify_closed_stdio (void) | |
1642 | { | |
1643 | int dev_null, i, status; | |
1644 | int return_value = 0; | |
1645 | ||
1646 | dev_null = open("/dev/null", O_RDWR); | |
1647 | if (dev_null < 0) { | |
1648 | DL_ERR("Cannot open /dev/null."); | |
1649 | return -1; | |
1650 | } | |
1651 | TRACE("[ %5d Opened /dev/null file-descriptor=%d]\n", pid, dev_null); | |
1652 | ||
1653 | /* If any of the stdio file descriptors is valid and not associated | |
1654 | with /dev/null, dup /dev/null to it. */ | |
1655 | for (i = 0; i < 3; i++) { | |
1656 | /* If it is /dev/null already, we are done. */ | |
1657 | if (i == dev_null) | |
1658 | continue; | |
1659 | ||
1660 | TRACE("[ %5d Nullifying stdio file descriptor %d]\n", pid, i); | |
1661 | /* The man page of fcntl does not say that fcntl(..,F_GETFL) | |
1662 | can be interrupted but we do this just to be safe. */ | |
1663 | do { | |
1664 | status = fcntl(i, F_GETFL); | |
1665 | } while (status < 0 && errno == EINTR); | |
1666 | ||
1667 | /* If file is openned, we are good. */ | |
1668 | if (status >= 0) | |
1669 | continue; | |
1670 | ||
1671 | /* The only error we allow is that the file descriptor does not | |
1672 | exist, in which case we dup /dev/null to it. */ | |
1673 | if (errno != EBADF) { | |
1674 | DL_ERR("nullify_stdio: unhandled error %s", strerror(errno)); | |
1675 | return_value = -1; | |
1676 | continue; | |
1677 | } | |
1678 | ||
1679 | /* Try dupping /dev/null to this stdio file descriptor and | |
1680 | repeat if there is a signal. Note that any errors in closing | |
1681 | the stdio descriptor are lost. */ | |
1682 | do { | |
1683 | status = dup2(dev_null, i); | |
1684 | } while (status < 0 && errno == EINTR); | |
1685 | ||
1686 | if (status < 0) { | |
1687 | DL_ERR("nullify_stdio: dup2 error %s", strerror(errno)); | |
1688 | return_value = -1; | |
1689 | continue; | |
1690 | } | |
1691 | } | |
1692 | ||
1693 | /* If /dev/null is not one of the stdio file descriptors, close it. */ | |
1694 | if (dev_null > 2) { | |
1695 | TRACE("[ %5d Closing /dev/null file-descriptor=%d]\n", pid, dev_null); | |
1696 | do { | |
1697 | status = close(dev_null); | |
1698 | } while (status < 0 && errno == EINTR); | |
1699 | ||
1700 | if (status < 0) { | |
1701 | DL_ERR("nullify_stdio: close error %s", strerror(errno)); | |
1702 | return_value = -1; | |
1703 | } | |
1704 | } | |
1705 | ||
1706 | return return_value; | |
1707 | } | |
1708 | ||
1709 | static int link_image(soinfo *si, unsigned wr_offset) | |
1710 | { | |
1711 | unsigned *d; | |
1712 | Elf32_Phdr *phdr = si->phdr; | |
1713 | int phnum = si->phnum; | |
1714 | ||
1715 | INFO("[ %5d linking %s ]\n", pid, si->name); | |
1716 | DEBUG("%5d si->base = 0x%08x si->flags = 0x%08x\n", pid, | |
1717 | si->base, si->flags); | |
1718 | ||
1719 | if (si->flags & FLAG_EXE) { | |
1720 | /* Locate the needed program segments (DYNAMIC/ARM_EXIDX) for | |
1721 | * linkage info if this is the executable. If this was a | |
1722 | * dynamic lib, that would have been done at load time. | |
1723 | * | |
1724 | * TODO: It's unfortunate that small pieces of this are | |
1725 | * repeated from the load_library routine. Refactor this just | |
1726 | * slightly to reuse these bits. | |
1727 | */ | |
1728 | si->size = 0; | |
1729 | for(; phnum > 0; --phnum, ++phdr) { | |
1730 | #ifdef ANDROID_ARM_LINKER | |
1731 | if(phdr->p_type == PT_ARM_EXIDX) { | |
1732 | /* exidx entries (used for stack unwinding) are 8 bytes each. | |
1733 | */ | |
1734 | si->ARM_exidx = (unsigned *)phdr->p_vaddr; | |
1735 | si->ARM_exidx_count = phdr->p_memsz / 8; | |
1736 | } | |
1737 | #endif | |
1738 | if (phdr->p_type == PT_LOAD) { | |
1739 | /* For the executable, we use the si->size field only in | |
1740 | dl_unwind_find_exidx(), so the meaning of si->size | |
1741 | is not the size of the executable; it is the last | |
1742 | virtual address of the loadable part of the executable; | |
1743 | since si->base == 0 for an executable, we use the | |
1744 | range [0, si->size) to determine whether a PC value | |
1745 | falls within the executable section. Of course, if | |
1746 | a value is below phdr->p_vaddr, it's not in the | |
1747 | executable section, but a) we shouldn't be asking for | |
1748 | such a value anyway, and b) if we have to provide | |
1749 | an EXIDX for such a value, then the executable's | |
1750 | EXIDX is probably the better choice. | |
1751 | */ | |
1752 | DEBUG_DUMP_PHDR(phdr, "PT_LOAD", pid); | |
1753 | if (phdr->p_vaddr + phdr->p_memsz > si->size) | |
1754 | si->size = phdr->p_vaddr + phdr->p_memsz; | |
1755 | /* try to remember what range of addresses should be write | |
1756 | * protected */ | |
1757 | if (!(phdr->p_flags & PF_W)) { | |
1758 | unsigned _end; | |
1759 | ||
1760 | if (phdr->p_vaddr < si->wrprotect_start) | |
1761 | si->wrprotect_start = phdr->p_vaddr; | |
1762 | _end = (((phdr->p_vaddr + phdr->p_memsz + PAGE_SIZE - 1) & | |
1763 | (~PAGE_MASK))); | |
1764 | if (_end > si->wrprotect_end) | |
1765 | si->wrprotect_end = _end; | |
1766 | } | |
1767 | } else if (phdr->p_type == PT_DYNAMIC) { | |
1768 | if (si->dynamic != (unsigned *)-1) { | |
1769 | DL_ERR("%5d multiple PT_DYNAMIC segments found in '%s'. " | |
1770 | "Segment at 0x%08x, previously one found at 0x%08x", | |
1771 | pid, si->name, si->base + phdr->p_vaddr, | |
1772 | (unsigned)si->dynamic); | |
1773 | goto fail; | |
1774 | } | |
1775 | DEBUG_DUMP_PHDR(phdr, "PT_DYNAMIC", pid); | |
1776 | si->dynamic = (unsigned *) (si->base + phdr->p_vaddr); | |
1777 | } | |
1778 | } | |
1779 | } | |
1780 | ||
1781 | if (si->dynamic == (unsigned *)-1) { | |
1782 | DL_ERR("%5d missing PT_DYNAMIC?!", pid); | |
1783 | goto fail; | |
1784 | } | |
1785 | ||
1786 | DEBUG("%5d dynamic = %p\n", pid, si->dynamic); | |
1787 | ||
1788 | /* extract useful information from dynamic section */ | |
1789 | for(d = si->dynamic; *d; d++){ | |
1790 | DEBUG("%5d d = %p, d[0] = 0x%08x d[1] = 0x%08x\n", pid, d, d[0], d[1]); | |
1791 | switch(*d++){ | |
1792 | case DT_HASH: | |
1793 | si->nbucket = ((unsigned *) (si->base + *d))[0]; | |
1794 | si->nchain = ((unsigned *) (si->base + *d))[1]; | |
1795 | si->bucket = (unsigned *) (si->base + *d + 8); | |
1796 | si->chain = (unsigned *) (si->base + *d + 8 + si->nbucket * 4); | |
1797 | break; | |
1798 | case DT_STRTAB: | |
1799 | si->strtab = (const char *) (si->base + *d); | |
1800 | break; | |
1801 | case DT_SYMTAB: | |
1802 | si->symtab = (Elf32_Sym *) (si->base + *d); | |
1803 | break; | |
1804 | #if !defined(ANDROID_SH_LINKER) | |
1805 | case DT_PLTREL: | |
1806 | if(*d != DT_REL) { | |
1807 | DL_ERR("DT_RELA not supported"); | |
1808 | goto fail; | |
1809 | } | |
1810 | break; | |
1811 | #endif | |
1812 | #ifdef ANDROID_SH_LINKER | |
1813 | case DT_JMPREL: | |
1814 | si->plt_rela = (Elf32_Rela*) (si->base + *d); | |
1815 | break; | |
1816 | case DT_PLTRELSZ: | |
1817 | si->plt_rela_count = *d / sizeof(Elf32_Rela); | |
1818 | break; | |
1819 | #else | |
1820 | case DT_JMPREL: | |
1821 | si->plt_rel = (Elf32_Rel*) (si->base + *d); | |
1822 | break; | |
1823 | case DT_PLTRELSZ: | |
1824 | si->plt_rel_count = *d / 8; | |
1825 | break; | |
1826 | #endif | |
1827 | case DT_REL: | |
1828 | si->rel = (Elf32_Rel*) (si->base + *d); | |
1829 | break; | |
1830 | case DT_RELSZ: | |
1831 | si->rel_count = *d / 8; | |
1832 | break; | |
1833 | #ifdef ANDROID_SH_LINKER | |
1834 | case DT_RELASZ: | |
1835 | si->rela_count = *d / sizeof(Elf32_Rela); | |
1836 | break; | |
1837 | #endif | |
1838 | case DT_PLTGOT: | |
1839 | /* Save this in case we decide to do lazy binding. We don't yet. */ | |
1840 | si->plt_got = (unsigned *)(si->base + *d); | |
1841 | break; | |
1842 | case DT_DEBUG: | |
1843 | // Set the DT_DEBUG entry to the addres of _r_debug for GDB | |
1844 | *d = (int) &_r_debug; | |
1845 | break; | |
1846 | #ifdef ANDROID_SH_LINKER | |
1847 | case DT_RELA: | |
1848 | si->rela = (Elf32_Rela *) (si->base + *d); | |
1849 | break; | |
1850 | #else | |
1851 | case DT_RELA: | |
1852 | DL_ERR("%5d DT_RELA not supported", pid); | |
1853 | goto fail; | |
1854 | #endif | |
1855 | case DT_INIT: | |
1856 | si->init_func = (void (*)(void))(si->base + *d); | |
1857 | DEBUG("%5d %s constructors (init func) found at %p\n", | |
1858 | pid, si->name, si->init_func); | |
1859 | break; | |
1860 | case DT_FINI: | |
1861 | si->fini_func = (void (*)(void))(si->base + *d); | |
1862 | DEBUG("%5d %s destructors (fini func) found at %p\n", | |
1863 | pid, si->name, si->fini_func); | |
1864 | break; | |
1865 | case DT_INIT_ARRAY: | |
1866 | si->init_array = (unsigned *)(si->base + *d); | |
1867 | DEBUG("%5d %s constructors (init_array) found at %p\n", | |
1868 | pid, si->name, si->init_array); | |
1869 | break; | |
1870 | case DT_INIT_ARRAYSZ: | |
1871 | si->init_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
1872 | break; | |
1873 | case DT_FINI_ARRAY: | |
1874 | si->fini_array = (unsigned *)(si->base + *d); | |
1875 | DEBUG("%5d %s destructors (fini_array) found at %p\n", | |
1876 | pid, si->name, si->fini_array); | |
1877 | break; | |
1878 | case DT_FINI_ARRAYSZ: | |
1879 | si->fini_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
1880 | break; | |
1881 | case DT_PREINIT_ARRAY: | |
1882 | si->preinit_array = (unsigned *)(si->base + *d); | |
1883 | DEBUG("%5d %s constructors (preinit_array) found at %p\n", | |
1884 | pid, si->name, si->preinit_array); | |
1885 | break; | |
1886 | case DT_PREINIT_ARRAYSZ: | |
1887 | si->preinit_array_count = ((unsigned)*d) / sizeof(Elf32_Addr); | |
1888 | break; | |
1889 | case DT_TEXTREL: | |
1890 | /* TODO: make use of this. */ | |
1891 | /* this means that we might have to write into where the text | |
1892 | * segment was loaded during relocation... Do something with | |
1893 | * it. | |
1894 | */ | |
1895 | DEBUG("%5d Text segment should be writable during relocation.\n", | |
1896 | pid); | |
1897 | break; | |
1898 | } | |
1899 | } | |
1900 | ||
1901 | DEBUG("%5d si->base = 0x%08x, si->strtab = %p, si->symtab = %p\n", | |
1902 | pid, si->base, si->strtab, si->symtab); | |
1903 | ||
1904 | if((si->strtab == 0) || (si->symtab == 0)) { | |
1905 | DL_ERR("%5d missing essential tables", pid); | |
1906 | goto fail; | |
1907 | } | |
1908 | ||
1909 | /* if this is the main executable, then load all of the preloads now */ | |
1910 | if(si->flags & FLAG_EXE) { | |
1911 | int i; | |
1912 | memset(preloads, 0, sizeof(preloads)); | |
1913 | for(i = 0; ldpreload_names[i] != NULL; i++) { | |
1914 | soinfo *lsi = find_library(ldpreload_names[i]); | |
1915 | if(lsi == 0) { | |
1916 | strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf)); | |
1917 | DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", | |
1918 | pid, ldpreload_names[i], si->name, tmp_err_buf); | |
1919 | goto fail; | |
1920 | } | |
1921 | lsi->refcount++; | |
1922 | preloads[i] = lsi; | |
1923 | } | |
1924 | } | |
1925 | ||
1926 | for(d = si->dynamic; *d; d += 2) { | |
1927 | if(d[0] == DT_NEEDED){ | |
1928 | DEBUG("%5d %s needs %s\n", pid, si->name, si->strtab + d[1]); | |
1929 | soinfo *lsi = find_library(si->strtab + d[1]); | |
1930 | if(lsi == 0) { | |
1931 | strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf)); | |
1932 | DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", | |
1933 | pid, si->strtab + d[1], si->name, tmp_err_buf); | |
1934 | goto fail; | |
1935 | } | |
1936 | /* Save the soinfo of the loaded DT_NEEDED library in the payload | |
1937 | of the DT_NEEDED entry itself, so that we can retrieve the | |
1938 | soinfo directly later from the dynamic segment. This is a hack, | |
1939 | but it allows us to map from DT_NEEDED to soinfo efficiently | |
1940 | later on when we resolve relocations, trying to look up a symgol | |
1941 | with dlsym(). | |
1942 | */ | |
1943 | d[1] = (unsigned)lsi; | |
1944 | lsi->refcount++; | |
1945 | } | |
1946 | } | |
1947 | ||
1948 | if(si->plt_rel) { | |
1949 | DEBUG("[ %5d relocating %s plt ]\n", pid, si->name ); | |
1950 | if(reloc_library(si, si->plt_rel, si->plt_rel_count)) | |
1951 | goto fail; | |
1952 | } | |
1953 | if(si->rel) { | |
1954 | DEBUG("[ %5d relocating %s ]\n", pid, si->name ); | |
1955 | if(reloc_library(si, si->rel, si->rel_count)) | |
1956 | goto fail; | |
1957 | } | |
1958 | ||
1959 | #ifdef ANDROID_SH_LINKER | |
1960 | if(si->plt_rela) { | |
1961 | DEBUG("[ %5d relocating %s plt ]\n", pid, si->name ); | |
1962 | if(reloc_library_a(si, si->plt_rela, si->plt_rela_count)) | |
1963 | goto fail; | |
1964 | } | |
1965 | if(si->rela) { | |
1966 | DEBUG("[ %5d relocating %s ]\n", pid, si->name ); | |
1967 | if(reloc_library_a(si, si->rela, si->rela_count)) | |
1968 | goto fail; | |
1969 | } | |
1970 | #endif /* ANDROID_SH_LINKER */ | |
1971 | ||
1972 | si->flags |= FLAG_LINKED; | |
1973 | DEBUG("[ %5d finished linking %s ]\n", pid, si->name); | |
1974 | ||
1975 | #if 0 | |
1976 | /* This is the way that the old dynamic linker did protection of | |
1977 | * non-writable areas. It would scan section headers and find where | |
1978 | * .text ended (rather where .data/.bss began) and assume that this is | |
1979 | * the upper range of the non-writable area. This is too coarse, | |
1980 | * and is kept here for reference until we fully move away from single | |
1981 | * segment elf objects. See the code in get_wr_offset (also #if'd 0) | |
1982 | * that made this possible. | |
1983 | */ | |
1984 | if(wr_offset < 0xffffffff){ | |
1985 | mprotect((void*) si->base, wr_offset, PROT_READ | PROT_EXEC); | |
1986 | } | |
1987 | #else | |
1988 | /* TODO: Verify that this does the right thing in all cases, as it | |
1989 | * presently probably does not. It is possible that an ELF image will | |
1990 | * come with multiple read-only segments. What we ought to do is scan | |
1991 | * the program headers again and mprotect all the read-only segments. | |
1992 | * To prevent re-scanning the program header, we would have to build a | |
1993 | * list of loadable segments in si, and then scan that instead. */ | |
1994 | if (si->wrprotect_start != 0xffffffff && si->wrprotect_end != 0) { | |
1995 | mprotect((void *)si->wrprotect_start, | |
1996 | si->wrprotect_end - si->wrprotect_start, | |
1997 | PROT_READ | PROT_EXEC); | |
1998 | } | |
1999 | #endif | |
2000 | ||
2001 | /* If this is a SET?ID program, dup /dev/null to opened stdin, | |
2002 | stdout and stderr to close a security hole described in: | |
2003 | ||
2004 | ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc | |
2005 | ||
2006 | */ | |
2007 | if (program_is_setuid) | |
2008 | nullify_closed_stdio (); | |
2009 | notify_gdb_of_load(si); | |
2010 | call_constructors(si); | |
2011 | return 0; | |
2012 | ||
2013 | fail: | |
2014 | ERROR("failed to link %s\n", si->name); | |
2015 | si->flags |= FLAG_ERROR; | |
2016 | return -1; | |
2017 | } | |
2018 | ||
2019 | static void parse_library_path(const char *path, char *delim) | |
2020 | { | |
2021 | size_t len; | |
2022 | char *ldpaths_bufp = ldpaths_buf; | |
2023 | int i = 0; | |
2024 | ||
2025 | len = strlcpy(ldpaths_buf, path, sizeof(ldpaths_buf)); | |
2026 | ||
2027 | while (i < LDPATH_MAX && (ldpaths[i] = strsep(&ldpaths_bufp, delim))) { | |
2028 | if (*ldpaths[i] != '\0') | |
2029 | ++i; | |
2030 | } | |
2031 | ||
2032 | /* Forget the last path if we had to truncate; this occurs if the 2nd to | |
2033 | * last char isn't '\0' (i.e. not originally a delim). */ | |
2034 | if (i > 0 && len >= sizeof(ldpaths_buf) && | |
2035 | ldpaths_buf[sizeof(ldpaths_buf) - 2] != '\0') { | |
2036 | ldpaths[i - 1] = NULL; | |
2037 | } else { | |
2038 | ldpaths[i] = NULL; | |
2039 | } | |
2040 | } | |
2041 | ||
2042 | static void parse_preloads(const char *path, char *delim) | |
2043 | { | |
2044 | size_t len; | |
2045 | char *ldpreloads_bufp = ldpreloads_buf; | |
2046 | int i = 0; | |
2047 | ||
2048 | len = strlcpy(ldpreloads_buf, path, sizeof(ldpreloads_buf)); | |
2049 | ||
2050 | while (i < LDPRELOAD_MAX && (ldpreload_names[i] = strsep(&ldpreloads_bufp, delim))) { | |
2051 | if (*ldpreload_names[i] != '\0') { | |
2052 | ++i; | |
2053 | } | |
2054 | } | |
2055 | ||
2056 | /* Forget the last path if we had to truncate; this occurs if the 2nd to | |
2057 | * last char isn't '\0' (i.e. not originally a delim). */ | |
2058 | if (i > 0 && len >= sizeof(ldpreloads_buf) && | |
2059 | ldpreloads_buf[sizeof(ldpreloads_buf) - 2] != '\0') { | |
2060 | ldpreload_names[i - 1] = NULL; | |
2061 | } else { | |
2062 | ldpreload_names[i] = NULL; | |
2063 | } | |
2064 | } | |
2065 | ||
2066 | int main(int argc, char **argv) | |
2067 | { | |
2068 | return 0; | |
2069 | } | |
2070 | ||
2071 | #define ANDROID_TLS_SLOTS BIONIC_TLS_SLOTS | |
2072 | ||
2073 | static void * __tls_area[ANDROID_TLS_SLOTS]; | |
2074 | ||
2075 | unsigned __linker_init(unsigned **elfdata) | |
2076 | { | |
2077 | static soinfo linker_soinfo; | |
2078 | ||
2079 | int argc = (int) *elfdata; | |
2080 | char **argv = (char**) (elfdata + 1); | |
2081 | unsigned *vecs = (unsigned*) (argv + argc + 1); | |
2082 | soinfo *si; | |
2083 | struct link_map * map; | |
2084 | const char *ldpath_env = NULL; | |
2085 | const char *ldpreload_env = NULL; | |
2086 | ||
2087 | /* Setup a temporary TLS area that is used to get a working | |
2088 | * errno for system calls. | |
2089 | */ | |
2090 | //__set_tls(__tls_area); | |
2091 | ||
2092 | pid = getpid(); | |
2093 | ||
2094 | #if TIMING | |
2095 | struct timeval t0, t1; | |
2096 | gettimeofday(&t0, 0); | |
2097 | #endif | |
2098 | ||
2099 | /* NOTE: we store the elfdata pointer on a special location | |
2100 | * of the temporary TLS area in order to pass it to | |
2101 | * the C Library's runtime initializer. | |
2102 | * | |
2103 | * The initializer must clear the slot and reset the TLS | |
2104 | * to point to a different location to ensure that no other | |
2105 | * shared library constructor can access it. | |
2106 | */ | |
2107 | #if 0 | |
2108 | __libc_init_tls(elfdata); | |
2109 | #endif | |
2110 | ||
2111 | pid = getpid(); | |
2112 | ||
2113 | #if TIMING | |
2114 | struct timeval t0, t1; | |
2115 | gettimeofday(&t0, 0); | |
2116 | #endif | |
2117 | ||
2118 | /* Initialize environment functions, and get to the ELF aux vectors table */ | |
2119 | vecs = linker_env_init(vecs); | |
2120 | ||
2121 | /* Sanitize environment if we're loading a setuid program */ | |
2122 | if (program_is_setuid) | |
2123 | linker_env_secure(); | |
2124 | ||
2125 | //debugger_init(); | |
2126 | ||
2127 | /* Get a few environment variables */ | |
2128 | { | |
2129 | const char* env; | |
2130 | env = linker_env_get("DEBUG"); /* XXX: TODO: Change to LD_DEBUG */ | |
2131 | if (env) | |
2132 | debug_verbosity = atoi(env); | |
2133 | ||
2134 | /* Normally, these are cleaned by linker_env_secure, but the test | |
2135 | * against program_is_setuid doesn't cost us anything */ | |
2136 | if (!program_is_setuid) { | |
2137 | ldpath_env = linker_env_get("LD_LIBRARY_PATH"); | |
2138 | ldpreload_env = linker_env_get("LD_PRELOAD"); | |
2139 | } | |
2140 | } | |
2141 | ||
2142 | INFO("[ android linker & debugger ]\n"); | |
2143 | DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata); | |
2144 | ||
2145 | si = alloc_info(argv[0]); | |
2146 | if(si == 0) { | |
2147 | exit(-1); | |
2148 | } | |
2149 | ||
2150 | /* bootstrap the link map, the main exe always needs to be first */ | |
2151 | si->flags |= FLAG_EXE; | |
2152 | map = &(si->linkmap); | |
2153 | ||
2154 | map->l_addr = 0; | |
2155 | map->l_name = argv[0]; | |
2156 | map->l_prev = NULL; | |
2157 | map->l_next = NULL; | |
2158 | ||
2159 | _r_debug.r_map = map; | |
2160 | r_debug_tail = map; | |
2161 | ||
2162 | /* gdb expects the linker to be in the debug shared object list, | |
2163 | * and we need to make sure that the reported load address is zero. | |
2164 | * Without this, gdb gets the wrong idea of where rtld_db_dlactivity() | |
2165 | * is. Don't use alloc_info(), because the linker shouldn't | |
2166 | * be on the soinfo list. | |
2167 | */ | |
2168 | strlcpy((char*) linker_soinfo.name, "/system/bin/linker", sizeof linker_soinfo.name); | |
2169 | linker_soinfo.flags = 0; | |
2170 | linker_soinfo.base = 0; // This is the important part; must be zero. | |
2171 | insert_soinfo_into_debug_map(&linker_soinfo); | |
2172 | ||
2173 | /* extract information passed from the kernel */ | |
2174 | while(vecs[0] != 0){ | |
2175 | switch(vecs[0]){ | |
2176 | case AT_PHDR: | |
2177 | si->phdr = (Elf32_Phdr*) vecs[1]; | |
2178 | break; | |
2179 | case AT_PHNUM: | |
2180 | si->phnum = (int) vecs[1]; | |
2181 | break; | |
2182 | case AT_ENTRY: | |
2183 | si->entry = vecs[1]; | |
2184 | break; | |
2185 | } | |
2186 | vecs += 2; | |
2187 | } | |
2188 | ||
2189 | si->base = 0; | |
2190 | si->dynamic = (unsigned *)-1; | |
2191 | si->wrprotect_start = 0xffffffff; | |
2192 | si->wrprotect_end = 0; | |
2193 | si->refcount = 1; | |
2194 | ||
2195 | /* Use LD_LIBRARY_PATH if we aren't setuid/setgid */ | |
2196 | if (ldpath_env) | |
2197 | parse_library_path(ldpath_env, ":"); | |
2198 | ||
2199 | if (ldpreload_env) { | |
2200 | parse_preloads(ldpreload_env, " :"); | |
2201 | } | |
2202 | ||
2203 | if(link_image(si, 0)) { | |
2204 | char errmsg[] = "CANNOT LINK EXECUTABLE\n"; | |
2205 | write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf)); | |
2206 | write(2, errmsg, sizeof(errmsg)); | |
2207 | exit(-1); | |
2208 | } | |
2209 | ||
2210 | #if ALLOW_SYMBOLS_FROM_MAIN | |
2211 | /* Set somain after we've loaded all the libraries in order to prevent | |
2212 | * linking of symbols back to the main image, which is not set up at that | |
2213 | * point yet. | |
2214 | */ | |
2215 | somain = si; | |
2216 | #endif | |
2217 | ||
2218 | #if TIMING | |
2219 | gettimeofday(&t1,NULL); | |
2220 | PRINT("LINKER TIME: %s: %d microseconds\n", argv[0], (int) ( | |
2221 | (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - | |
2222 | (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec) | |
2223 | )); | |
2224 | #endif | |
2225 | #if STATS | |
2226 | PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol\n", argv[0], | |
2227 | linker_stats.reloc[RELOC_ABSOLUTE], | |
2228 | linker_stats.reloc[RELOC_RELATIVE], | |
2229 | linker_stats.reloc[RELOC_COPY], | |
2230 | linker_stats.reloc[RELOC_SYMBOL]); | |
2231 | #endif | |
2232 | #if COUNT_PAGES | |
2233 | { | |
2234 | unsigned n; | |
2235 | unsigned i; | |
2236 | unsigned count = 0; | |
2237 | for(n = 0; n < 4096; n++){ | |
2238 | if(bitmask[n]){ | |
2239 | unsigned x = bitmask[n]; | |
2240 | for(i = 0; i < 8; i++){ | |
2241 | if(x & 1) count++; | |
2242 | x >>= 1; | |
2243 | } | |
2244 | } | |
2245 | } | |
2246 | PRINT("PAGES MODIFIED: %s: %d (%dKB)\n", argv[0], count, count * 4); | |
2247 | } | |
2248 | #endif | |
2249 | ||
2250 | #if TIMING || STATS || COUNT_PAGES | |
2251 | fflush(stdout); | |
2252 | #endif | |
2253 | ||
2254 | TRACE("[ %5d Ready to execute '%s' @ 0x%08x ]\n", pid, si->name, | |
2255 | si->entry); | |
2256 | return si->entry; | |
2257 | } |