OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [ldso/] [libdl/] [dlib.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
2
 * libdl.c
3
 *
4
 * Functions required for dlopen et. al.
5
 */
6
 
7
#include <ldso.h>
8
 
9
 
10
/* The public interfaces */
11
void *dlopen(const char *, int) __attribute__ ((__weak__, __alias__ ("_dlopen")));
12
int dlclose(void *) __attribute__ ((__weak__, __alias__ ("_dlclose")));
13
void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym")));
14
const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror")));
15
int dladdr(void *, Dl_info *) __attribute__ ((__weak__, __alias__ ("_dladdr")));
16
void _dlinfo(void);
17
 
18
 
19
#ifdef __PIC__
20
/* This is a real hack.  We need access to the dynamic linker, but we
21
also need to make it possible to link against this library without any
22
unresolved externals.  We provide these weak symbols to make the link
23
possible, but at run time the normal symbols are accessed. */
24
static void __attribute__ ((unused)) foobar(void)
25
{
26
        const char msg[]="libdl library not correctly linked\n";
27
        _dl_write(2, msg, _dl_strlen(msg));
28
        _dl_exit(1);
29
}
30
 
31
static int __attribute__ ((unused)) foobar1 = (int) foobar;     /* Use as pointer */
32
extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__, __alias__ ("foobar")));
33
extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, enum caller_type)
34
        __attribute__ ((__weak__, __alias__ ("foobar")));
35
extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *)
36
        __attribute__ ((__weak__, __alias__ ("foobar")));
37
extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *full_libname)
38
        __attribute__ ((__weak__, __alias__ ("foobar")));
39
extern int _dl_fixup(struct elf_resolve *tpnt, int lazy)
40
         __attribute__ ((__weak__, __alias__ ("foobar")));
41
extern int _dl_copy_fixups(struct dyn_elf * tpnt)
42
         __attribute__ ((__weak__, __alias__ ("foobar")));
43
#ifdef __mips__
44
extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
45
        __attribute__ ((__weak__, __alias__ ("foobar")));
46
#endif
47
#ifdef USE_CACHE
48
int _dl_map_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
49
int _dl_unmap_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
50
#endif  
51
 
52
extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__, __alias__ ("foobar1")));
53
extern struct dyn_elf *_dl_handles __attribute__ ((__weak__, __alias__ ("foobar1")));
54
extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias__ ("foobar1")));
55
extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1")));
56
extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1")));
57
extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1")));
58
#ifdef __SUPPORT_LD_DEBUG__
59
extern char *_dl_debug __attribute__ ((__weak__, __alias__ ("foobar1")));
60
extern char *_dl_debug_symbols __attribute__ ((__weak__, __alias__ ("foobar1")));
61
extern char *_dl_debug_move __attribute__ ((__weak__, __alias__ ("foobar1")));
62
extern char *_dl_debug_reloc __attribute__ ((__weak__, __alias__ ("foobar1")));
63
extern char *_dl_debug_detail __attribute__ ((__weak__, __alias__ ("foobar1")));
64
extern char *_dl_debug_nofixups __attribute__ ((__weak__, __alias__ ("foobar1")));
65
extern char *_dl_debug_bindings __attribute__ ((__weak__, __alias__ ("foobar1")));
66
extern int   _dl_debug_file __attribute__ ((__weak__, __alias__ ("foobar1")));
67
#endif
68
 
69
#else   /* __PIC__ */
70
 
