Add protected symbols support for all architectures
[uclibc-ng.git] / ldso / ldso / avr32 / elfinterp.c
blob2d0dbf366e2b7312e1f7ff8ec7f0d5584b96eab0
1 /*
2 * AVR32 ELF shared library loader suppport
4 * Copyright (C) 2004-2006 Atmel Corporation
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. The name of the above contributors may not be
14 * used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)
33 * AVR32 currently does not do lazy relocation.
35 #if 0
36 struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
37 Elf32_Sym *sym;
38 unsigned long local_gotno;
39 unsigned long gotsym;
40 unsigned long new_addr;
41 char *strtab, *symname;
42 unsigned long *entry;
43 unsigned long sym_index = got_offset / 4;
45 local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
46 gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
48 sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
49 + sym_index;
50 strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
51 symname = strtab + sym->st_name;
53 new_addr = (unsigned long) _dl_find_hash(symname,
54 tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
56 entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
57 *entry = new_addr;
59 return new_addr;
60 #endif
61 return 0;
64 static int
65 _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
66 unsigned long rel_addr, unsigned long rel_size,
67 int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
68 Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
70 Elf32_Sym *symtab;
71 Elf32_Rela *rpnt;
72 char *strtab;
73 int i;
75 rpnt = (Elf32_Rela *)rel_addr;
76 rel_size /= sizeof(Elf32_Rela);
77 symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
78 strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
80 for (i = 0; i < rel_size; i++, rpnt++) {
81 int symtab_index, res;
83 symtab_index = ELF32_R_SYM(rpnt->r_info);
85 debug_sym(symtab, strtab, symtab_index);
86 debug_reloc(symtab, strtab, rpnt);
88 res = reloc_func(tpnt, scope, rpnt, symtab, strtab);
90 if (res == 0)
91 continue;
93 _dl_dprintf(2, "\n%s: ", _dl_progname);
95 if (symtab_index)
96 _dl_dprintf(2, "symbol '%s': ",
97 strtab + symtab[symtab_index].st_name);
99 if (res < 0) {
100 int reloc_type = ELF32_R_TYPE(rpnt->r_info);
101 #if defined(__SUPPORT_LD_DEBUG__)
102 _dl_dprintf(2, "can't handle reloc type %s\n",
103 _dl_reltypes(reloc_type));
104 #else
105 _dl_dprintf(2, "can't handle reloc type %x\n",
106 reloc_type);
107 #endif
108 _dl_exit(-res);
109 } else {
110 _dl_dprintf(2, "can't resolve symbol\n");
111 return res;
115 return 0;
118 static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
119 Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)
121 int reloc_type;
122 int symtab_index;
123 char *symname;
124 unsigned long *reloc_addr;
125 unsigned long symbol_addr;
126 #if defined(__SUPPORT_LD_DEBUG__)
127 unsigned long old_val;
128 #endif
129 struct symbol_ref sym_ref;
131 reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
132 reloc_type = ELF32_R_TYPE(rpnt->r_info);
133 symtab_index = ELF32_R_SYM(rpnt->r_info);
134 symbol_addr = 0;
135 sym_ref.sym = &symtab[symtab_index];
136 sym_ref.tpnt = NULL;
137 symname = strtab + symtab[symtab_index].st_name;
139 if (symtab_index) {
140 symbol_addr = (unsigned long)
141 _dl_find_hash(symname, scope, tpnt,
142 elf_machine_type_class(reloc_type), &sym_ref);
144 /* Allow undefined references to weak symbols */
145 if (!symbol_addr &&
146 ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
147 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
148 _dl_progname, symname);
149 return 0;
153 #if defined(__SUPPORT_LD_DEBUG__)
154 old_val = *reloc_addr;
155 #endif
156 switch (reloc_type) {
157 case R_AVR32_NONE:
158 break;
159 case R_AVR32_GLOB_DAT:
160 case R_AVR32_JMP_SLOT:
161 *reloc_addr = symbol_addr + rpnt->r_addend;
162 break;
163 case R_AVR32_RELATIVE:
164 *reloc_addr = (unsigned long)tpnt->loadaddr
165 + rpnt->r_addend;
166 break;
167 default:
168 return -1;
171 #if defined(__SUPPORT_LD_DEBUG__)
172 if (_dl_debug_reloc && _dl_debug_detail)
173 _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
174 old_val, *reloc_addr);
175 #endif
177 return 0;
180 void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
181 unsigned long rel_addr,
182 unsigned long rel_size)
184 /* TODO: Might want to support this in order to get faster
185 * startup times... */
188 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
189 unsigned long rel_addr,
190 unsigned long rel_size)
192 return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
193 _dl_do_reloc);