1 /* vi: set sw=4 ts=4: */
3 * Program to load an ELF binary on a linux system, and run it
4 * after resolving ELF shared library symbols
6 * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
7 * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
8 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
9 * David Engel, Hongjiu Lu and Mitch D'Souza
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
34 /* Various symbol table handling functions, including symbol lookup */
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.
41 struct elf_resolve *_dl_loaded_modules = NULL;
44 * This is the list of modules that are loaded when the image is first
45 * started. As we add more via dlopen, they get added into other
48 struct dyn_elf *_dl_symbol_tables = NULL;
51 * This is the list of modules that are loaded via dlopen. We may need
52 * to search these for RTLD_GLOBAL files.
54 struct dyn_elf *_dl_handles = NULL;
57 /* This is the hash function that is used by the ELF linker to generate the
58 * hash table that each executable and library is required to have. We need
59 * it to decode the hash table. */
60 static inline Elf_Symndx _dl_elf_hash(const char *name)
66 hash = (hash << 4) + *name++;
67 tmp = hash & 0xf0000000;
68 /* The algorithm specified in the ELF ABI is as follows:
72 But the following is equivalent and a lot
73 faster, especially on modern processors. */
81 * We call this function when we have just read an ELF library or executable.
82 * We add the relevant info to the symbol chain, so that we can resolve all
85 struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
86 DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
87 attribute_unused unsigned long dynamic_size)
89 Elf_Symndx *hash_addr;
90 struct elf_resolve *tpnt;
93 if (!_dl_loaded_modules) {
94 tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
95 _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
97 tpnt = _dl_loaded_modules;
100 tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
101 _dl_memset(tpnt->next, 0, sizeof(struct elf_resolve));
102 tpnt->next->prev = tpnt;
108 tpnt->libname = _dl_strdup(libname);
109 tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
110 tpnt->libtype = loaded_file;
112 if (dynamic_info[DT_HASH] != 0) {
113 hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH];
114 tpnt->nbucket = *hash_addr++;
115 tpnt->nchain = *hash_addr++;
116 tpnt->elf_buckets = hash_addr;
117 hash_addr += tpnt->nbucket;
118 tpnt->chains = hash_addr;
120 tpnt->loadaddr = loadaddr;
121 for (i = 0; i < DYNAMIC_SIZE; i++)
122 tpnt->dynamic_info[i] = dynamic_info[i];
128 * This function resolves externals, and this is either called when we process
129 * relocations or when we call an entry in the PLT table for the first time.
131 char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class)
133 struct elf_resolve *tpnt;
137 unsigned long elf_hash_number, hn;
138 const ElfW(Sym) *sym;
139 char *weak_result = NULL;
141 elf_hash_number = _dl_elf_hash(name);
143 for (; rpnt; rpnt = rpnt->next) {
146 if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
150 struct init_fini_list *tmp;
152 for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
153 if (tmp->tpnt == tpnt)
160 /* Don't search the executable when resolving a copy reloc. */
161 if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
164 /* Avoid calling .urem here. */
165 do_rem(hn, elf_hash_number, tpnt->nbucket);
166 symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
167 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
169 for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
172 if (type_class & (sym->st_shndx == SHN_UNDEF))
174 if (_dl_strcmp(strtab + sym->st_name, name) != 0)
176 if (sym->st_value == 0)
178 if (ELF_ST_TYPE(sym->st_info) > STT_FUNC)
181 switch (ELF_ST_BIND(sym->st_info)) {
184 /* Perhaps we should support old style weak symbol handling
185 * per what glibc does when you export LD_DYNAMIC_WEAK */
187 weak_result = (char *) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value);
191 return (char*) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value);
192 default: /* Local symbols not handled here */