71
#ifdef __SUPPORT_LD_DEBUG__
72
char *_dl_debug  = 0;
73
char *_dl_debug_symbols = 0;
74
char *_dl_debug_move    = 0;
75
char *_dl_debug_reloc   = 0;
76
char *_dl_debug_detail  = 0;
77
char *_dl_debug_nofixups  = 0;
78
char *_dl_debug_bindings  = 0;
79
int   _dl_debug_file = 2;
80
#endif
81
char *_dl_library_path = 0;
82
char *_dl_ldsopath = 0;
83
struct r_debug *_dl_debug_addr = NULL;
84
static char *_dl_malloc_addr, *_dl_mmap_zero;
85
#include "../ldso/_dl_progname.h"               /* Pull in the name of ld.so */
86
#include "../ldso/hash.c"
87
#define _dl_trace_loaded_objects    0
88
#include "../ldso/readelflib1.c"
89
void *(*_dl_malloc_function) (size_t size);
90
int _dl_fixup(struct elf_resolve *tpnt, int lazy);
91
#endif
92
 
93
static int do_dlclose(void *, int need_fini);
94
 
95
 
96
static const char *dl_error_names[] = {
97
        "",
98
        "File not found",
99
        "Unable to open /dev/zero",
100
        "Not an ELF file",
101
#if defined (__i386__)
102
        "Not i386 binary",
103
#elif defined (__sparc__)
104
        "Not sparc binary",
105
#elif defined (__mc68000__)
106
        "Not m68k binary",
107
#else
108
        "Unrecognized binary type",
109
#endif
110
        "Not an ELF shared library",
111
        "Unable to mmap file",
112
        "No dynamic section",
113
#ifdef ELF_USES_RELOCA
114
        "Unable to process REL relocs",
115
#else
116
        "Unable to process RELA relocs",
117
#endif
118
        "Bad handle",
119
        "Unable to resolve symbol"
120
};
121
 
122
static void __attribute__ ((destructor)) dl_cleanup(void)
123
{
124
        struct dyn_elf *d;
125
 
126
        for (d = _dl_handles; d; d = d->next_handle)
127
                if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) {
128
                        (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) ();
129
                        d->dyn->dynamic_info[DT_FINI] = 0;
130
                }
131
}
132
 
133
void *_dlopen(const char *libname, int flag)
134
{
135
        struct elf_resolve *tpnt, *tfrom, *tcurr;
136
        struct dyn_elf *dyn_chain, *rpnt = NULL;
137
        struct dyn_elf *dpnt;
138
        static int dl_init = 0;
139
        ElfW(Addr) from;
140
        struct elf_resolve *tpnt1;
141
        void (*dl_brk) (void);
142
 
143
        /* A bit of sanity checking... */
144
        if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
145
                _dl_error_number = LD_BAD_HANDLE;
146
                return NULL;
147
        }
148
 
149
        from = (ElfW(Addr)) __builtin_return_address(0);
150
 
151
        /* Have the dynamic linker use the regular malloc function now */
152
        if (!dl_init) {
153
                dl_init++;
154
                _dl_malloc_function = malloc;
155
        }
156
 
157
        /* Cover the trivial case first */
158
        if (!libname)
159
                return _dl_symbol_tables;
160
 
161
        _dl_map_cache();
162
 
163
        /*
164
         * Try and locate the module we were called from - we
165
         * need this so that we get the correct RPATH.  Note that
166
         * this is the current behavior under Solaris, but the
167
         * ABI+ specifies that we should only use the RPATH from
168
         * the application.  Thus this may go away at some time
169
         * in the future.
170
         */
171
        tfrom = NULL;
172
        for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
173
                tpnt = dpnt->dyn;
174
                if (tpnt->loadaddr < from
175
                                && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
176
                        tfrom = tpnt;
177
        }
178
 
179
        /* Try to load the specified library */
180
#ifdef __SUPPORT_LD_DEBUG__
181
        if(_dl_debug)
182
        _dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
183
#endif
184
        tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname);
185
        if (tpnt == NULL) {
186
                _dl_unmap_cache();
187
                return NULL;
188
        }
189
 
190
        dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
191
        _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
192
        dyn_chain->dyn = tpnt;
193
        dyn_chain->flags = flag;
194
        if (!tpnt->symbol_scope)
195
                tpnt->symbol_scope = dyn_chain;
