source: mainline/uspace/lib/c/arch/mips32/src/rtld/reloc.c@ 2ca5f632

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2ca5f632 was 2ca5f632, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Integrate arch/ part of rtld into core C library.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup rtld rtld
30 * @brief
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39
40#include <elf_dyn.h>
41#include <symbol.h>
42#include <rtld.h>
43#include <rtld_debug.h>
44
45#include <rtld_arch.h>
46
47void module_process_pre_arch(module_t *m)
48{
49 elf_symbol_t *sym_table;
50 elf_symbol_t *sym_def;
51 elf_symbol_t *sym;
52 uint32_t gotsym;
53 uint32_t lgotno;
54 uint32_t *got;
55 char *str_tab;
56 unsigned i, j;
57
58 uint32_t sym_addr;
59 module_t *dest;
60
61 got = (uint32_t *) m->dyn.plt_got;
62 sym_table = m->dyn.sym_tab;
63 str_tab = m->dyn.str_tab;
64 gotsym = m->dyn.arch.gotsym;
65 lgotno = m->dyn.arch.lgotno;
66
67 DPRINTF("** Relocate GOT entries **\n");
68 DPRINTF("MIPS base = 0x%x\n", m->dyn.arch.base);
69
70 /*
71 * Local entries.
72 */
73 for (i = 0; i < gotsym; i++) {
74 /* FIXME: really subtract MIPS base? */
75 got[i] += m->bias - m->dyn.arch.base;
76 }
77
78 DPRINTF("sym_ent = %d, gotsym = %d\n", m->dyn.arch.sym_no, gotsym);
79 DPRINTF("lgotno = %d\n", lgotno);
80
81 /*
82 * Iterate over GOT-mapped symbol entries.
83 */
84 for (j = gotsym; j < m->dyn.arch.sym_no; j++) {
85 /* Corresponding (global) GOT entry. */
86 i = lgotno + j - gotsym;
87
88 DPRINTF("relocate GOT entry %d\n", i);
89// getchar();
90// getchar();
91
92 sym = &sym_table[j];
93 if (ELF32_R_TYPE(sym->st_info) == STT_FUNC) {
94 if (sym->st_shndx == SHN_UNDEF) {
95 if (sym->st_value == 0) {
96 /* 1 */
97 } else {
98 if (got[i] == sym->st_value) {
99 /* 2 */
100 DPRINTF("(2)\n");
101 got[i] += m->bias - m->dyn.arch.base;
102 continue;
103 } else {
104 /* 3 */
105 DPRINTF("(3)\n");
106 got[i] = sym->st_value + m->bias - m->dyn.arch.base;
107 continue;
108 }
109 }
110 } else {
111 /* 2 */
112 DPRINTF("(2)\n");
113 got[i] += m->bias - m->dyn.arch.base;
114 continue;
115 }
116 } else {
117 if (sym->st_shndx == SHN_UNDEF ||
118 sym->st_shndx == SHN_COMMON) {
119 /* 1 */
120 } else {
121 /* 1 */
122 }
123 }
124
125 DPRINTF("(1) symbol name='%s'\n", str_tab + sym->st_name);
126 sym_def = symbol_def_find(str_tab + sym->st_name, m, &dest);
127 if (sym_def) {
128 sym_addr = (uintptr_t) symbol_get_addr(sym_def, dest);
129 DPRINTF("symbol definition found, addr=0x%x\n", sym_addr);
130 } else {
131 DPRINTF("symbol definition not found\n");
132 continue;
133 }
134 DPRINTF("write 0x%x at 0x%x\n", sym_addr, (uint32_t) &got[i]);
135 got[i] = sym_addr;
136 }
137
138 DPRINTF("** Done **\n");
139}
140
141/**
142 * Process (fixup) all relocations in a relocation table.
143 */
144void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
145{
146 unsigned i;
147
148 size_t rt_entries;
149 size_t r_offset;
150 elf_word r_info;
151 unsigned rel_type;
152 elf_word sym_idx;
153 uintptr_t sym_addr;
154
155 elf_symbol_t *sym_table;
156 elf_symbol_t *sym;
157 uint32_t *r_ptr;
158/* uint16_t *r_ptr16;*/
159 char *str_tab;
160
161 elf_symbol_t *sym_def;
162 module_t *dest;
163
164 uint32_t *got;
165 uint32_t gotsym;
166 uint32_t lgotno;
167 uint32_t ea;
168
169 DPRINTF("parse relocation table\n");
170
171 sym_table = m->dyn.sym_tab;
172 rt_entries = rt_size / sizeof(elf_rela_t);
173 str_tab = m->dyn.str_tab;
174 got = (uint32_t *) m->dyn.plt_got;
175 gotsym = m->dyn.arch.gotsym;
176 lgotno = m->dyn.arch.lgotno;
177
178 DPRINTF("got=0x%x, gotsym=%d\n", (uintptr_t) got, gotsym);
179
180 DPRINTF("address: 0x%x, entries: %d\n", (uintptr_t)rt, rt_entries);
181
182 for (i = 0; i < rt_entries; ++i) {
183 DPRINTF("symbol %d: ", i);
184 r_offset = rt[i].r_offset;
185 r_info = rt[i].r_info;
186
187 sym_idx = ELF32_R_SYM(r_info);
188 sym = &sym_table[sym_idx];
189
190 DPRINTF("name '%s', value 0x%x, size 0x%x\n",
191 str_tab + sym->st_name,
192 sym->st_value,
193 sym->st_size);
194
195 rel_type = ELF32_R_TYPE(r_info);
196 r_ptr = (uint32_t *)(r_offset + m->bias);
197 /*r_ptr16 = (uint16_t *)(r_offset + m->bias);*/
198
199 if (sym->st_name != 0) {
200 DPRINTF("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset);
201 DPRINTF("dest name: '%s'\n", dest->dyn.soname);
202 DPRINTF("dest bias: 0x%x\n", dest->bias);
203 if (sym_def) {
204 sym_addr = (uintptr_t) symbol_get_addr(sym_def,
205 dest);
206 DPRINTF("symbol definition found, addr=0x%x\n", sym_addr);
207 } else {
208 DPRINTF("symbol definition not found\n");
209 continue;
210 }
211 } else {
212 sym_def = NULL;
213 sym_addr = 0;
214 }
215
216 DPRINTF("switch(%u)\n", rel_type);
217
218 switch (rel_type) {
219 case R_MIPS_NONE:
220 DPRINTF("Ignoring R_MIPS_NONE\n");
221 break;
222
223 case R_MIPS_REL32:
224 DPRINTF("fixup R_MIPS_REL32 (r - ea + s)\n");
225 if (sym_idx < gotsym)
226 ea = sym_addr;
227 else
228 ea = got[lgotno + sym_idx - gotsym];
229
230 *r_ptr += sym_addr - ea;
231 DPRINTF("p = 0x%x, val := 0x%x\n", (uint32_t) r_ptr,
232 *r_ptr);
233// getchar();
234 break;
235
236 /* No other non-TLS relocation types should appear. */
237
238 case R_MIPS_TLS_DTPMOD32:
239 /*
240 * We can ignore this as long as the only module
241 * with TLS variables is libc.so.
242 */
243 DPRINTF("Ignoring R_MIPS_DTPMOD32\n");
244 break;
245
246 default:
247 printf("Error: Unknown relocation type %d.\n",
248 rel_type);
249 exit(1);
250 break;
251 }
252 }
253
254
255 printf("relocation done\n");
256}
257
258void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
259{
260 /* Unused */
261 (void)m; (void)rt; (void)rt_size;
262}
263
264/** @}
265 */
Note: See TracBrowser for help on using the repository browser.