source: mainline/uspace/lib/c/arch/ia64/src/rtld/reloc.c

Last change on this file was a949f4a, checked in by Jiri Svoboda <jiri@…>, 6 years ago

Dynamic linking on IA-64 (WIP)

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[a949f4a]1/*
2 * Copyright (c) 2019 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 libcia64
30 * @brief
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <inttypes.h>
40#include <str.h>
41
42#include <libarch/rtld/elf_dyn.h>
43#include <rtld/symbol.h>
44#include <rtld/rtld.h>
45#include <rtld/rtld_debug.h>
46#include <rtld/rtld_arch.h>
47
48static void fill_fun_desc(uintptr_t *, uintptr_t, uintptr_t);
49
50void module_process_pre_arch(module_t *m)
51{
52 /* Unused */
53}
54
55/**
56 * Process (fixup) all relocations in a relocation table with implicit addends.
57 */
58void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
59{
60
61 DPRINTF("rel table address: 0x%zx, size: %zd\n", (uintptr_t)rt, rt_size);
62 /* Unused */
63 (void)m;
64 (void)rt;
65 (void)rt_size;
66}
67
68static uintptr_t get_module_gp(module_t *m)
69{
70#if 0
71 printf("get_module_gp: m=%p m->bias=%zu m->dyn.plt_got=%zu\n",
72 m, m->bias, (uintptr_t) m->dyn.plt_got);
73#endif
74 return (uintptr_t) m->dyn.plt_got;
75}
76
77/**
78 * Process (fixup) all relocations in a relocation table with explicit addends.
79 */
80void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
81{
82 unsigned i;
83
84 size_t rt_entries;
85 size_t r_offset;
86 size_t r_addend;
87 elf_xword r_info;
88 unsigned rel_type;
89 elf_word sym_idx;
90 uintptr_t sym_addr;
91
92 elf_symbol_t *sym_table;
93 elf_symbol_t *sym;
94 uintptr_t *r_ptr;
95 uintptr_t sym_size;
96 char *str_tab;
97
98 elf_symbol_t *sym_def;
99 module_t *dest;
100
101 DPRINTF("parse relocation table\n");
102
103 sym_table = m->dyn.sym_tab;
104 rt_entries = rt_size / sizeof(elf_rela_t);
105 str_tab = m->dyn.str_tab;
106
107 DPRINTF("rel table address: 0x%zx, entries: %zd\n", (uintptr_t)rt, rt_entries);
108
109 for (i = 0; i < rt_entries; ++i) {
110#if 0
111 DPRINTF("symbol %d: ", i);
112#endif
113 r_offset = rt[i].r_offset;
114 r_info = rt[i].r_info;
115 r_addend = rt[i].r_addend;
116
117 sym_idx = ELF64_R_SYM(r_info);
118 sym = &sym_table[sym_idx];
119#if 0
120 DPRINTF("r sym: name '%s', value 0x%zx, size 0x%zx, binding 0x%x\n",
121 str_tab + sym->st_name,
122 sym->st_value,
123 sym->st_size,
124 elf_st_bind(sym->st_info));
125#endif
126 rel_type = ELF64_R_TYPE(r_info);
127 r_ptr = (uintptr_t *)(r_offset + m->bias);
128
129 if (elf_st_bind(sym->st_info) == STB_LOCAL) {
130 sym_def = sym;
131 dest = m;
132 sym_addr = (uintptr_t)
133 symbol_get_addr(sym_def, dest, NULL);
134 DPRINTF("Resolved local symbol, addr=0x%zx\n", sym_addr);
135 } else if (sym->st_name != 0) {
136 DPRINTF("rel_type: %x, rel_offset: 0x%zx\n", rel_type, r_offset);
137 sym_def = symbol_def_find(str_tab + sym->st_name,
138 m, ssf_none, &dest);
139 DPRINTF("dest name: '%s'\n", dest->dyn.soname);
140 DPRINTF("dest bias: 0x%zx\n", dest->bias);
141 if (sym_def) {
142 sym_addr = (uintptr_t)
143 symbol_get_addr(sym_def, dest, NULL);
144 DPRINTF("symbol definition found, value=0x%zx addr=0x%zx\n", sym_def->st_value, sym_addr);
145 } else {
146 printf("Definition of '%s' not found.\n",
147 str_tab + sym->st_name);
148 continue;
149 }
150 } else {
151 sym_addr = 0;
152 sym_def = NULL;
153
154 /*
155 * DTPMOD with null st_name should return the index
156 * of the current module.
157 */
158 dest = m;
159 }
160
161 switch (rel_type) {
162 case R_IA_64_DIR64LSB:
163 DPRINTF("fixup R_IA_DIR64LSB (S+A)\n");
164 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr,
165 sym_addr + r_addend);
166 *r_ptr = sym_addr + r_addend;
167 DPRINTF("OK\n");
168 break;
169
170 case R_IA_64_FPTR64LSB:
171 // FIXME ?????
172 DPRINTF("fixup R_IA_FPTR64LSB (@fptr(S+A))\n");
173 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr,
174 sym_addr + r_addend);
175 *r_ptr = sym_addr + r_addend;
176 DPRINTF("OK\n");
177 break;
178 case R_IA_64_REL64LSB:
179 DPRINTF("fixup R_IA_REL64LSB (BD+A)\n");
180 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr,
181 dest->bias + r_addend);
182 *r_ptr = dest->bias + r_addend;
183 DPRINTF("OK\n");
184 break;
185
186 case R_IA_64_IPLTLSB:
187 DPRINTF("fixup R_IA_64_IPLTLSB\n");
188 DPRINTF("r_offset=0x%zx r_addend=0x%zx\n",
189 r_offset, r_addend);
190
191 sym_size = sym->st_size;
192 if (sym_size != sym_def->st_size) {
193 printf("Warning: Mismatched symbol sizes.\n");
194 /* Take the lower value. */
195 if (sym_size > sym_def->st_size)
196 sym_size = sym_def->st_size;
197 }
198
199 DPRINTF("symbol='%s'\n", str_tab + sym->st_name);
200 DPRINTF("sym_addr = 0x%zx\n", sym_addr);
201 DPRINTF("gp = 0x%zx\n", get_module_gp(dest));
202 DPRINTF("r_offset=0x%zx\n", r_offset);
203
204 /*
205 * Initialize function descriptor entry with the
206 * address of the function and the value of the
207 * global pointer.
208 */
209 fill_fun_desc(r_ptr, sym_addr, get_module_gp(dest));
210
211 DPRINTF("OK\n");
212 break;
213
214 case R_IA_64_DTPMOD64LSB:
215 DPRINTF("fixup R_IA_64_DTPMOD64LSB\n");
216 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, (size_t)dest->id);
217 *r_ptr = dest->id;
218 DPRINTF("OK\n");
219 break;
220
221 case R_IA_64_DTPREL64LSB:
222 DPRINTF("fixup R_IA_64_DTPREL64LSB\n");
223 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, sym_def->st_value);
224 *r_ptr = sym_def->st_value;
225 DPRINTF("OK\n");
226 break;
227
228 default:
229 printf("Error: Unknown relocation type %d\n",
230 rel_type);
231 exit(1);
232 }
233
234 }
235}
236
237static void fill_fun_desc(uintptr_t *fdesc, uintptr_t faddr, uintptr_t gp)
238{
239 fdesc[0] = faddr;
240 fdesc[1] = gp;
241}
242
243#include <rtld/rtld_arch.h>
244
245/** Get the adress of a function.
246 *
247 * On IA-64 we actually return the address of the function descriptor.
248 *
249 * @param sym Symbol
250 * @param m Module in which the symbol is located
251 * @return Address of function
252 */
253void *func_get_addr(elf_symbol_t *sym, module_t *m)
254{
255 void *fa;
256 uintptr_t *fdesc;
257
258#if 0
259 printf("func_get_addr: name='%s'\n", m->dyn.str_tab + sym->st_name);
260#endif
261 fa = symbol_get_addr(sym, m, __tcb_get());
262 if (fa == NULL)
263 return NULL;
264
265 fdesc = malloc(16);
266 if (fdesc == NULL)
267 return NULL;
268
269 fill_fun_desc(fdesc, (uintptr_t)fa, get_module_gp(m));
270#if 0
271 printf("-> fun_desc=%p\n", fdesc);
272#endif
273 return fdesc;
274}
275
276/** @}
277 */
Note: See TracBrowser for help on using the repository browser.