1 /* vi: set sw=4 ts=4: */
3 * Program to load an ELF binary on a linux system, and run it
4 * after resolving ELF shared library symbols
6 * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org>
7 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
8 * David Engel, Hongjiu Lu and Mitch D'Souza
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the above contributors may not be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #define ALLOW_ZERO_PLTGOT
37 /* Pull in the value of _dl_progname */
38 #include "dl-progname.h"
40 /* Global variables used within the shared library loader */
41 char *_dl_library_path = 0; /* Where we look for libraries */
42 char *_dl_preload = 0; /* Things to be loaded before the libs */
43 char *_dl_ldsopath = 0; /* Location of the shared lib loader */
44 int _dl_secure = 1; /* Are we dealing with setuid stuff? */
45 int _dl_errno = 0; /* We can't use the real errno in ldso */
46 size_t _dl_pagesize = 0; /* Store the page size for use later */
47 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
51 #ifdef __SUPPORT_LD_DEBUG__
53 char *_dl_debug_symbols = 0;
54 char *_dl_debug_move = 0;
55 char *_dl_debug_reloc = 0;
56 char *_dl_debug_detail = 0;
57 char *_dl_debug_nofixups = 0;
58 char *_dl_debug_bindings = 0;
59 int _dl_debug_file = 2;
62 /* Forward function declarations */
63 static int _dl_suid_ok(void);
66 * This stub function is used by some debuggers. The idea is that they
67 * can set an internal breakpoint on it, so that we are notified when the
68 * address mapping is changed in some way.
70 void _dl_debug_state(void)
74 static unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */
75 static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */
79 #if defined (__SUPPORT_LD_DEBUG__)
80 static void debug_fini (int status, void *arg)
83 _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
87 void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
88 Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, char **argv)
93 int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
95 struct elf_resolve *tcurr;
96 struct elf_resolve *tpnt1;
97 struct elf_resolve app_tpnt_tmp;
98 struct elf_resolve *app_tpnt = &app_tpnt_tmp;
99 struct r_debug *debug_addr;
100 unsigned long brk_addr, *lpnt;
101 int (*_dl_atexit) (void *);
102 #if defined (__SUPPORT_LD_DEBUG__)
103 int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
106 #ifdef __SUPPORT_LD_DEBUG_EARLY__
108 SEND_STDERR("Cool, we managed to make a function call.\n");
111 /* Store the page size for later use */
112 _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
113 /* Make it so _dl_malloc can use the page of memory we have already
114 * allocated. We shouldn't need to grab any more memory. This must
115 * be first since things like _dl_dprintf() use _dl_malloc().... */
116 _dl_malloc_addr = (unsigned char *)_dl_pagesize;
120 /* Now we have done the mandatory linking of some things. We are now
121 * free to start using global variables, since these things have all been
122 * fixed up by now. Still no function calls outside of this library ,
123 * since the dynamic resolver is not yet ready. */
125 _dl_progname = argv[0];
128 /* Start to build the tables of the modules that are required for
129 * this beast to run. We start with the basic executable, and then
130 * go from there. Eventually we will run across ourself, and we
131 * will need to properly deal with that as well. */
137 epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
138 tpnt->n_phent = epnt->e_phnum;
139 tpnt->ppnt = myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
140 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
141 if (myppnt->p_type == PT_DYNAMIC) {
142 tpnt->dynamic_addr = (ElfW(Dyn) *)(myppnt->p_vaddr + load_addr);
143 tpnt->dynamic_size = myppnt->p_filesz;
150 if (_dl_getenv("LD_BIND_NOW", envp))
153 /* At this point we are now free to examine the user application,
154 and figure out which libraries are supposed to be called. Until
155 we have this list, we will not be completely ready for dynamic linking */
157 /* Find the runtime load address of the main executable, this may be
158 * different from what the ELF header says for ET_DYN/PIE executables.
162 ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
163 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
164 if (ppnt->p_type == PT_PHDR) {
165 app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
169 #ifdef __SUPPORT_LD_DEBUG_EARLY__
170 if (app_tpnt->loadaddr) {
171 SEND_STDERR("Position Independent Executable: app_tpnt->loadaddr=");
172 SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
177 * This is used by gdb to locate the chain of shared libraries that are currently loaded.
179 debug_addr = _dl_malloc(sizeof(struct r_debug));
180 _dl_memset(debug_addr, 0, sizeof(struct r_debug));
182 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
183 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
184 if (ppnt->p_type == PT_LOAD) {
185 if (ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz > brk_addr)
186 brk_addr = ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz;
188 if (ppnt->p_type == PT_DYNAMIC) {
189 dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
190 while (dpnt->d_tag) {
191 #if defined(__mips__)
192 if (dpnt->d_tag == DT_MIPS_GOTSYM)
193 app_tpnt->mips_gotsym =
194 (unsigned long) dpnt->d_un.d_val;
195 if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
196 app_tpnt->mips_local_gotno =
197 (unsigned long) dpnt->d_un.d_val;
198 if (dpnt->d_tag == DT_MIPS_SYMTABNO)
199 app_tpnt->mips_symtabno =
200 (unsigned long) dpnt->d_un.d_val;
201 if (dpnt->d_tag > DT_JMPREL) {
205 app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
207 if (dpnt->d_tag == DT_DEBUG) {
208 /* Allow writing debug_addr into the .dynamic segment.
209 * Even though the program header is marked RWE, the kernel gives
212 Elf32_Addr mpa = (ppnt->p_vaddr + app_tpnt->loadaddr) & ~(_dl_pagesize - 1);
213 Elf32_Word mps = ((ppnt->p_vaddr + app_tpnt->loadaddr) - mpa) + ppnt->p_memsz;
214 if(_dl_mprotect(mpa, mps, PROT_READ | PROT_WRITE | PROT_EXEC)) {
215 SEND_STDERR("Couldn't mprotect .dynamic segment to rwx.\n");
218 dpnt->d_un.d_val = (unsigned long) debug_addr;
221 if (dpnt->d_tag > DT_JMPREL) {
225 app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
226 if (dpnt->d_tag == DT_DEBUG) {
227 dpnt->d_un.d_val = (unsigned long) debug_addr;
230 if (dpnt->d_tag == DT_TEXTREL)
231 app_tpnt->dynamic_info[DT_TEXTREL] = 1;
234 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
235 /* Ugly, ugly. We need to call mprotect to change the protection of
236 the text pages so that we can do the dynamic linking. We can set the
237 protection back again once we are done */
238 #ifdef __SUPPORT_LD_DEBUG_EARLY__
239 SEND_STDERR("calling mprotect on the application program\n");
241 /* Now cover the application program. */
242 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
243 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
244 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
245 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
246 _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
247 ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
248 (unsigned long) ppnt->p_filesz,
249 PROT_READ | PROT_WRITE | PROT_EXEC);
254 #ifndef ALLOW_ZERO_PLTGOT
255 /* make sure it's really there. */
256 if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
259 /* OK, we have what we need - slip this one into the list. */
260 app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr,
261 app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
262 _dl_loaded_modules->libtype = elf_executable;
263 _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
264 _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
265 _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
266 _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
267 rpnt->dyn = _dl_loaded_modules;
268 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
269 app_tpnt->usage_count++;
270 app_tpnt->symbol_scope = _dl_symbol_tables;
271 lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT] + app_tpnt->loadaddr);
272 #ifdef ALLOW_ZERO_PLTGOT
275 INIT_GOT(lpnt, _dl_loaded_modules);
278 /* OK, fill this in - we did not have this before */
279 if (ppnt->p_type == PT_INTERP) {
281 char *pnt, *pnt1, buf[1024];
282 tpnt->libname = _dl_strdup((char *) ppnt->p_offset +
283 (auxvt[AT_PHDR].a_un.a_val & PAGE_ALIGN));
285 /* Determine if the shared lib loader is a symlink */
286 _dl_memset(buf, 0, sizeof(buf));
287 readsize = _dl_readlink(tpnt->libname, buf, sizeof(buf));
288 if (readsize > 0 && readsize < (int)(sizeof(buf)-1)) {
289 pnt1 = _dl_strrchr(buf, '/');
290 if (pnt1 && buf != pnt1) {
291 #ifdef __SUPPORT_LD_DEBUG_EARLY__
292 _dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
294 tpnt->libname = _dl_strdup(buf);
298 /* Store the path where the shared lib loader was found for
300 pnt = _dl_strdup(tpnt->libname);
301 pnt1 = _dl_strrchr(pnt, '/');
306 _dl_ldsopath = tpnt->libname;
308 #ifdef __SUPPORT_LD_DEBUG_EARLY__
309 _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
314 /* Now we need to figure out what kind of options are selected.
315 Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */
317 if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
318 (auxvt[AT_UID].a_un.a_val != -1 &&
319 auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val
320 && auxvt[AT_GID].a_un.a_val== auxvt[AT_EGID].a_un.a_val)) {
322 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
323 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
326 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
327 _dl_unsetenv("LD_AOUT_PRELOAD", envp);
328 _dl_unsetenv("LD_LIBRARY_PATH", envp);
329 _dl_unsetenv("LD_AOUT_LIBRARY_PATH", envp);
330 _dl_library_path = NULL;
334 #ifdef __SUPPORT_LD_DEBUG__
335 _dl_debug = _dl_getenv("LD_DEBUG", envp);
338 if (_dl_strstr(_dl_debug, "all")) {
339 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
340 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = _dl_strstr(_dl_debug, "all");
343 _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
344 _dl_debug_move = _dl_strstr(_dl_debug, "move");
345 _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
346 _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
347 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
348 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
352 const char *dl_debug_output;
354 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
358 char tmp[22], *tmp1, *filename;
361 _dl_memset(tmp, 0, sizeof(tmp));
362 tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
364 len1 = _dl_strlen(dl_debug_output);
365 len2 = _dl_strlen(tmp1);
367 filename = _dl_malloc(len1+len2+2);
371 _dl_strcpy (filename, dl_debug_output);
372 filename[len1] = '.';
373 _dl_strcpy (&filename[len1+1], tmp1);
375 _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644);
376 if (_dl_debug_file<0)
379 _dl_dprintf (2, "can't open file: '%s'\n",filename);
387 if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
388 trace_loaded_objects++;
390 #ifndef __LDSO_LDD_SUPPORT__
391 if (trace_loaded_objects) {
392 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
398 * OK, fix one more thing - set up debug_addr so it will point
399 * to our chain. Later we may need to fill in more fields, but this
400 * should be enough for now.
402 debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
403 debug_addr->r_version = 1;
404 debug_addr->r_ldbase = load_addr;
405 debug_addr->r_brk = (unsigned long) &_dl_debug_state;
406 _dl_debug_addr = debug_addr;
408 /* Notify the debugger we are in a consistant state */
409 _dl_debug_addr->r_state = RT_CONSISTENT;
412 /* OK, we now have the application in the list, and we have some
413 basic stuff in place. Now search through the list for other shared
414 libraries that should be loaded, and insert them on the list in the
425 while (*str == ':' || *str == ' ' || *str == '\t')
430 while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
434 if (!_dl_secure || _dl_strchr(str, '/') == NULL)
436 if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects)))
438 tpnt1->usage_count++;
441 #if defined (__SUPPORT_LD_DEBUG__)
442 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
445 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
447 #ifdef __LDSO_LDD_SUPPORT__
448 if (trace_loaded_objects)
449 _dl_dprintf(1, "\t%s => not found\n", str);
453 _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
457 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
458 #ifdef __SUPPORT_LD_DEBUG_EARLY__
459 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
461 #ifdef __LDSO_LDD_SUPPORT__
462 if (trace_loaded_objects && tpnt1->usage_count==1) {
463 /* this is a real hack to make ldd not print
464 * the library itself when run on a library. */
465 if (_dl_strcmp(_dl_progname, str) != 0)
466 _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
467 (unsigned) tpnt1->loadaddr);
474 while (*str == ':' || *str == ' ' || *str == '\t')
479 #ifdef SUPPORT_LDSO_PRELOAD_FILE
484 if (!_dl_stat(LDSO_PRELOAD, &st) && st.st_size > 0) {
485 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
486 _dl_dprintf(2, "%s: can't open file '%s'\n",
487 _dl_progname, LDSO_PRELOAD);
489 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
490 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
492 if (preload == (caddr_t) - 1) {
493 _dl_dprintf(2, "%s: can't map file '%s'\n",
494 _dl_progname, LDSO_PRELOAD);
498 /* convert all separators and comments to spaces */
499 for (cp = preload; *cp; /*nada */ ) {
500 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
502 } else if (*cp == '#') {
505 while (*cp != '\n' && *cp != '\0');
511 /* find start of first library */
512 for (cp = preload; *cp && *cp == ' '; cp++)
516 /* find end of library */
517 for (cp2 = cp; *cp && *cp != ' '; cp++)
522 if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects)))
524 tpnt1->usage_count++;
527 #if defined (__SUPPORT_LD_DEBUG__)
528 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
531 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
533 #ifdef __LDSO_LDD_SUPPORT__
534 if (trace_loaded_objects)
535 _dl_dprintf(1, "\t%s => not found\n", cp2);
539 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
543 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
544 #ifdef __SUPPORT_LD_DEBUG_EARLY__
545 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
547 #ifdef __LDSO_LDD_SUPPORT__
548 if (trace_loaded_objects && tpnt1->usage_count==1) {
549 _dl_dprintf(1, "\t%s => %s (%x)\n", cp2,
550 tpnt1->libname, (unsigned) tpnt1->loadaddr);
555 /* find start of next library */
557 for ( /*nada */ ; *cp && *cp == ' '; cp++)
561 _dl_munmap(preload, st.st_size + 1);
568 for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
571 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++)
573 if (dpnt->d_tag == DT_NEEDED)
576 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
577 name = _dl_get_last_path_component(lpntstr);
579 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))
581 tpnt1->usage_count++;
584 #if defined (__SUPPORT_LD_DEBUG__)
585 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
586 lpntstr, _dl_progname);
588 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))
590 #ifdef __LDSO_LDD_SUPPORT__
591 if (trace_loaded_objects) {
592 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
597 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
601 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
602 #ifdef __SUPPORT_LD_DEBUG_EARLY__
603 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
605 #ifdef __LDSO_LDD_SUPPORT__
606 if (trace_loaded_objects && tpnt1->usage_count==1) {
607 _dl_dprintf(1, "\t%s => %s (%x)\n", lpntstr, tpnt1->libname,
608 (unsigned) tpnt1->loadaddr);
620 * If the program interpreter is not in the module chain, add it. This will
621 * be required for dlopen to be able to access the internal functions in the
622 * dynamic linker and to relocate the interpreter again once all libs are loaded.
625 tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr, tpnt->dynamic_info,
626 (unsigned long)tpnt->dynamic_addr, tpnt->dynamic_size);
627 tpnt->libtype = program_interpreter;
629 tpnt->symbol_scope = _dl_symbol_tables;
631 rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
632 _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf));
633 rpnt->next->prev = rpnt;
636 rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
637 _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
640 tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
641 #ifdef RERELOCATE_LDSO
642 /* Only rerelocate functions for now. */
643 tpnt->init_flag = RELOCS_DONE | COPY_RELOCS_DONE;
644 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
645 # ifdef ALLOW_ZERO_PLTGOT
646 if (tpnt->dynamic_info[DT_PLTGOT])
648 INIT_GOT(lpnt, tpnt);
650 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE | COPY_RELOCS_DONE;
655 #ifdef __LDSO_LDD_SUPPORT__
656 /* End of the line for ldd.... */
657 if (trace_loaded_objects) {
658 _dl_dprintf(1, "\t%s => %s (%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1,
659 rpnt->dyn->libname, rpnt->dyn->loadaddr);
667 * Relocation of the GOT entries for MIPS have to be done
668 * after all the libraries have been loaded.
670 _dl_perform_mips_global_got_relocations(_dl_loaded_modules);
673 #ifdef __SUPPORT_LD_DEBUG_EARLY__
674 _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
677 * OK, now all of the kids are tucked into bed in their proper addresses.
678 * Now we go through and look for REL and RELA records that indicate fixups
679 * to the GOT tables. We need to do this in reverse order so that COPY
680 * directives work correctly */
681 if (_dl_symbol_tables)
682 goof += _dl_fixup(_dl_symbol_tables, unlazy);
685 /* OK, at this point things are pretty much ready to run. Now we
686 need to touch up a few items that are required, and then
687 we can let the user application have at it. Note that
688 the dynamic linker itself is not guaranteed to be fully
689 dynamicly linked if we are using ld.so.1, so we have to look
690 up each symbol individually. */
692 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
697 /* We had to set the protections of all pages to R/W for dynamic linking.
698 Set text pages back to R/O */
699 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
700 for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
701 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
702 _dl_mprotect((void *) (tpnt->loadaddr + (myppnt->p_vaddr & PAGE_ALIGN)),
703 (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
710 _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT);
711 #if defined (__SUPPORT_LD_DEBUG__)
712 _dl_on_exit = (int (*)(void (*)(int, void *),void*))
713 (intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT);
716 /* Notify the debugger we have added some objects. */
717 _dl_debug_addr->r_state = RT_ADD;
720 for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
723 for (;rpnt!=NULL; rpnt=rpnt->prev)
727 if (tpnt->libtype == program_interpreter)
730 /* Apparently crt0/1 for the application is responsible for handling this.
731 * We only need to run the init/fini for shared libraries
733 if (tpnt->libtype == elf_executable)
734 break; /* at this point all shared libs are initialized !! */
736 if (tpnt->init_flag & INIT_FUNCS_CALLED)
738 tpnt->init_flag |= INIT_FUNCS_CALLED;
740 if (tpnt->dynamic_info[DT_INIT]) {
741 void (*dl_elf_func) (void);
742 dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
743 #if defined (__SUPPORT_LD_DEBUG__)
744 if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ncalling init: %s\n\n", tpnt->libname);
748 if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
749 void (*dl_elf_func) (void);
750 dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
751 (*_dl_atexit) (dl_elf_func);
752 #if defined (__SUPPORT_LD_DEBUG__)
753 if(_dl_debug && _dl_on_exit)
755 (*_dl_on_exit)(debug_fini, tpnt->libname);
759 #if defined (__SUPPORT_LD_DEBUG__)
762 _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
764 if (!tpnt->dynamic_info[DT_FINI])
765 _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
771 /* Notify the debugger that all objects are now mapped in. */
772 _dl_debug_addr->r_state = RT_CONSISTENT;
776 char *_dl_getenv(const char *symbol, char **envp)
781 while ((pnt = *envp++)) {
783 while (*pnt && *pnt == *pnt1)
785 if (!*pnt || *pnt != '=' || *pnt1)
792 void _dl_unsetenv(const char *symbol, char **envp)
796 char **newenvp = envp;
798 for (pnt = *envp; pnt; pnt = *++envp) {
800 while (*pnt && *pnt == *pnt1)
802 if (!*pnt || *pnt != '=' || *pnt1)
809 static int _dl_suid_ok(void)
811 __kernel_uid_t uid, euid;
812 __kernel_gid_t gid, egid;
815 euid = _dl_geteuid();
817 egid = _dl_getegid();
819 if(uid == euid && gid == egid) {
825 void *(*_dl_malloc_function) (size_t size) = NULL;
826 void *_dl_malloc(int size)
831 #ifdef __SUPPORT_LD_DEBUG_EARLY__
832 _dl_dprintf(2, "malloc: request for %d bytes\n", size);
836 if (_dl_malloc_function)
837 return (*_dl_malloc_function) (size);
839 if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
840 #ifdef __SUPPORT_LD_DEBUG_EARLY__
841 _dl_dprintf(2, "malloc: mmapping more memory\n");
843 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size,
844 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
845 if (_dl_mmap_check_error(_dl_mmap_zero)) {
846 _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
850 retval = _dl_malloc_addr;
851 _dl_malloc_addr += size;
854 * Align memory to 4 byte boundary. Some platforms require this, others
855 * simply get better performance.
857 _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3));