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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [ldso/] [ldso/] [hash.c] - Blame information for rev 1766

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

Line No. Rev Author Line
1 1325 phoenix
/* vi: set sw=4 ts=4: */
2
/* Program to load an ELF binary on a linux system, and run it
3
 * after resolving ELF shared library symbols
4
 *
5
 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
6
 *                              David Engel, Hongjiu Lu and Mitch D'Souza
7
 * Copyright (C) 2001-2002, Erik Andersen
8
 *
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. The name of the above contributors may not be
17
 *    used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
 
33
 
34
/* Various symbol table handling functions, including symbol lookup */
35
 
36
/*
37
 * This is the start of the linked list that describes all of the files present
38
 * in the system with pointers to all of the symbol, string, and hash tables,
39
 * as well as all of the other good stuff in the binary.
40
 */
41
 
42
struct elf_resolve *_dl_loaded_modules = NULL;
43
 
44
/*
45
 * This is the list of modules that are loaded when the image is first
46
 * started.  As we add more via dlopen, they get added into other
47
 * chains.
48
 */
49
struct dyn_elf *_dl_symbol_tables = NULL;
50
 
51
/*
52
 * This is the list of modules that are loaded via dlopen.  We may need
53
 * to search these for RTLD_GLOBAL files.
54
 */
55
struct dyn_elf *_dl_handles = NULL;
56
 
57
 
58
/*
59
 * This is the hash function that is used by the ELF linker to generate
60
 * the hash table that each executable and library is required to
61
 * have.  We need it to decode the hash table.
62
 */
63
 
64
unsigned long _dl_elf_hash(const char *name)
65
{
66
        unsigned long hash = 0;
67
        unsigned long tmp;
68
 
69
        while (*name) {
70
                hash = (hash << 4) + *name++;
71
                if ((tmp = hash & 0xf0000000))
72
                        hash ^= tmp >> 24;
73
                hash &= ~tmp;
74
        };
75
        return hash;
76
}
77
 
78
/*
79
 * Check to see if a library has already been added to the hash chain.
80
 */
81
struct elf_resolve *_dl_check_hashed_files(const char *libname)
82
{
83
        struct elf_resolve *tpnt;
84
        int len = _dl_strlen(libname);
85
 
86
        for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
87
                if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
88
                        (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
89
                        return tpnt;
90
        }
91
 
92
        return NULL;
93
}
94
 
95
/*
96
 * We call this function when we have just read an ELF library or executable.
97
 * We add the relevant info to the symbol chain, so that we can resolve all
98
 * externals properly.
99
 */
100
 
101
struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
102
        char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
103
        unsigned long dynamic_size)
104
{
105
        unsigned long *hash_addr;
106
        struct elf_resolve *tpnt;
107
        int i;
108
 
109
        if (!_dl_loaded_modules) {
110
                tpnt = _dl_loaded_modules =
111
                    (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
112
                _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
113
        } else {
114
                tpnt = _dl_loaded_modules;
115
                while (tpnt->next)
116
                        tpnt = tpnt->next;
117
                tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
118
                _dl_memset(tpnt->next, 0, sizeof(struct elf_resolve));
119
                tpnt->next->prev = tpnt;
120
                tpnt = tpnt->next;
121
        };
122
 
123
        tpnt->next = NULL;
124
        tpnt->init_flag = 0;
125
        tpnt->libname = _dl_strdup(libname);
126
        tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
127
        tpnt->dynamic_size = dynamic_size;
128
        tpnt->libtype = loaded_file;
129
 
130
        if (dynamic_info[DT_HASH] != 0) {
131
                hash_addr = (unsigned long *) (intptr_t)(dynamic_info[DT_HASH] + loadaddr);
132
                tpnt->nbucket = *hash_addr++;
133
                tpnt->nchain = *hash_addr++;
134
                tpnt->elf_buckets = hash_addr;
135
                hash_addr += tpnt->nbucket;
136
                tpnt->chains = hash_addr;
137
        }
138
        tpnt->loadaddr = (ElfW(Addr))loadaddr;
139
        for (i = 0; i < 24; i++)
140
                tpnt->dynamic_info[i] = dynamic_info[i];
141
#ifdef __mips__
142
        {
143
                Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
144
 
145
                while(dpnt->d_tag) {
146
                        if (dpnt->d_tag == DT_MIPS_GOTSYM)
147
                                tpnt->mips_gotsym = dpnt->d_un.d_val;
148
                        if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
149
                                tpnt->mips_local_gotno = dpnt->d_un.d_val;
150
                        if (dpnt->d_tag == DT_MIPS_SYMTABNO)
151
                                tpnt->mips_symtabno = dpnt->d_un.d_val;
152
                        dpnt++;
153
                }
154
        }
155
#endif
156
        return tpnt;
157
}
158
 
159
 
160
/*
161
 * This function resolves externals, and this is either called when we process
162
 * relocations or when we call an entry in the PLT table for the first time.
163
 */
164
 
165
char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
166
        struct elf_resolve *f_tpnt, enum caller_type caller_type)