196
 
197
        dyn_chain->next_handle = _dl_handles;
198
        _dl_handles = rpnt = dyn_chain;
199
 
200
        if (tpnt->init_flag & INIT_FUNCS_CALLED) {
201
            /* If the init and fini stuff has already been run, that means
202
             * the dlopen'd library has already been loaded, and nothing
203
             * further needs to be done. */
204
            return (void *) dyn_chain;
205
        }
206
 
207
 
208
#ifdef __SUPPORT_LD_DEBUG__
209
        if(_dl_debug)
210
        _dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
211
#endif
212
 
213
        for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
214
        {
215
                Elf32_Dyn *dpnt;
216
                char *lpntstr;
217
                for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
218
                        if (dpnt->d_tag == DT_NEEDED) {
219
 
220
                                char *name;
221
                                lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
222
                                        dpnt->d_un.d_val);
223
                                name = _dl_get_last_path_component(lpntstr);
224
 
225
#ifdef __SUPPORT_LD_DEBUG__
226
                                if(_dl_debug)
227
                                _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
228
                                                lpntstr, tcurr->libname);
229
#endif
230
 
231
                                if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) {
232
                                        goto oops;
233
                                }
234
 
235
#if 1
236
//FIXME:  Enabling this is _so_ wrong....
237
                                /* We need global symbol resolution for everything
238
                                 * in the dependent chain */
239
                                dyn_chain->flags |= RTLD_GLOBAL;
240
#endif
241
 
242
                                rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
243
                                _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
244
                                rpnt = rpnt->next;
245
                                if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
246
                                rpnt->dyn = tpnt1;
247
 
248
                        }
249
                }
250
        }
251
 
252
        /*
253
         * OK, now attach the entire chain at the end
254
         */
255
        rpnt->next = _dl_symbol_tables;
256
 
257
#ifdef __mips__
258
        /*
259
         * Relocation of the GOT entries for MIPS have to be done
260
         * after all the libraries have been loaded.
261
         */
262
        _dl_perform_mips_global_got_relocations(tpnt);
263
#endif
264
 
265
#ifdef __SUPPORT_LD_DEBUG__
266
        if(_dl_debug)
267
        _dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
268
#endif
269
        /*
270
         * OK, now all of the kids are tucked into bed in their proper addresses.
271
         * Now we go through and look for REL and RELA records that indicate fixups
272
         * to the GOT tables.  We need to do this in reverse order so that COPY
273
         * directives work correctly */
274
        if (_dl_fixup(dyn_chain->dyn, dyn_chain->flags))
275
                goto oops;
276
 
277
#ifdef __SUPPORT_LD_DEBUG__
278
        if(_dl_debug)
279
        _dl_dprintf(_dl_debug_file, "Beginning dlopen copy fixups\n");
280
#endif
281
        if (_dl_symbol_tables) {
282
                if (_dl_copy_fixups(dyn_chain))
283
                        goto oops;
284
        }
285
 
286
 
287
        /* TODO:  Should we set the protections of all pages back to R/O now ? */
288
 
289
 
290
        /* Notify the debugger we have added some objects. */
291
        _dl_debug_addr->r_state = RT_ADD;
292
        if (_dl_debug_addr) {
293
                dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
294
                if (dl_brk != NULL) {
295
                        _dl_debug_addr->r_state = RT_ADD;
296
                        (*dl_brk) ();
297
 
298
                        _dl_debug_addr->r_state = RT_CONSISTENT;
299
                        (*dl_brk) ();
300
                }
301
        }
302
 
303
#if 0 //def __SUPPORT_LD_DEBUG__
304
        if(_dl_debug)
305
        _dlinfo();
306
#endif
307
 
308
#ifdef __PIC__
309
        /* Find the last library so we can run things in the right order */
310
        for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
311
            ;
312
 
313
        /* Run the ctors and set up the dtors */
314
        for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
