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 unsigned long *_dl_brkp = 0; /* The end of the data segment for brk and sbrk */
45 unsigned long *_dl_envp = 0; /* The environment address */
46 int _dl_secure = 1; /* Are we dealing with setuid stuff? */
47 int _dl_errno = 0; /* We can't use the real errno in ldso */
48 size_t _dl_pagesize = 0; /* Store the page size for use later */
49 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
53 #ifdef __SUPPORT_LD_DEBUG__
55 char *_dl_debug_symbols = 0;
56 char *_dl_debug_move = 0;
57 char *_dl_debug_reloc = 0;
58 char *_dl_debug_detail = 0;
59 char *_dl_debug_nofixups = 0;
60 char *_dl_debug_bindings = 0;
61 int _dl_debug_file = 2;
64 /* Forward function declarations */
65 static int _dl_suid_ok(void);
68 * This stub function is used by some debuggers. The idea is that they
69 * can set an internal breakpoint on it, so that we are notified when the
70 * address mapping is changed in some way.
72 void _dl_debug_state(void)
76 static unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */
77 static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */
81 #if defined (__SUPPORT_LD_DEBUG__)
82 static void debug_fini (int status, void *arg)
85 _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
89 void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt,
90 unsigned long load_addr, unsigned long *hash_addr,
91 Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, struct r_debug *debug_addr,
92 unsigned char *malloc_buffer, unsigned char *mmap_zero, char **argv)
96 int i, goof = 0, be_lazy = RTLD_LAZY, trace_loaded_objects = 0;
98 struct elf_resolve *tcurr;
99 struct elf_resolve *tpnt1;
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 /* Make it so _dl_malloc can use the page of memory we have already
112 * allocated. We shouldn't need to grab any more memory. This must
113 * be first since things like _dl_dprintf() use _dl_malloc().... */
114 _dl_malloc_addr = malloc_buffer;
115 _dl_mmap_zero = mmap_zero;
117 /* Store the page size for later use */
118 _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
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. */
132 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
134 tpnt->chains = hash_addr;
137 tpnt->libtype = program_interpreter;
138 tpnt->loadaddr = (ElfW(Addr)) load_addr;
140 #ifdef ALLOW_ZERO_PLTGOT
141 if (tpnt->dynamic_info[DT_PLTGOT])
144 INIT_GOT(lpnt, tpnt);
145 #ifdef __SUPPORT_LD_DEBUG_EARLY__
146 _dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
150 /* OK, this was a big step, now we need to scan all of the user images
151 and load them properly. */
157 epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
158 tpnt->n_phent = epnt->e_phnum;
159 tpnt->ppnt = myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
160 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
161 if (myppnt->p_type == PT_DYNAMIC) {
162 tpnt->dynamic_addr = (ElfW(Dyn) *)myppnt->p_vaddr + load_addr;
163 tpnt->dynamic_size = myppnt->p_filesz;
171 /* At this point we are now free to examine the user application,
172 and figure out which libraries are supposed to be called. Until
173 we have this list, we will not be completely ready for dynamic linking */
175 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
176 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
177 if (ppnt->p_type == PT_LOAD) {
178 if (ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz > brk_addr)
179 brk_addr = ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz;
181 if (ppnt->p_type == PT_DYNAMIC) {
182 #ifndef ALLOW_ZERO_PLTGOT
183 /* make sure it's really there. */
184 if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
187 /* OK, we have what we need - slip this one into the list. */
188 app_tpnt = _dl_add_elf_hash_table("", (char *)app_tpnt->loadaddr,
189 app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
190 _dl_loaded_modules->libtype = elf_executable;
191 _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
192 _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
193 _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
194 _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
195 rpnt->dyn = _dl_loaded_modules;
196 app_tpnt->usage_count++;
197 app_tpnt->symbol_scope = _dl_symbol_tables;
198 lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT] + app_tpnt->loadaddr);
199 #ifdef ALLOW_ZERO_PLTGOT
202 INIT_GOT(lpnt, _dl_loaded_modules);
205 /* OK, fill this in - we did not have this before */
206 if (ppnt->p_type == PT_INTERP) {
208 char *pnt, *pnt1, buf[1024];
209 tpnt->libname = _dl_strdup((char *) ppnt->p_offset +
210 (auxvt[AT_PHDR].a_un.a_val & PAGE_ALIGN));
212 /* Determine if the shared lib loader is a symlink */
213 _dl_memset(buf, 0, sizeof(buf));
214 readsize = _dl_readlink(tpnt->libname, buf, sizeof(buf));
215 if (readsize > 0 && readsize < (int)(sizeof(buf)-1)) {
216 pnt1 = _dl_strrchr(buf, '/');
217 if (pnt1 && buf != pnt1) {
218 #ifdef __SUPPORT_LD_DEBUG_EARLY__
219 _dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
221 tpnt->libname = _dl_strdup(buf);
225 /* Store the path where the shared lib loader was found for
227 pnt = _dl_strdup(tpnt->libname);
228 pnt1 = _dl_strrchr(pnt, '/');
233 _dl_ldsopath = tpnt->libname;
235 #ifdef __SUPPORT_LD_DEBUG_EARLY__
236 _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
242 /* Now we need to figure out what kind of options are selected.
243 Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */
245 if (_dl_getenv("LD_BIND_NOW", envp))
248 if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
249 (auxvt[AT_UID].a_un.a_val != -1 &&
250 auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val
251 && auxvt[AT_GID].a_un.a_val== auxvt[AT_EGID].a_un.a_val)) {
253 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
254 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
257 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
258 _dl_unsetenv("LD_AOUT_PRELOAD", envp);
259 _dl_unsetenv("LD_LIBRARY_PATH", envp);
260 _dl_unsetenv("LD_AOUT_LIBRARY_PATH", envp);
261 _dl_library_path = NULL;
265 #ifdef __SUPPORT_LD_DEBUG__
266 _dl_debug = _dl_getenv("LD_DEBUG", envp);
269 if (_dl_strstr(_dl_debug, "all")) {
270 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
271 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = _dl_strstr(_dl_debug, "all");
274 _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
275 _dl_debug_move = _dl_strstr(_dl_debug, "move");
276 _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
277 _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
278 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
279 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
283 const char *dl_debug_output;
285 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
289 char tmp[22], *tmp1, *filename;
292 _dl_memset(tmp, 0, sizeof(tmp));
293 tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
295 len1 = _dl_strlen(dl_debug_output);
296 len2 = _dl_strlen(tmp1);
298 filename = _dl_malloc(len1+len2+2);
302 _dl_strcpy (filename, dl_debug_output);
303 filename[len1] = '.';
304 _dl_strcpy (&filename[len1+1], tmp1);
306 _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644);
307 if (_dl_debug_file<0)
310 _dl_dprintf (2, "can't open file: '%s'\n",filename);
318 if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
319 trace_loaded_objects++;
321 #ifndef __LDSO_LDD_SUPPORT__
322 if (trace_loaded_objects) {
323 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
329 * OK, fix one more thing - set up debug_addr so it will point
330 * to our chain. Later we may need to fill in more fields, but this
331 * should be enough for now.
333 debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
334 debug_addr->r_version = 1;
335 debug_addr->r_ldbase = load_addr;
336 debug_addr->r_brk = (unsigned long) &_dl_debug_state;
337 _dl_debug_addr = debug_addr;
339 /* Notify the debugger we are in a consistant state */
340 _dl_debug_addr->r_state = RT_CONSISTENT;
343 /* OK, we now have the application in the list, and we have some
344 basic stuff in place. Now search through the list for other shared
345 libraries that should be loaded, and insert them on the list in the
356 while (*str == ':' || *str == ' ' || *str == '\t')
361 while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
365 if (!_dl_secure || _dl_strchr(str, '/') == NULL)
367 if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects)))
371 #if defined (__SUPPORT_LD_DEBUG__)
372 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
375 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
377 #ifdef __LDSO_LDD_SUPPORT__
378 if (trace_loaded_objects)
379 _dl_dprintf(1, "\t%s => not found\n", str);
383 _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
387 #ifdef __SUPPORT_LD_DEBUG_EARLY__
388 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
390 #ifdef __LDSO_LDD_SUPPORT__
391 if (trace_loaded_objects && tpnt1->usage_count==1) {
392 /* this is a real hack to make ldd not print
393 * the library itself when run on a library. */
394 if (_dl_strcmp(_dl_progname, str) != 0)
395 _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
396 (unsigned) tpnt1->loadaddr);
403 while (*str == ':' || *str == ' ' || *str == '\t')
408 #ifdef SUPPORT_LDSO_PRELOAD_FILE
413 if (!_dl_stat(LDSO_PRELOAD, &st) && st.st_size > 0) {
414 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
415 _dl_dprintf(2, "%s: can't open file '%s'\n",
416 _dl_progname, LDSO_PRELOAD);
418 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
419 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
421 if (preload == (caddr_t) - 1) {
422 _dl_dprintf(2, "%s: can't map file '%s'\n",
423 _dl_progname, LDSO_PRELOAD);
427 /* convert all separators and comments to spaces */
428 for (cp = preload; *cp; /*nada */ ) {
429 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
431 } else if (*cp == '#') {
434 while (*cp != '\n' && *cp != '\0');
440 /* find start of first library */
441 for (cp = preload; *cp && *cp == ' '; cp++)
445 /* find end of library */
446 for (cp2 = cp; *cp && *cp != ' '; cp++)
451 if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects)))
455 #if defined (__SUPPORT_LD_DEBUG__)
456 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
459 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
461 #ifdef __LDSO_LDD_SUPPORT__
462 if (trace_loaded_objects)
463 _dl_dprintf(1, "\t%s => not found\n", cp2);
467 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
471 #ifdef __SUPPORT_LD_DEBUG_EARLY__
472 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
474 #ifdef __LDSO_LDD_SUPPORT__
475 if (trace_loaded_objects && tpnt1->usage_count==1) {
476 _dl_dprintf(1, "\t%s => %s (%x)\n", cp2,
477 tpnt1->libname, (unsigned) tpnt1->loadaddr);
482 /* find start of next library */
484 for ( /*nada */ ; *cp && *cp == ' '; cp++)
488 _dl_munmap(preload, st.st_size + 1);
495 for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
498 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++)
500 if (dpnt->d_tag == DT_NEEDED)
503 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
504 name = _dl_get_last_path_component(lpntstr);
506 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))
510 #if defined (__SUPPORT_LD_DEBUG__)
511 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n",
512 lpntstr, _dl_progname);
514 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))
516 #ifdef __LDSO_LDD_SUPPORT__
517 if (trace_loaded_objects) {
518 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
523 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
527 #ifdef __SUPPORT_LD_DEBUG_EARLY__
528 _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
530 #ifdef __LDSO_LDD_SUPPORT__
531 if (trace_loaded_objects && tpnt1->usage_count==1) {
532 _dl_dprintf(1, "\t%s => %s (%x)\n", lpntstr, tpnt1->libname,
533 (unsigned) tpnt1->loadaddr);
545 * If the program interpreter is not in the module chain, add it. This will
546 * be required for dlopen to be able to access the internal functions in the
550 tcurr = _dl_loaded_modules;
561 _dl_loaded_modules = tpnt;
565 rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
566 _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf));
567 rpnt->next->prev = rpnt;
570 rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
571 _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
577 #ifdef __LDSO_LDD_SUPPORT__
578 /* End of the line for ldd.... */
579 if (trace_loaded_objects) {
580 _dl_dprintf(1, "\t%s => %s (%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1,
581 rpnt->dyn->libname, rpnt->dyn->loadaddr);
589 * Relocation of the GOT entries for MIPS have to be done
590 * after all the libraries have been loaded.
592 _dl_perform_mips_global_got_relocations(_dl_loaded_modules);
595 #ifdef __SUPPORT_LD_DEBUG_EARLY__
596 _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
599 * OK, now all of the kids are tucked into bed in their proper addresses.
600 * Now we go through and look for REL and RELA records that indicate fixups
601 * to the GOT tables. We need to do this in reverse order so that COPY
602 * directives work correctly */
603 if (_dl_symbol_tables)
604 goof += _dl_fixup(_dl_symbol_tables, be_lazy);
607 /* OK, at this point things are pretty much ready to run. Now we
608 need to touch up a few items that are required, and then
609 we can let the user application have at it. Note that
610 the dynamic linker itself is not guaranteed to be fully
611 dynamicly linked if we are using ld.so.1, so we have to look
612 up each symbol individually. */
615 _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("__curbrk", NULL, 0);
618 *_dl_brkp = brk_addr;
620 _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, 0);
623 *_dl_envp = (unsigned long) envp;
626 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
631 /* We had to set the protections of all pages to R/W for dynamic linking.
632 Set text pages back to R/O */
633 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
634 for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
635 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
636 _dl_mprotect((void *) (tpnt->loadaddr + (myppnt->p_vaddr & PAGE_ALIGN)),
637 (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
644 _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, ELF_RTYPE_CLASS_PLT);
645 #if defined (__SUPPORT_LD_DEBUG__)
646 _dl_on_exit = (int (*)(void (*)(int, void *),void*))
647 (intptr_t) _dl_find_hash("on_exit", NULL, ELF_RTYPE_CLASS_PLT);
650 /* Notify the debugger we have added some objects. */
651 _dl_debug_addr->r_state = RT_ADD;
654 for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
657 for (;rpnt!=NULL; rpnt=rpnt->prev)
661 if (tpnt->libtype == program_interpreter)
664 /* Apparently crt0/1 for the application is responsible for handling this.
665 * We only need to run the init/fini for shared libraries
667 if (tpnt->libtype == elf_executable)
668 break; /* at this point all shared libs are initialized !! */
670 if (tpnt->init_flag & INIT_FUNCS_CALLED)
672 tpnt->init_flag |= INIT_FUNCS_CALLED;
674 if (tpnt->dynamic_info[DT_INIT]) {
675 void (*dl_elf_func) (void);
676 dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
677 #if defined (__SUPPORT_LD_DEBUG__)
678 if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ncalling init: %s\n\n", tpnt->libname);
682 if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
683 void (*dl_elf_func) (void);
684 dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
685 (*_dl_atexit) (dl_elf_func);
686 #if defined (__SUPPORT_LD_DEBUG__)
687 if(_dl_debug && _dl_on_exit)
689 (*_dl_on_exit)(debug_fini, tpnt->libname);
693 #if defined (__SUPPORT_LD_DEBUG__)
696 _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
698 if (!tpnt->dynamic_info[DT_FINI])
699 _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
705 /* Notify the debugger that all objects are now mapped in. */
706 _dl_debug_addr->r_state = RT_CONSISTENT;
710 char *_dl_getenv(const char *symbol, char **envp)
715 while ((pnt = *envp++)) {
717 while (*pnt && *pnt == *pnt1)
719 if (!*pnt || *pnt != '=' || *pnt1)
726 void _dl_unsetenv(const char *symbol, char **envp)
730 char **newenvp = envp;
732 for (pnt = *envp; pnt; pnt = *++envp) {
734 while (*pnt && *pnt == *pnt1)
736 if (!*pnt || *pnt != '=' || *pnt1)
743 static int _dl_suid_ok(void)
745 __kernel_uid_t uid, euid;
746 __kernel_gid_t gid, egid;
749 euid = _dl_geteuid();
751 egid = _dl_getegid();
753 if(uid == euid && gid == egid) {
759 void *(*_dl_malloc_function) (size_t size) = NULL;
760 void *_dl_malloc(int size)
765 #ifdef __SUPPORT_LD_DEBUG_EARLY__
766 _dl_dprintf(2, "malloc: request for %d bytes\n", size);
770 if (_dl_malloc_function)
771 return (*_dl_malloc_function) (size);
773 if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
774 #ifdef __SUPPORT_LD_DEBUG_EARLY__
775 _dl_dprintf(2, "malloc: mmapping more memory\n");
777 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size,
778 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
779 if (_dl_mmap_check_error(_dl_mmap_zero)) {
780 _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
784 retval = _dl_malloc_addr;
785 _dl_malloc_addr += size;
788 * Align memory to 4 byte boundary. Some platforms require this, others
789 * simply get better performance.
791 _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3));