OSDN Git Service

Hopefully fix Laszlo and Jacobs dlopen problem.
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Program to load an ELF binary on a linux system, and run it
4  * after resolving ELF shared library symbols
5  *
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
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  */
31
32
33 #include "ldso.h"
34
35 #define ALLOW_ZERO_PLTGOT
36
37 /* Pull in the value of _dl_progname */
38 #include "dl-progname.h"
39
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 */
48
49
50
51 #ifdef __SUPPORT_LD_DEBUG__
52 char *_dl_debug           = 0;
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;
60 #endif
61
62 /* Forward function declarations */
63 static int _dl_suid_ok(void);
64
65 /*
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.
69  */
70 void _dl_debug_state(void)
71 {
72 }
73
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 */
76
77
78
79 #if defined (__SUPPORT_LD_DEBUG__)
80 static void debug_fini (int status, void *arg)
81 {
82         (void)status;
83         _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
84 }
85 #endif
86
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)
89 {
90         ElfW(Phdr) *ppnt;
91         Elf32_Dyn *dpnt;
92         char *lpntstr;
93         int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
94         struct dyn_elf *rpnt;
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*);
104 #endif
105
106 #ifdef __SUPPORT_LD_DEBUG_EARLY__
107         /* Wahoo!!! */
108         SEND_STDERR("Cool, we managed to make a function call.\n");
109 #endif
110
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;
117         _dl_mmap_zero = 0;
118
119
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. */
124         if (argv[0]) {
125                 _dl_progname = argv[0];
126         }
127
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         {
133                 ElfW(Ehdr) *epnt;
134                 ElfW(Phdr) *myppnt;
135                 int j;
136
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;
144                         }
145                 }
146         }
147
148         brk_addr = 0;
149         rpnt = NULL;
150         if (_dl_getenv("LD_BIND_NOW", envp))
151                 unlazy = RTLD_NOW;
152
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 */
156
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.
159          */
160         {
161                 int i;
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);
166                                 break;
167                         }
168
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);
173                 }
174 #endif
175         }
176         /*
177          * This is used by gdb to locate the chain of shared libraries that are currently loaded.
178          */
179         debug_addr = _dl_malloc(sizeof(struct r_debug));
180         _dl_memset(debug_addr, 0, sizeof(struct r_debug));
181
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;
187                 }
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) {
202                                         dpnt++;
203                                         continue;
204                                 }
205                                 app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
206                                 
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
210                                          * it to us rx.
211                                          */
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");
216                                                 _dl_exit(0);
217                                         }
218                                         dpnt->d_un.d_val = (unsigned long) debug_addr;
219                                 }
220 #else
221                                 if (dpnt->d_tag > DT_JMPREL) {
222                                                 dpnt++;
223                                                 continue;
224                                 }
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;
228                                 }
229 #endif
230                                 if (dpnt->d_tag == DT_TEXTREL)
231                                         app_tpnt->dynamic_info[DT_TEXTREL] = 1;
232                                 dpnt++;
233                         }
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");
240 #endif
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);
250                                 }
251                         }
252 #endif
253
254 #ifndef ALLOW_ZERO_PLTGOT
255                         /* make sure it's really there. */
256                         if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
257                                 continue;
258 #endif
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
273                         if (lpnt)
274 #endif
275                                 INIT_GOT(lpnt, _dl_loaded_modules);
276                 }
277
278                 /* OK, fill this in - we did not have this before */
279                 if (ppnt->p_type == PT_INTERP) {
280                         int readsize = 0;
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));
284
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);
293 #endif
294                                         tpnt->libname = _dl_strdup(buf);
295                                 }
296                         }
297
298                         /* Store the path where the shared lib loader was found for
299                          * later use */
300                         pnt = _dl_strdup(tpnt->libname);
301                         pnt1 = _dl_strrchr(pnt, '/');
302                         if (pnt != pnt1) {
303                                 *pnt1 = '\0';
304                                 _dl_ldsopath = pnt;
305                         } else {
306                                 _dl_ldsopath = tpnt->libname;
307                         }
308 #ifdef __SUPPORT_LD_DEBUG_EARLY__
309                         _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
310 #endif
311                 }
312         }
313
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 */
316         {
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)) {
321                         _dl_secure = 0;
322                         _dl_preload = _dl_getenv("LD_PRELOAD", envp);
323                         _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
324                 } else {
325                         _dl_secure = 1;
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;
331                 }
332         }
333
334 #ifdef __SUPPORT_LD_DEBUG__
335         _dl_debug    = _dl_getenv("LD_DEBUG", envp);
336         if (_dl_debug)
337         {
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");
341                 }
342                 else {
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");
349                 }
350         }
351         {
352                 const char *dl_debug_output;
353
354                 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
355
356                 if (dl_debug_output)
357                 {
358                         char tmp[22], *tmp1, *filename;
359                         int len1, len2;
360
361                         _dl_memset(tmp, 0, sizeof(tmp));
362                         tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
363
364                         len1 = _dl_strlen(dl_debug_output);
365                         len2 = _dl_strlen(tmp1);
366
367                         filename = _dl_malloc(len1+len2+2);
368
369                         if (filename)
370                         {
371                                 _dl_strcpy (filename, dl_debug_output);
372                                 filename[len1] = '.';
373                                 _dl_strcpy (&filename[len1+1], tmp1);
374
375                                 _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644);
376                                 if (_dl_debug_file<0)
377                                 {
378                                         _dl_debug_file = 2;
379                                         _dl_dprintf (2, "can't open file: '%s'\n",filename);
380                                 }
381                         }
382                 }
383         }
384
385
386 #endif
387         if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
388                 trace_loaded_objects++;
389         }
390 #ifndef __LDSO_LDD_SUPPORT__
391         if (trace_loaded_objects) {
392                 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
393                 _dl_exit(1);
394         }
395 #endif
396
397         /*
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.
401          */
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;
407
408         /* Notify the debugger we are in a consistant state */
409         _dl_debug_addr->r_state = RT_CONSISTENT;
410         _dl_debug_state();
411
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
415            correct order. */
416
417         _dl_map_cache();
418
419
420         if (_dl_preload)
421         {
422                 char c, *str, *str2;
423
424                 str = _dl_preload;
425                 while (*str == ':' || *str == ' ' || *str == '\t')
426                         str++;
427                 while (*str)
428                 {
429                         str2 = str;
430                         while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
431                                 str2++;
432                         c = *str2;
433                         *str2 = '\0';
434                         if (!_dl_secure || _dl_strchr(str, '/') == NULL)
435                         {
436                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects)))
437                                 {
438                                         tpnt1->usage_count++;
439                                         continue;
440                                 }
441 #if defined (__SUPPORT_LD_DEBUG__)
442                                 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s';  needed by '%s'\n",
443                                                 str, _dl_progname);
444 #endif
445                                 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
446                                 if (!tpnt1) {
447 #ifdef __LDSO_LDD_SUPPORT__
448                                         if (trace_loaded_objects)
449                                                 _dl_dprintf(1, "\t%s => not found\n", str);
450                                         else
451 #endif
452                                         {
453                                                 _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
454                                                 _dl_exit(15);
455                                         }
456                                 } else {
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);
460 #endif
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);
468                                         }
469 #endif
470                                 }
471                         }
472                         *str2 = c;
473                         str = str2;
474                         while (*str == ':' || *str == ' ' || *str == '\t')
475                                 str++;
476                 }
477         }
478
479 #ifdef SUPPORT_LDSO_PRELOAD_FILE
480         {
481                 int fd;
482                 struct stat st;
483                 char *preload;
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);
488                         } else {
489                                 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
490                                                 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
491                                 _dl_close(fd);
492                                 if (preload == (caddr_t) - 1) {
493                                         _dl_dprintf(2, "%s: can't map file '%s'\n",
494                                                         _dl_progname, LDSO_PRELOAD);
495                                 } else {
496                                         char c, *cp, *cp2;
497
498                                         /* convert all separators and comments to spaces */
499                                         for (cp = preload; *cp; /*nada */ ) {
500                                                 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
501                                                         *cp++ = ' ';
502                                                 } else if (*cp == '#') {
503                                                         do
504                                                                 *cp++ = ' ';
505                                                         while (*cp != '\n' && *cp != '\0');
506                                                 } else {
507                                                         cp++;
508                                                 }
509                                         }
510
511                                         /* find start of first library */
512                                         for (cp = preload; *cp && *cp == ' '; cp++)
513                                                 /*nada */ ;
514
515                                         while (*cp) {
516                                                 /* find end of library */
517                                                 for (cp2 = cp; *cp && *cp != ' '; cp++)
518                                                         /*nada */ ;
519                                                 c = *cp;
520                                                 *cp = '\0';
521
522                                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects)))
523                                                 {
524                                                         tpnt1->usage_count++;
525                                                         continue;
526                                                 }
527 #if defined (__SUPPORT_LD_DEBUG__)
528                                                 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s';  needed by '%s'\n",
529                                                                 cp2, _dl_progname);
530 #endif
531                                                 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
532                                                 if (!tpnt1) {
533 #ifdef __LDSO_LDD_SUPPORT__
534                                                         if (trace_loaded_objects)
535                                                                 _dl_dprintf(1, "\t%s => not found\n", cp2);
536                                                         else
537 #endif
538                                                         {
539                                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
540                                                                 _dl_exit(15);
541                                                         }
542                                                 } else {
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);
546 #endif
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);
551                                                         }
552 #endif
553                                                 }
554
555                                                 /* find start of next library */
556                                                 *cp = c;
557                                                 for ( /*nada */ ; *cp && *cp == ' '; cp++)
558                                                         /*nada */ ;
559                                         }
560
561                                         _dl_munmap(preload, st.st_size + 1);
562                                 }
563                         }
564                 }
565         }
566 #endif
567
568         for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
569         {
570                 Elf32_Dyn *dpnt;
571                 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++)
572                 {
573                         if (dpnt->d_tag == DT_NEEDED)
574                         {
575                                 char *name;
576                                 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
577                                 name = _dl_get_last_path_component(lpntstr);
578
579                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))
580                                 {
581                                         tpnt1->usage_count++;
582                                         continue;
583                                 }
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);
587 #endif
588                                 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))
589                                 {
590 #ifdef __LDSO_LDD_SUPPORT__
591                                         if (trace_loaded_objects) {
592                                                 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
593                                                 continue;
594                                         } else
595 #endif
596                                         {
597                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
598                                                 _dl_exit(16);
599                                         }
600                                 } else {
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);
604 #endif
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);
609                                         }
610 #endif
611                                 }
612                         }
613                 }
614         }
615
616
617         _dl_unmap_cache();
618
619         /*
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.
623          */
624         if (tpnt) {
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;
628                 tpnt->usage_count++;
629                 tpnt->symbol_scope = _dl_symbol_tables;
630                 if (rpnt) {
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;
634                         rpnt = rpnt->next;
635                 } else {
636                         rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
637                         _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
638                 }
639                 rpnt->dyn = tpnt;
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])
647 # endif
648                         INIT_GOT(lpnt, tpnt);
649 #else
650                 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE | COPY_RELOCS_DONE;
651 #endif
652                 tpnt = NULL;
653         }
654
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);
660                 _dl_exit(0);
661         }
662 #endif
663
664
665 #ifdef __mips__
666         /*
667          * Relocation of the GOT entries for MIPS have to be done
668          * after all the libraries have been loaded.
669          */
670         _dl_perform_mips_global_got_relocations(_dl_loaded_modules);
671 #endif
672
673 #ifdef __SUPPORT_LD_DEBUG_EARLY__
674         _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
675 #endif
676         /*
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);
683
684
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. */
691
692 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
693         {
694                 unsigned int j;
695                 ElfW(Phdr) *myppnt;
696
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));
704                                 }
705                         }
706                 }
707
708         }
709 #endif
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);
714 #endif
715
716         /* Notify the debugger we have added some objects. */
717         _dl_debug_addr->r_state = RT_ADD;
718         _dl_debug_state();
719
720         for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
721                 ;
722
723         for (;rpnt!=NULL; rpnt=rpnt->prev)
724         {
725                 tpnt = rpnt->dyn;
726
727                 if (tpnt->libtype == program_interpreter)
728                         continue;
729
730                 /* Apparently crt0/1 for the application is responsible for handling this.
731                  * We only need to run the init/fini for shared libraries
732                  */
733                 if (tpnt->libtype == elf_executable)
734                         break;      /* at this point all shared libs are initialized !! */
735
736                 if (tpnt->init_flag & INIT_FUNCS_CALLED)
737                         continue;
738                 tpnt->init_flag |= INIT_FUNCS_CALLED;
739
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);
745 #endif
746                         (*dl_elf_func) ();
747                 }
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)
754                         {
755                                 (*_dl_on_exit)(debug_fini, tpnt->libname);
756                         }
757 #endif
758                 }
759 #if defined (__SUPPORT_LD_DEBUG__)
760                 else {
761                         if (!_dl_atexit)
762                                 _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
763 #if 0
764                         if (!tpnt->dynamic_info[DT_FINI])
765                                 _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
766 #endif
767                 }
768 #endif
769         }
770
771         /* Notify the debugger that all objects are now mapped in.  */
772         _dl_debug_addr->r_state = RT_CONSISTENT;
773         _dl_debug_state();
774 }
775
776 char *_dl_getenv(const char *symbol, char **envp)
777 {
778         char *pnt;
779         const char *pnt1;
780
781         while ((pnt = *envp++)) {
782                 pnt1 = symbol;
783                 while (*pnt && *pnt == *pnt1)
784                         pnt1++, pnt++;
785                 if (!*pnt || *pnt != '=' || *pnt1)
786                         continue;
787                 return pnt + 1;
788         }
789         return 0;
790 }
791
792 void _dl_unsetenv(const char *symbol, char **envp)
793 {
794         char *pnt;
795         const char *pnt1;
796         char **newenvp = envp;
797
798         for (pnt = *envp; pnt; pnt = *++envp) {
799                 pnt1 = symbol;
800                 while (*pnt && *pnt == *pnt1)
801                         pnt1++, pnt++;
802                 if (!*pnt || *pnt != '=' || *pnt1)
803                         *newenvp++ = *envp;
804         }
805         *newenvp++ = *envp;
806         return;
807 }
808
809 static int _dl_suid_ok(void)
810 {
811         __kernel_uid_t uid, euid;
812         __kernel_gid_t gid, egid;
813
814         uid = _dl_getuid();
815         euid = _dl_geteuid();
816         gid = _dl_getgid();
817         egid = _dl_getegid();
818
819         if(uid == euid && gid == egid) {
820                 return 1;
821         }
822         return 0;
823 }
824
825 void *(*_dl_malloc_function) (size_t size) = NULL;
826 void *_dl_malloc(int size)
827 {
828         void *retval;
829
830 #if 0
831 #ifdef __SUPPORT_LD_DEBUG_EARLY__
832         _dl_dprintf(2, "malloc: request for %d bytes\n", size);
833 #endif
834 #endif
835
836         if (_dl_malloc_function)
837                 return (*_dl_malloc_function) (size);
838
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");
842 #endif
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);
847                         _dl_exit(20);
848                 }
849         }
850         retval = _dl_malloc_addr;
851         _dl_malloc_addr += size;
852
853         /*
854          * Align memory to 4 byte boundary.  Some platforms require this, others
855          * simply get better performance.
856          */
857         _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3));
858         return retval;
859 }
860
861
862 #include "dl-hash.c"
863 #include "dl-elf.c"