315
        {
316
                /* Apparently crt1 for the application is responsible for handling this.
317
                 * We only need to run the init/fini for shared libraries
318
                 */
319
                if (tpnt->libtype == program_interpreter)
320
                        continue;
321
                if (tpnt->libtype == elf_executable)
322
                        continue;
323
                if (tpnt->init_flag & INIT_FUNCS_CALLED)
324
                        continue;
325
                tpnt->init_flag |= INIT_FUNCS_CALLED;
326
 
327
                if (tpnt->dynamic_info[DT_INIT]) {
328
                    void (*dl_elf_func) (void);
329
                    dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
330
                    if (dl_elf_func && *dl_elf_func != NULL) {
331
#ifdef __SUPPORT_LD_DEBUG__
332
                        if(_dl_debug)
333
                        _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
334
#endif
335
                        (*dl_elf_func) ();
336
                    }
337
                }
338
                if (tpnt->dynamic_info[DT_FINI]) {
339
                    void (*dl_elf_func) (void);
340
                    dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
341
                    if (dl_elf_func && *dl_elf_func != NULL) {
342
#ifdef __SUPPORT_LD_DEBUG__
343
                        if(_dl_debug)
344
                        _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
345
#endif
346
                        atexit(dl_elf_func);
347
                    }
348
                }
349
        }
350
#endif
351
        return (void *) dyn_chain;
352
 
353
oops:
354
        /* Something went wrong.  Clean up and return NULL. */
355
        _dl_unmap_cache();
356
        do_dlclose(dyn_chain, 0);
357
        return NULL;
358
}
359
 
360
void *_dlsym(void *vhandle, const char *name)
361
{
362
        struct elf_resolve *tpnt, *tfrom;
363
        struct dyn_elf *handle;
364
        ElfW(Addr) from;
365
        struct dyn_elf *rpnt;
366
        void *ret;
367
 
368
        handle = (struct dyn_elf *) vhandle;
369
 
370
        /* First of all verify that we have a real handle
371
           of some kind.  Return NULL if not a valid handle. */
372
 
373
        if (handle == NULL)
374
                handle = _dl_symbol_tables;
375
        else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
376
                for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
377
                        if (rpnt == handle)
378
                                break;
379
                if (!rpnt) {
380
                        _dl_error_number = LD_BAD_HANDLE;
381
                        return NULL;
382
                }
383
        } else if (handle == RTLD_NEXT) {
384
                /*
385
                 * Try and locate the module we were called from - we
386
                 * need this so that we know where to start searching
387
                 * from.  We never pass RTLD_NEXT down into the actual
388
                 * dynamic loader itself, as it doesn't know
389
                 * how to properly treat it.
390
                 */
391
                from = (ElfW(Addr)) __builtin_return_address(0);
392
 
393
                tfrom = NULL;
394
                for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
395
                        tpnt = rpnt->dyn;
396
                        if (tpnt->loadaddr < from
397
                                && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
398
                                tfrom = tpnt;
399
                                handle = rpnt->next;
400
                        }
401
                }
402
        }
403
 
404
        ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
405
 
406
        /*
407
         * Nothing found.
408
         */
409
        if (!ret)
410
                _dl_error_number = LD_NO_SYMBOL;
411
        return ret;
412
}
413
 
414
int _dlclose(void *vhandle)
415
{
416
        return do_dlclose(vhandle, 1);
417
}
418
 
419
static int do_dlclose(void *vhandle, int need_fini)
420
{
421
        struct dyn_elf *rpnt, *rpnt1;
422
        struct dyn_elf *spnt, *spnt1;
423
        ElfW(Phdr) *ppnt;
424
        struct elf_resolve *tpnt;
425
        int (*dl_elf_fini) (void);
426
        void (*dl_brk) (void);
427
        struct dyn_elf *handle;
428
        unsigned int end;
429
        int i = 0;
430
 
431
        handle = (struct dyn_elf *) vhandle;
432
        rpnt1 = NULL;
433
        for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
434
                if (rpnt == handle) {
435
                        break;
436
                }
437
                rpnt1 = rpnt;
438
        }
