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