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

Last change on this file was eb630cf, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 2 years ago

Fix handling of ABS32 relocation on arm32

A bad symbol reference in entryjmp.S was creating
an ABS32 relocation causing issues for dynamic
linker, leading to the ABS32 relocation being
generally ignored. However, that was not the
correct solution, as doing so breaks stacktrace
code (which emits global function pointers in
static data, creating ABS32 relocs).

The symbol reference in entryjmp.S was fixed by
converting the function to inline assembly, let
GCC deal with variable addresses.

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