439
 
440
        if (!rpnt) {
441
                _dl_error_number = LD_BAD_HANDLE;
442
                return 1;
443
        }
444
 
445
        /* OK, this is a valid handle - now close out the file.
446
         * We check if we need to call fini () on the handle. */
447
        spnt = need_fini ? handle : handle->next;
448
        for (; spnt; spnt = spnt1) {
449
                spnt1 = spnt->next;
450
 
451
                /* We appended the module list to the end - when we get back here,
452
                   quit. The access counts were not adjusted to account for being here. */
453
                if (spnt == _dl_symbol_tables)
454
                        break;
455
                if (spnt->dyn->usage_count == 1
456
                        && spnt->dyn->libtype == loaded_file) {
457
                        tpnt = spnt->dyn;
458
                        /* Apparently crt1 for the application is responsible for handling this.
459
                         * We only need to run the init/fini for shared libraries
460
                         */
461
 
462
                        if (tpnt->dynamic_info[DT_FINI]) {
463
                                dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
464
                                        tpnt->dynamic_info[DT_FINI]);
465
                                (*dl_elf_fini) ();
466
                        }
467
                }
468
        }
469
        if (rpnt1)
470
                rpnt1->next_handle = rpnt->next_handle;
471
        else
472
                _dl_handles = rpnt->next_handle;
473
 
474
        /* OK, this is a valid handle - now close out the file */
475
        for (rpnt = handle; rpnt; rpnt = rpnt1) {
476
                rpnt1 = rpnt->next;
477
 
478
                /* We appended the module list to the end - when we get back here,
479
                   quit. The access counts were not adjusted to account for being here. */
480
                if (rpnt == _dl_symbol_tables)
481
                        break;
482
 
483
                rpnt->dyn->usage_count--;
484
                if (rpnt->dyn->usage_count == 0
485
                        && rpnt->dyn->libtype == loaded_file) {
486
                        tpnt = rpnt->dyn;
487
                        /* Apparently crt1 for the application is responsible for handling this.
488
                         * We only need to run the init/fini for shared libraries
489
                         */
490
#if 0
491
 
492
                        /* We have to do this above, before we start closing objects.
493
                         * Otherwise when the needed symbols for _fini handling are
494
                         * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
495
                        if (tpnt->dynamic_info[DT_FINI]) {
496
                            dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
497
                                (*dl_elf_fini) ();
498
                        }
499
#endif
500
                        end = 0;
501
                        for (i = 0, ppnt = rpnt->dyn->ppnt;
502
                                 i < rpnt->dyn->n_phent; ppnt++, i++) {
503
                                if (ppnt->p_type != PT_LOAD)
504
                                        continue;
505
                                if (end < ppnt->p_vaddr + ppnt->p_memsz)
506
                                        end = ppnt->p_vaddr + ppnt->p_memsz;
507
                        }
508
                        _dl_munmap((void*)rpnt->dyn->loadaddr, end);
509
                        /* Next, remove rpnt->dyn from the loaded_module list */
510
                        if (_dl_loaded_modules == rpnt->dyn) {
511
                                _dl_loaded_modules = rpnt->dyn->next;
512
                                if (_dl_loaded_modules)
513
                                        _dl_loaded_modules->prev = 0;
514
                        } else
515
                                for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
516
                                        if (tpnt->next == rpnt->dyn) {
517
                                                tpnt->next = tpnt->next->next;
518
                                                if (tpnt->next)
519
                                                        tpnt->next->prev = tpnt;
520
                                                break;
521
                                        }
522
                        free(rpnt->dyn->libname);
523
                        free(rpnt->dyn);
524
                }
525
                free(rpnt);
526
        }
527
 
528
 
