source: mainline/uspace/lib/c/arch/amd64/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: 6.4 KB
Line 
1/*
2 * Copyright (c) 2016 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 libcamd64
30 * @brief
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <mem.h>
38#include <stdio.h>
39#include <stdlib.h>
40
41#include <libarch/rtld/elf_dyn.h>
42#include <rtld/symbol.h>
43#include <rtld/rtld.h>
44#include <rtld/rtld_debug.h>
45#include <rtld/rtld_arch.h>
46
47void module_process_pre_arch(module_t *m)
48{
49 /* Unused */
50}
51
52/**
53 * Process (fixup) all relocations in a relocation table with implicit addends.
54 */
55void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
56{
57
58 DPRINTF("rel table address: 0x%zx, size: %zd\n", (uintptr_t)rt, rt_size);
59 /* Unused */
60 (void)m;
61 (void)rt;
62 (void)rt_size;
63}
64
65/**
66 * Process (fixup) all relocations in a relocation table with explicit addends.
67 */
68void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
69{
70 unsigned i;
71
72 size_t rt_entries;
73 size_t r_offset;
74 size_t r_addend;
75 elf_xword r_info;
76 unsigned rel_type;
77 elf_word sym_idx;
78 uintptr_t sym_addr;
79
80 elf_symbol_t *sym_table;
81 elf_symbol_t *sym;
82 uintptr_t *r_ptr;
83 uint32_t *r_ptr32;
84 uintptr_t sym_size;
85 char *str_tab;
86
87 elf_symbol_t *sym_def;
88 module_t *dest;
89
90 DPRINTF("parse relocation table\n");
91
92 sym_table = m->dyn.sym_tab;
93 rt_entries = rt_size / sizeof(elf_rela_t);
94 str_tab = m->dyn.str_tab;
95
96 DPRINTF("rel table address: 0x%zx, entries: %zd\n", (uintptr_t)rt, rt_entries);
97
98 for (i = 0; i < rt_entries; ++i) {
99#if 0
100 DPRINTF("symbol %d: ", i);
101#endif
102 r_offset = rt[i].r_offset;
103 r_info = rt[i].r_info;
104 r_addend = rt[i].r_addend;
105
106 sym_idx = ELF64_R_SYM(r_info);
107 sym = &sym_table[sym_idx];
108
109#if 0
110 DPRINTF("name '%s', value 0x%x, size 0x%x\n",
111 str_tab + sym->st_name,
112 sym->st_value,
113 sym->st_size);
114#endif
115 rel_type = ELF64_R_TYPE(r_info);
116 r_ptr = (uintptr_t *)(r_offset + m->bias);
117 r_ptr32 = (uint32_t *)r_ptr;
118
119 if (sym->st_name != 0) {
120 DPRINTF("rel_type: %x, rel_offset: 0x%zx\n", rel_type, r_offset);
121 sym_def = symbol_def_find(str_tab + sym->st_name,
122 m, ssf_none, &dest);
123 DPRINTF("dest name: '%s'\n", dest->dyn.soname);
124 DPRINTF("dest bias: 0x%zx\n", dest->bias);
125 if (sym_def) {
126 sym_addr = (uintptr_t)
127 symbol_get_addr(sym_def, dest, NULL);
128 DPRINTF("symbol definition found, value=0x%zx addr=0x%zx\n", sym_def->st_value, sym_addr);
129 } else {
130 printf("Definition of '%s' not found.\n",
131 str_tab + sym->st_name);
132 continue;
133 }
134 } else {
135 sym_addr = 0;
136 sym_def = NULL;
137
138 /*
139 * DTPMOD with null st_name should return the index
140 * of the current module.
141 */
142 dest = m;
143 }
144
145 switch (rel_type) {
146 case R_X86_64_64:
147 DPRINTF("fixup R_X86_64_64 (S+A)\n");
148 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, sym_addr + r_addend);
149 *r_ptr = sym_addr + r_addend;
150 DPRINTF("OK\n");
151 break;
152
153 case R_X86_64_PC32:
154 DPRINTF("fixup R_X86_64_PC32 (S+A-P)\n");
155 DPRINTF("(32)*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, sym_addr + r_addend - (uintptr_t) r_ptr);
156 *r_ptr32 = sym_addr + r_addend - (uintptr_t) r_ptr;
157 DPRINTF("OK\n");
158 break;
159
160 case R_X86_64_COPY:
161 /*
162 * Copy symbol data from shared object to specified
163 * location. Need to find the 'source', i.e. the
164 * other instance of the object than the one in the
165 * executable program.
166 */
167 DPRINTF("fixup R_X86_64_COPY (s)\n");
168
169 sym_def = symbol_def_find(str_tab + sym->st_name,
170 m, ssf_noexec, &dest);
171
172 if (sym_def) {
173 sym_addr = (uintptr_t)
174 symbol_get_addr(sym_def, dest, NULL);
175 } else {
176 printf("Source definition of '%s' not found.\n",
177 str_tab + sym->st_name);
178 continue;
179 }
180
181 sym_size = sym->st_size;
182 if (sym_size != sym_def->st_size) {
183 printf("Warning: Mismatched symbol sizes.\n");
184 /* Take the lower value. */
185 if (sym_size > sym_def->st_size)
186 sym_size = sym_def->st_size;
187 }
188
189 memcpy(r_ptr, (const void *)sym_addr, sym_size);
190 DPRINTF("OK\n");
191 break;
192
193 case R_X86_64_GLOB_DAT:
194 case R_X86_64_JUMP_SLOT:
195 DPRINTF("fixup R_X86_64_GLOB_DAT/JUMP_SLOT (S)\n");
196 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, sym_addr);
197 *r_ptr = sym_addr;
198 DPRINTF("OK\n");
199 break;
200
201 case R_X86_64_RELATIVE:
202 DPRINTF("fixup R_X86_64_RELATIVE (B+A)\n");
203 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, m->bias + r_addend);
204 *r_ptr = m->bias + r_addend;
205 DPRINTF("OK\n");
206 break;
207
208 case R_X86_64_DTPMOD64:
209 DPRINTF("fixup R_X86_64_DTPMOD64\n");
210 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, (size_t)dest->id);
211 *r_ptr = dest->id;
212 DPRINTF("OK\n");
213 break;
214
215 case R_X86_64_DTPOFF64:
216 DPRINTF("fixup R_X86_64_DTPOFF64\n");
217 DPRINTF("*0x%zx = 0x%zx\n", (uintptr_t)r_ptr, sym_def->st_value);
218 *r_ptr = sym_def->st_value;
219 DPRINTF("OK\n");
220 break;
221
222 case R_X86_64_TPOFF64:
223 DPRINTF("fixup R_X86_64_TPOFF64\n");
224 *r_ptr = sym_def->st_value + dest->tpoff;
225 break;
226
227 default:
228 printf("Error: Unknown relocation type %d\n",
229 rel_type);
230 exit(1);
231 }
232
233 }
234}
235
236/** Get the adress of a function.
237 *
238 * @param sym Symbol
239 * @param m Module in which the symbol is located
240 * @return Address of function
241 */
242void *func_get_addr(elf_symbol_t *sym, module_t *m)
243{
244 return symbol_get_addr(sym, m, __tcb_get());
245}
246
247/** @}
248 */
Note: See TracBrowser for help on using the repository browser.