167
{
168
        struct elf_resolve *tpnt;
169
        int si;
170
        char *pnt;
171
        int pass;
172
        char *strtab;
173
        Elf32_Sym *symtab;
174
        unsigned long elf_hash_number, hn;
175
        char *weak_result;
176
        struct elf_resolve *first_def;
177
        struct dyn_elf *rpnt, first;
178
        char *data_result = 0;           /* nakao */
179
 
180
        weak_result = 0;
181
        elf_hash_number = _dl_elf_hash(name);
182
 
183
        /* A quick little hack to make sure that any symbol in the executable
184
           will be preferred to one in a shared library.  This is necessary so
185
           that any shared library data symbols referenced in the executable
186
           will be seen at the same address by the executable, shared libraries
187
           and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
188
        if (_dl_symbol_tables && !caller_type && rpnt1) {
189
                first = (*_dl_symbol_tables);
190
                first.next = rpnt1;
191
                rpnt1 = (&first);
192
        }
193
 
194
        /*
195
         * The passes are so that we can first search the regular symbols
196
         * for whatever module was specified, and then search anything
197
         * loaded with RTLD_GLOBAL.  When pass is 1, it means we are just
198
         * starting the first dlopened module, and anything above that
199
         * is just the next one in the chain.
200
         */
201
        for (pass = 0; (1 == 1); pass++) {
202
 
203
                /*
204
                 * If we are just starting to search for RTLD_GLOBAL, setup
205
                 * the pointer for the start of the search.
206
                 */
207
                if (pass == 1) {
208
                        rpnt1 = _dl_handles;
209
                }
210
 
211
                /*
212
                 * Anything after this, we need to skip to the next module.
213
                 */
214
                else if (pass >= 2) {
215
                        rpnt1 = rpnt1->next_handle;
216
                }
217
 
218
                /*
219
                 * Make sure we still have a module, and make sure that this
220
                 * module was loaded with RTLD_GLOBAL.
221
                 */
222
                if (pass != 0) {
223
                        if (rpnt1 == NULL)
224
                                break;
225
                        if ((rpnt1->flags & RTLD_GLOBAL) == 0)
226
                                continue;
227
                }
228
 
229
                for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
230
                        tpnt = rpnt->dyn;
231
 
232
                        /*
233
                         * The idea here is that if we are using dlsym, we want to
234
                         * first search the entire chain loaded from dlopen, and
235
                         * return a result from that if we found anything.  If this
236
                         * fails, then we continue the search into the stuff loaded
237
                         * when the image was activated.  For normal lookups, we start
238
                         * with rpnt == NULL, so we should never hit this.
239
                         */
240
                        if (tpnt->libtype == elf_executable && weak_result != 0) {
241
                                break;
242
                        }
243
 
244
                        /*
245
                         * Avoid calling .urem here.
246
                         */
247
                        do_rem(hn, elf_hash_number, tpnt->nbucket);
248
                        symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
249
                        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
250
                        /*
251
                         * This crap is required because the first instance of a
252
                         * symbol on the chain will be used for all symbol references.
253
                         * Thus this instance must be resolved to an address that
254
                         * contains the actual function,
255
                         */
256
 
257
                        first_def = NULL;
258
 
259
                        for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) {
260
                                pnt = strtab + symtab[si].st_name;
261
 
262
                                if (_dl_strcmp(pnt, name) == 0 &&
263
                                    symtab[si].st_value != 0)
264
                                {
265
                                  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
266
                                       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
267
                                       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
268
                                      symtab[si].st_shndx != SHN_UNDEF) {
269
 
270
                                        /* Here we make sure that we find a module where the symbol is
271
                                         * actually defined.
272
                                         */
273
 
274
                                        if (f_tpnt) {
275
                                                if (!first_def)
276
                                                        first_def = tpnt;
277
                                                if (first_def == f_tpnt
278
                                                        && symtab[si].st_shndx == 0)
279
                                                        continue;
280
                                        }
281
 
282
                                        switch (ELF32_ST_BIND(symtab[si].st_info)) {
283
                                        case STB_GLOBAL:
284
                                                if (tpnt->libtype != elf_executable &&
285
                                                        ELF32_ST_TYPE(symtab[si].st_info)
286
                                                        == STT_NOTYPE)
287
                                                {       /* nakao */
288
                                                        data_result = (char *)tpnt->loadaddr +
289
                                                            symtab[si].st_value;        /* nakao */
290
                                                        break;  /* nakao */
291
                                                } else  /* nakao */
292
                                                        return (char*)tpnt->loadaddr + symtab[si].st_value;
293
                                        case STB_WEAK:
294
                                                if (!weak_result)
295
                                                        weak_result = (char *)tpnt->loadaddr + symtab[si].st_value;
296
                                                break;
297
                                        default:        /* Do local symbols need to be examined? */
298
                                                break;
299
                                        }
300
                                  }
301
#ifndef __mips__
302
                                  /*
303
                                   * References to the address of a function from an executable file and
304
                                   * the shared objects associated with it might not resolve to the same
305
                                   * value. To allow comparisons of function addresses we must resolve
306
                                   * to the address of the plt entry of the executable instead of the
307
                                   * real function address.
308
                                   * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
309
                                   * Adresses)
310
                                   */
311
                                  if (resolver != caller_type &&
312
                                      NULL==f_tpnt && /*trick: don't  handle R_??_JMP_SLOT reloc type*/
313
                                      tpnt->libtype == elf_executable &&
314
                                      ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
315
                                      symtab[si].st_shndx == SHN_UNDEF)
316
                                  {
317
                                      return (char*)symtab[si].st_value;
318
                                  }
319
#endif
320
                                }
321
                        }
322
                }
323
        }
324
        if (data_result)
325
                return data_result;             /* nakao */
326
        return weak_result;
327
}

powered by: WebSVN 2.1.0

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