529
        if (_dl_debug_addr) {
530
            dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
531
            if (dl_brk != NULL) {
532
                _dl_debug_addr->r_state = RT_DELETE;
533
                (*dl_brk) ();
534
 
535
                _dl_debug_addr->r_state = RT_CONSISTENT;
536
                (*dl_brk) ();
537
            }
538
        }
539
 
540
        return 0;
541
}
542
 
543
const char *_dlerror(void)
544
{
545
        const char *retval;
546
 
547
        if (!_dl_error_number)
548
                return NULL;
549
        retval = dl_error_names[_dl_error_number];
550
        _dl_error_number = 0;
551
        return retval;
552
}
553
 
554
/*
555
 * Dump information to stderrr about the current loaded modules
556
 */
557
static char *type[] = { "Lib", "Exe", "Int", "Mod" };
558
 
559
void _dlinfo(void)
560
{
561
        struct elf_resolve *tpnt;
562
        struct dyn_elf *rpnt, *hpnt;
563
 
564
        _dl_dprintf(2, "List of loaded modules\n");
565
        /* First start with a complete list of all of the loaded files. */
566
        for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
567
                _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
568
                        (unsigned) tpnt->loadaddr, (unsigned) tpnt,
569
                        (unsigned) tpnt->symbol_scope,
570
                        type[tpnt->libtype],
571
                        tpnt->usage_count, tpnt->libname);
572
        }
573
 
574
        /* Next dump the module list for the application itself */
575
        _dl_dprintf(2, "\nModules for application (%x):\n",
576
                                 (unsigned) _dl_symbol_tables);
577
        for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
578
                _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
579
 
580
        for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
581
                _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
582
                for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
583
                        _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
584
                                rpnt->dyn->libname);
585
        }
586
}
587
 
588
int _dladdr(void *__address, Dl_info * __dlip)
589
{
590
        struct elf_resolve *pelf;
591
        struct elf_resolve *rpnt;
592
 
593
        _dl_map_cache();
594
 
595
        /*
596
         * Try and locate the module address is in
597
         */
598
        pelf = NULL;
599
 
600
#if 0
601
        _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
602
#endif
603
 
604
        for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
605
                struct elf_resolve *tpnt;
606
 
607
                tpnt = rpnt;
608
#if 0
609
                _dl_dprintf(2, "Module \"%s\" at %x\n",
610
                        tpnt->libname, tpnt->loadaddr);
611
#endif
612
                if (tpnt->loadaddr < (ElfW(Addr)) __address
613
                        && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
614
                    pelf = tpnt;
615
                }
616
        }
617
 
618
        if (!pelf) {
619
                return 0;
620
        }
621
 
622
        /*
623
         * Try and locate the symbol of address
624
         */
625
 
626
        {
627
                char *strtab;
628
                Elf32_Sym *symtab;
629
                int hn, si;
630
                int sf;
631
                int sn = 0;
632
                ElfW(Addr) sa;
633
 
634
                sa = 0;
635
                symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
636
                strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
637
 
638
                sf = 0;
639
                for (hn = 0; hn < pelf->nbucket; hn++) {
640
                        for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
641
                                ElfW(Addr) symbol_addr;
642
 
643
                                symbol_addr = pelf->loadaddr + symtab[si].st_value;
644
                                if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
645
                                        sa = symbol_addr;
646
                                        sn = si;
647
                                        sf = 1;
648
                                }
649
#if 0
650
                                _dl_dprintf(2, "Symbol \"%s\" at %x\n",
651
                                        strtab + symtab[si].st_name, symbol_addr);
652
#endif
653
                        }
654
                }
655
 
656
                if (sf) {
657
                        __dlip->dli_fname = pelf->libname;
658
                        __dlip->dli_fbase = (void *)pelf->loadaddr;
659
                        __dlip->dli_sname = strtab + symtab[sn].st_name;
660
                        __dlip->dli_saddr = (void *)sa;
661
                }
662
                return 1;
663
        }
664
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.