OSDN Git Service

s/___brk_addr/__curbrk/g
[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 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 */
50
51
52
53 #ifdef __SUPPORT_LD_DEBUG__
54 char *_dl_debug           = 0;
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;
62 #endif
63
64 /* Forward function declarations */
65 static int _dl_suid_ok(void);
66
67 /*
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.
71  */
72 void _dl_debug_state(void)
73 {
74 }
75
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 */
78
79
80
81 #if defined (__SUPPORT_LD_DEBUG__)
82 static void debug_fini (int status, void *arg)
83 {
84         (void)status;
85         _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
86 }
87 #endif
88
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)
93 {
94         ElfW(Phdr) *ppnt;
95         char *lpntstr;
96         int i, goof = 0, be_lazy = RTLD_LAZY, trace_loaded_objects = 0;
97         struct dyn_elf *rpnt;
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*);
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         /* 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;
116
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;
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         lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
133
134         tpnt->chains = hash_addr;
135         tpnt->next = 0;
136         tpnt->libname = 0;
137         tpnt->libtype = program_interpreter;
138         tpnt->loadaddr = (ElfW(Addr)) load_addr;
139
140 #ifdef ALLOW_ZERO_PLTGOT
141         if (tpnt->dynamic_info[DT_PLTGOT])
142 #endif
143         {
144                 INIT_GOT(lpnt, tpnt);
145 #ifdef __SUPPORT_LD_DEBUG_EARLY__
146                 _dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
147 #endif
148         }
149
150         /* OK, this was a big step, now we need to scan all of the user images
151            and load them properly. */
152         {
153                 ElfW(Ehdr) *epnt;
154                 ElfW(Phdr) *myppnt;
155                 int j;
156
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;
164                         }
165                 }
166         }
167
168         brk_addr = 0;
169         rpnt = NULL;
170
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 */
174
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;
180                 }
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)
185                                 continue;
186 #endif
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
200                         if (lpnt)
201 #endif
202                                 INIT_GOT(lpnt, _dl_loaded_modules);
203                 }
204
205                 /* OK, fill this in - we did not have this before */
206                 if (ppnt->p_type == PT_INTERP) {
207                         int readsize = 0;
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));
211
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);
220 #endif
221                                         tpnt->libname = _dl_strdup(buf);
222                                 }
223                         }
224
225                         /* Store the path where the shared lib loader was found for
226                          * later use */
227                         pnt = _dl_strdup(tpnt->libname);
228                         pnt1 = _dl_strrchr(pnt, '/');
229                         if (pnt != pnt1) {
230                                 *pnt1 = '\0';
231                                 _dl_ldsopath = pnt;
232                         } else {
233                                 _dl_ldsopath = tpnt->libname;
234                         }
235 #ifdef __SUPPORT_LD_DEBUG_EARLY__
236                         _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
237 #endif
238                 }
239         }
240
241
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 */
244         {
245                 if (_dl_getenv("LD_BIND_NOW", envp))
246                         be_lazy = 0;
247
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)) {
252                         _dl_secure = 0;
253                         _dl_preload = _dl_getenv("LD_PRELOAD", envp);
254                         _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
255                 } else {
256                         _dl_secure = 1;
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;
262                 }
263         }
264
265 #ifdef __SUPPORT_LD_DEBUG__
266         _dl_debug    = _dl_getenv("LD_DEBUG", envp);
267         if (_dl_debug)
268         {
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");
272                 }
273                 else {
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");
280                 }
281         }
282         {
283                 const char *dl_debug_output;
284
285                 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
286
287                 if (dl_debug_output)
288                 {
289                         char tmp[22], *tmp1, *filename;
290                         int len1, len2;
291
292                         _dl_memset(tmp, 0, sizeof(tmp));
293                         tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
294
295                         len1 = _dl_strlen(dl_debug_output);
296                         len2 = _dl_strlen(tmp1);
297
298                         filename = _dl_malloc(len1+len2+2);
299
300                         if (filename)
301                         {
302                                 _dl_strcpy (filename, dl_debug_output);
303                                 filename[len1] = '.';
304                                 _dl_strcpy (&filename[len1+1], tmp1);
305
306                                 _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644);
307                                 if (_dl_debug_file<0)
308                                 {
309                                         _dl_debug_file = 2;
310                                         _dl_dprintf (2, "can't open file: '%s'\n",filename);
311                                 }
312                         }
313                 }
314         }
315
316
317 #endif
318         if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
319                 trace_loaded_objects++;
320         }
321 #ifndef __LDSO_LDD_SUPPORT__
322         if (trace_loaded_objects) {
323                 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
324                 _dl_exit(1);
325         }
326 #endif
327
328         /*
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.
332          */
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;
338
339         /* Notify the debugger we are in a consistant state */
340         _dl_debug_addr->r_state = RT_CONSISTENT;
341         _dl_debug_state();
342
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
346            correct order. */
347
348         _dl_map_cache();
349
350
351         if (_dl_preload)
352         {
353                 char c, *str, *str2;
354
355                 str = _dl_preload;
356                 while (*str == ':' || *str == ' ' || *str == '\t')
357                         str++;
358                 while (*str)
359                 {
360                         str2 = str;
361                         while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
362                                 str2++;
363                         c = *str2;
364                         *str2 = '\0';
365                         if (!_dl_secure || _dl_strchr(str, '/') == NULL)
366                         {
367                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects)))
368                                 {
369                                         continue;
370                                 }
371 #if defined (__SUPPORT_LD_DEBUG__)
372                                 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s';  needed by '%s'\n",
373                                                 str, _dl_progname);
374 #endif
375                                 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
376                                 if (!tpnt1) {
377 #ifdef __LDSO_LDD_SUPPORT__
378                                         if (trace_loaded_objects)
379                                                 _dl_dprintf(1, "\t%s => not found\n", str);
380                                         else
381 #endif
382                                         {
383                                                 _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
384                                                 _dl_exit(15);
385                                         }
386                                 } else {
387 #ifdef __SUPPORT_LD_DEBUG_EARLY__
388                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
389 #endif
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);
397                                         }
398 #endif
399                                 }
400                         }
401                         *str2 = c;
402                         str = str2;
403                         while (*str == ':' || *str == ' ' || *str == '\t')
404                                 str++;
405                 }
406         }
407
408 #ifdef SUPPORT_LDSO_PRELOAD_FILE
409         {
410                 int fd;
411                 struct stat st;
412                 char *preload;
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);
417                         } else {
418                                 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
419                                                 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
420                                 _dl_close(fd);
421                                 if (preload == (caddr_t) - 1) {
422                                         _dl_dprintf(2, "%s: can't map file '%s'\n",
423                                                         _dl_progname, LDSO_PRELOAD);
424                                 } else {
425                                         char c, *cp, *cp2;
426
427                                         /* convert all separators and comments to spaces */
428                                         for (cp = preload; *cp; /*nada */ ) {
429                                                 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
430                                                         *cp++ = ' ';
431                                                 } else if (*cp == '#') {
432                                                         do
433                                                                 *cp++ = ' ';
434                                                         while (*cp != '\n' && *cp != '\0');
435                                                 } else {
436                                                         cp++;
437                                                 }
438                                         }
439
440                                         /* find start of first library */
441                                         for (cp = preload; *cp && *cp == ' '; cp++)
442                                                 /*nada */ ;
443
444                                         while (*cp) {
445                                                 /* find end of library */
446                                                 for (cp2 = cp; *cp && *cp != ' '; cp++)
447                                                         /*nada */ ;
448                                                 c = *cp;
449                                                 *cp = '\0';
450
451                                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects)))
452                                                 {
453                                                         continue;
454                                                 }
455 #if defined (__SUPPORT_LD_DEBUG__)
456                                                 if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s';  needed by '%s'\n",
457                                                                 cp2, _dl_progname);
458 #endif
459                                                 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
460                                                 if (!tpnt1) {
461 #ifdef __LDSO_LDD_SUPPORT__
462                                                         if (trace_loaded_objects)
463                                                                 _dl_dprintf(1, "\t%s => not found\n", cp2);
464                                                         else
465 #endif
466                                                         {
467                                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
468                                                                 _dl_exit(15);
469                                                         }
470                                                 } else {
471 #ifdef __SUPPORT_LD_DEBUG_EARLY__
472                                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
473 #endif
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);
478                                                         }
479 #endif
480                                                 }
481
482                                                 /* find start of next library */
483                                                 *cp = c;
484                                                 for ( /*nada */ ; *cp && *cp == ' '; cp++)
485                                                         /*nada */ ;
486                                         }
487
488                                         _dl_munmap(preload, st.st_size + 1);
489                                 }
490                         }
491                 }
492         }
493 #endif
494
495         for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
496         {
497                 Elf32_Dyn *dpnt;
498                 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++)
499                 {
500                         if (dpnt->d_tag == DT_NEEDED)
501                         {
502                                 char *name;
503                                 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
504                                 name = _dl_get_last_path_component(lpntstr);
505
506                                 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))
507                                 {
508                                         continue;
509                                 }
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);
513 #endif
514                                 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))
515                                 {
516 #ifdef __LDSO_LDD_SUPPORT__
517                                         if (trace_loaded_objects) {
518                                                 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
519                                                 continue;
520                                         } else
521 #endif
522                                         {
523                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
524                                                 _dl_exit(16);
525                                         }
526                                 } else {
527 #ifdef __SUPPORT_LD_DEBUG_EARLY__
528                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
529 #endif
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);
534                                         }
535 #endif
536                                 }
537                         }
538                 }
539         }
540
541
542         _dl_unmap_cache();
543
544         /*
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
547          * dynamic linker.
548          */
549         if (tpnt) {
550                 tcurr = _dl_loaded_modules;
551                 if (tcurr)
552                         while (tcurr->next)
553                                 tcurr = tcurr->next;
554                 tpnt->next = NULL;
555                 tpnt->usage_count++;
556
557                 if (tcurr) {
558                         tcurr->next = tpnt;
559                         tpnt->prev = tcurr;
560                 } else {
561                         _dl_loaded_modules = tpnt;
562                         tpnt->prev = NULL;
563                 }
564                 if (rpnt) {
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;
568                         rpnt = rpnt->next;
569                 } else {
570                         rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
571                         _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
572                 }
573                 rpnt->dyn = tpnt;
574                 tpnt = NULL;
575         }
576
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);
582                 _dl_exit(0);
583         }
584 #endif
585
586
587 #ifdef __mips__
588         /*
589          * Relocation of the GOT entries for MIPS have to be done
590          * after all the libraries have been loaded.
591          */
592         _dl_perform_mips_global_got_relocations(_dl_loaded_modules);
593 #endif
594
595 #ifdef __SUPPORT_LD_DEBUG_EARLY__
596         _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
597 #endif
598         /*
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);
605
606
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. */
613
614
615         _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("__curbrk", NULL, 0);
616
617         if (_dl_brkp) {
618                 *_dl_brkp = brk_addr;
619         }
620         _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, 0);
621
622         if (_dl_envp) {
623                 *_dl_envp = (unsigned long) envp;
624         }
625
626 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
627         {
628                 unsigned int j;
629                 ElfW(Phdr) *myppnt;
630
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));
638                                 }
639                         }
640                 }
641
642         }
643 #endif
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);
648 #endif
649
650         /* Notify the debugger we have added some objects. */
651         _dl_debug_addr->r_state = RT_ADD;
652         _dl_debug_state();
653
654         for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
655                 ;
656
657         for (;rpnt!=NULL; rpnt=rpnt->prev)
658         {
659                 tpnt = rpnt->dyn;
660
661                 if (tpnt->libtype == program_interpreter)
662                         continue;
663
664                 /* Apparently crt0/1 for the application is responsible for handling this.
665                  * We only need to run the init/fini for shared libraries
666                  */
667                 if (tpnt->libtype == elf_executable)
668                         break;      /* at this point all shared libs are initialized !! */
669
670                 if (tpnt->init_flag & INIT_FUNCS_CALLED)
671                         continue;
672                 tpnt->init_flag |= INIT_FUNCS_CALLED;
673
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);
679 #endif
680                         (*dl_elf_func) ();
681                 }
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)
688                         {
689                                 (*_dl_on_exit)(debug_fini, tpnt->libname);
690                         }
691 #endif
692                 }
693 #if defined (__SUPPORT_LD_DEBUG__)
694                 else {
695                         if (!_dl_atexit)
696                                 _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
697 #if 0
698                         if (!tpnt->dynamic_info[DT_FINI])
699                                 _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
700 #endif
701                 }
702 #endif
703         }
704
705         /* Notify the debugger that all objects are now mapped in.  */
706         _dl_debug_addr->r_state = RT_CONSISTENT;
707         _dl_debug_state();
708 }
709
710 char *_dl_getenv(const char *symbol, char **envp)
711 {
712         char *pnt;
713         const char *pnt1;
714
715         while ((pnt = *envp++)) {
716                 pnt1 = symbol;
717                 while (*pnt && *pnt == *pnt1)
718                         pnt1++, pnt++;
719                 if (!*pnt || *pnt != '=' || *pnt1)
720                         continue;
721                 return pnt + 1;
722         }
723         return 0;
724 }
725
726 void _dl_unsetenv(const char *symbol, char **envp)
727 {
728         char *pnt;
729         const char *pnt1;
730         char **newenvp = envp;
731
732         for (pnt = *envp; pnt; pnt = *++envp) {
733                 pnt1 = symbol;
734                 while (*pnt && *pnt == *pnt1)
735                         pnt1++, pnt++;
736                 if (!*pnt || *pnt != '=' || *pnt1)
737                         *newenvp++ = *envp;
738         }
739         *newenvp++ = *envp;
740         return;
741 }
742
743 static int _dl_suid_ok(void)
744 {
745         __kernel_uid_t uid, euid;
746         __kernel_gid_t gid, egid;
747
748         uid = _dl_getuid();
749         euid = _dl_geteuid();
750         gid = _dl_getgid();
751         egid = _dl_getegid();
752
753         if(uid == euid && gid == egid) {
754                 return 1;
755         }
756         return 0;
757 }
758
759 void *(*_dl_malloc_function) (size_t size) = NULL;
760 void *_dl_malloc(int size)
761 {
762         void *retval;
763
764 #if 0
765 #ifdef __SUPPORT_LD_DEBUG_EARLY__
766         _dl_dprintf(2, "malloc: request for %d bytes\n", size);
767 #endif
768 #endif
769
770         if (_dl_malloc_function)
771                 return (*_dl_malloc_function) (size);
772
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");
776 #endif
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);
781                         _dl_exit(20);
782                 }
783         }
784         retval = _dl_malloc_addr;
785         _dl_malloc_addr += size;
786
787         /*
788          * Align memory to 4 byte boundary.  Some platforms require this, others
789          * simply get better performance.
790          */
791         _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3));
792         return retval;
793 }
794
795
796 #include "dl-hash.c"
797 #include "dl-elf.c"