xref: /optee_os/ldelf/ta_elf_rel.c (revision 7509ff7ce5e5a7679319e6fa059b71dd6f6cc8b9)
1*7509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*7509ff7cSJens Wiklander /*
3*7509ff7cSJens Wiklander  * Copyright (c) 2019, Linaro Limited
4*7509ff7cSJens Wiklander  */
5*7509ff7cSJens Wiklander 
6*7509ff7cSJens Wiklander #include <assert.h>
7*7509ff7cSJens Wiklander #include <elf32.h>
8*7509ff7cSJens Wiklander #include <elf64.h>
9*7509ff7cSJens Wiklander #include <elf_common.h>
10*7509ff7cSJens Wiklander #include <string.h>
11*7509ff7cSJens Wiklander #include <tee_api_types.h>
12*7509ff7cSJens Wiklander #include <util.h>
13*7509ff7cSJens Wiklander 
14*7509ff7cSJens Wiklander #include "sys.h"
15*7509ff7cSJens Wiklander #include "ta_elf.h"
16*7509ff7cSJens Wiklander 
17*7509ff7cSJens Wiklander static bool __resolve_sym(struct ta_elf *elf, unsigned int bind,
18*7509ff7cSJens Wiklander 			  size_t st_shndx, size_t st_name, size_t st_value,
19*7509ff7cSJens Wiklander 			  const char *name, vaddr_t *val)
20*7509ff7cSJens Wiklander {
21*7509ff7cSJens Wiklander 	if (bind != STB_GLOBAL)
22*7509ff7cSJens Wiklander 		return false;
23*7509ff7cSJens Wiklander 	if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX)
24*7509ff7cSJens Wiklander 		return false;
25*7509ff7cSJens Wiklander 	if (!st_name)
26*7509ff7cSJens Wiklander 		return false;
27*7509ff7cSJens Wiklander 	if (st_name > elf->dynstr_size)
28*7509ff7cSJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Symbol out of range");
29*7509ff7cSJens Wiklander 
30*7509ff7cSJens Wiklander 	if (strcmp(name, elf->dynstr + st_name))
31*7509ff7cSJens Wiklander 		return false;
32*7509ff7cSJens Wiklander 
33*7509ff7cSJens Wiklander 	*val = st_value + elf->load_addr;
34*7509ff7cSJens Wiklander 	return true;
35*7509ff7cSJens Wiklander }
36*7509ff7cSJens Wiklander 
37*7509ff7cSJens Wiklander static void resolve_sym(const char *name, vaddr_t *val)
38*7509ff7cSJens Wiklander {
39*7509ff7cSJens Wiklander 	struct ta_elf *elf = NULL;
40*7509ff7cSJens Wiklander 	size_t n = 0;
41*7509ff7cSJens Wiklander 
42*7509ff7cSJens Wiklander 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
43*7509ff7cSJens Wiklander 		if (elf->is_32bit) {
44*7509ff7cSJens Wiklander 			Elf32_Sym *sym = elf->dynsymtab;
45*7509ff7cSJens Wiklander 
46*7509ff7cSJens Wiklander 			for (n = 0; n < elf->num_dynsyms; n++) {
47*7509ff7cSJens Wiklander 				if (__resolve_sym(elf,
48*7509ff7cSJens Wiklander 						  ELF32_ST_BIND(sym[n].st_info),
49*7509ff7cSJens Wiklander 						  sym[n].st_shndx,
50*7509ff7cSJens Wiklander 						  sym[n].st_name,
51*7509ff7cSJens Wiklander 						  sym[n].st_value, name, val))
52*7509ff7cSJens Wiklander 					return;
53*7509ff7cSJens Wiklander 			}
54*7509ff7cSJens Wiklander 		} else {
55*7509ff7cSJens Wiklander 			Elf64_Sym *sym = elf->dynsymtab;
56*7509ff7cSJens Wiklander 
57*7509ff7cSJens Wiklander 			for (n = 0; n < elf->num_dynsyms; n++) {
58*7509ff7cSJens Wiklander 				if (__resolve_sym(elf,
59*7509ff7cSJens Wiklander 						  ELF64_ST_BIND(sym[n].st_info),
60*7509ff7cSJens Wiklander 						  sym[n].st_shndx,
61*7509ff7cSJens Wiklander 						  sym[n].st_name,
62*7509ff7cSJens Wiklander 						  sym[n].st_value, name, val))
63*7509ff7cSJens Wiklander 					return;
64*7509ff7cSJens Wiklander 			}
65*7509ff7cSJens Wiklander 		}
66*7509ff7cSJens Wiklander 	}
67*7509ff7cSJens Wiklander 	err(TEE_ERROR_ITEM_NOT_FOUND, "Symbol %s not found", name);
68*7509ff7cSJens Wiklander }
69*7509ff7cSJens Wiklander 
70*7509ff7cSJens Wiklander static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms,
71*7509ff7cSJens Wiklander 				const char *str_tab, size_t str_tab_size,
72*7509ff7cSJens Wiklander 				Elf32_Rel *rel, Elf32_Addr *where)
73*7509ff7cSJens Wiklander {
74*7509ff7cSJens Wiklander 	size_t sym_idx = 0;
75*7509ff7cSJens Wiklander 	const char *name = NULL;
76*7509ff7cSJens Wiklander 	vaddr_t val = 0;
77*7509ff7cSJens Wiklander 	size_t name_idx = 0;
78*7509ff7cSJens Wiklander 
79*7509ff7cSJens Wiklander 	sym_idx = ELF32_R_SYM(rel->r_info);
80*7509ff7cSJens Wiklander 	assert(sym_idx < num_syms);
81*7509ff7cSJens Wiklander 
82*7509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
83*7509ff7cSJens Wiklander 	assert(name_idx < str_tab_size);
84*7509ff7cSJens Wiklander 	name = str_tab + name_idx;
85*7509ff7cSJens Wiklander 
86*7509ff7cSJens Wiklander 	resolve_sym(name, &val);
87*7509ff7cSJens Wiklander 	*where = val;
88*7509ff7cSJens Wiklander }
89*7509ff7cSJens Wiklander 
90*7509ff7cSJens Wiklander static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx)
91*7509ff7cSJens Wiklander {
92*7509ff7cSJens Wiklander 	Elf32_Shdr *shdr = elf->shdr;
93*7509ff7cSJens Wiklander 	Elf32_Rel *rel = NULL;
94*7509ff7cSJens Wiklander 	Elf32_Rel *rel_end = NULL;
95*7509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
96*7509ff7cSJens Wiklander 	Elf32_Sym *sym_tab = NULL;
97*7509ff7cSJens Wiklander 	size_t num_syms = 0;
98*7509ff7cSJens Wiklander 	size_t sh_end = 0;
99*7509ff7cSJens Wiklander 	const char *str_tab = NULL;
100*7509ff7cSJens Wiklander 	size_t str_tab_size = 0;
101*7509ff7cSJens Wiklander 
102*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_REL);
103*7509ff7cSJens Wiklander 
104*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel));
105*7509ff7cSJens Wiklander 
106*7509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
107*7509ff7cSJens Wiklander 	if (sym_tab_idx) {
108*7509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
109*7509ff7cSJens Wiklander 
110*7509ff7cSJens Wiklander 		assert(sym_tab_idx < elf->e_shnum);
111*7509ff7cSJens Wiklander 
112*7509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym));
113*7509ff7cSJens Wiklander 
114*7509ff7cSJens Wiklander 		/* Check the address is inside ELF memory */
115*7509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
116*7509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
117*7509ff7cSJens Wiklander 			err(TEE_ERROR_SECURITY, "Overflow");
118*7509ff7cSJens Wiklander 		assert(sh_end < (elf->max_addr - elf->load_addr));
119*7509ff7cSJens Wiklander 
120*7509ff7cSJens Wiklander 		sym_tab = (Elf32_Sym *)(elf->load_addr +
121*7509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
122*7509ff7cSJens Wiklander 
123*7509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym);
124*7509ff7cSJens Wiklander 
125*7509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
126*7509ff7cSJens Wiklander 		if (str_tab_idx) {
127*7509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
128*7509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
129*7509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
130*7509ff7cSJens Wiklander 				err(TEE_ERROR_SECURITY, "Overflow");
131*7509ff7cSJens Wiklander 			assert(sh_end < (elf->max_addr - elf->load_addr));
132*7509ff7cSJens Wiklander 
133*7509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
134*7509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
135*7509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
136*7509ff7cSJens Wiklander 		}
137*7509ff7cSJens Wiklander 	}
138*7509ff7cSJens Wiklander 
139*7509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
140*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr));
141*7509ff7cSJens Wiklander 	rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr);
142*7509ff7cSJens Wiklander 
143*7509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
144*7509ff7cSJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size,
145*7509ff7cSJens Wiklander 			 &sh_end))
146*7509ff7cSJens Wiklander 		err(TEE_ERROR_SECURITY, "Overflow");
147*7509ff7cSJens Wiklander 	assert(sh_end < (elf->max_addr - elf->load_addr));
148*7509ff7cSJens Wiklander 	rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel);
149*7509ff7cSJens Wiklander 	for (; rel < rel_end; rel++) {
150*7509ff7cSJens Wiklander 		Elf32_Addr *where = NULL;
151*7509ff7cSJens Wiklander 		size_t sym_idx = 0;
152*7509ff7cSJens Wiklander 
153*7509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
154*7509ff7cSJens Wiklander 		assert(rel->r_offset < (elf->max_addr - elf->load_addr));
155*7509ff7cSJens Wiklander 		where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
156*7509ff7cSJens Wiklander 
157*7509ff7cSJens Wiklander 		switch (ELF32_R_TYPE(rel->r_info)) {
158*7509ff7cSJens Wiklander 		case R_ARM_ABS32:
159*7509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
160*7509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
161*7509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
162*7509ff7cSJens Wiklander 				/* Symbol is external */
163*7509ff7cSJens Wiklander 				e32_process_dyn_rel(sym_tab, num_syms, str_tab,
164*7509ff7cSJens Wiklander 						    str_tab_size, rel, where);
165*7509ff7cSJens Wiklander 			} else {
166*7509ff7cSJens Wiklander 				*where += elf->load_addr +
167*7509ff7cSJens Wiklander 					  sym_tab[sym_idx].st_value;
168*7509ff7cSJens Wiklander 			}
169*7509ff7cSJens Wiklander 			break;
170*7509ff7cSJens Wiklander 		case R_ARM_REL32:
171*7509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
172*7509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
173*7509ff7cSJens Wiklander 			*where += sym_tab[sym_idx].st_value - rel->r_offset;
174*7509ff7cSJens Wiklander 			break;
175*7509ff7cSJens Wiklander 		case R_ARM_RELATIVE:
176*7509ff7cSJens Wiklander 			*where += elf->load_addr;
177*7509ff7cSJens Wiklander 			break;
178*7509ff7cSJens Wiklander 		case R_ARM_GLOB_DAT:
179*7509ff7cSJens Wiklander 		case R_ARM_JUMP_SLOT:
180*7509ff7cSJens Wiklander 			e32_process_dyn_rel(sym_tab, num_syms, str_tab,
181*7509ff7cSJens Wiklander 					    str_tab_size, rel, where);
182*7509ff7cSJens Wiklander 			break;
183*7509ff7cSJens Wiklander 		default:
184*7509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
185*7509ff7cSJens Wiklander 			     ELF32_R_TYPE(rel->r_info));
186*7509ff7cSJens Wiklander 		}
187*7509ff7cSJens Wiklander 	}
188*7509ff7cSJens Wiklander }
189*7509ff7cSJens Wiklander 
190*7509ff7cSJens Wiklander #ifdef ARM64
191*7509ff7cSJens Wiklander static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
192*7509ff7cSJens Wiklander 				 const char *str_tab, size_t str_tab_size,
193*7509ff7cSJens Wiklander 				 Elf64_Rela *rela, Elf64_Addr *where)
194*7509ff7cSJens Wiklander {
195*7509ff7cSJens Wiklander 	size_t sym_idx = 0;
196*7509ff7cSJens Wiklander 	const char *name = NULL;
197*7509ff7cSJens Wiklander 	uintptr_t val = 0;
198*7509ff7cSJens Wiklander 	size_t name_idx = 0;
199*7509ff7cSJens Wiklander 
200*7509ff7cSJens Wiklander 	sym_idx = ELF64_R_SYM(rela->r_info);
201*7509ff7cSJens Wiklander 	assert(sym_idx < num_syms);
202*7509ff7cSJens Wiklander 
203*7509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
204*7509ff7cSJens Wiklander 	assert(name_idx < str_tab_size);
205*7509ff7cSJens Wiklander 	name = str_tab + name_idx;
206*7509ff7cSJens Wiklander 
207*7509ff7cSJens Wiklander 	resolve_sym(name, &val);
208*7509ff7cSJens Wiklander 	*where = val;
209*7509ff7cSJens Wiklander }
210*7509ff7cSJens Wiklander 
211*7509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
212*7509ff7cSJens Wiklander {
213*7509ff7cSJens Wiklander 	Elf64_Shdr *shdr = elf->shdr;
214*7509ff7cSJens Wiklander 	Elf64_Rela *rela = NULL;
215*7509ff7cSJens Wiklander 	Elf64_Rela *rela_end = NULL;
216*7509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
217*7509ff7cSJens Wiklander 	Elf64_Sym *sym_tab = NULL;
218*7509ff7cSJens Wiklander 	size_t num_syms = 0;
219*7509ff7cSJens Wiklander 	size_t sh_end = 0;
220*7509ff7cSJens Wiklander 	const char *str_tab = NULL;
221*7509ff7cSJens Wiklander 	size_t str_tab_size = 0;
222*7509ff7cSJens Wiklander 
223*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_RELA);
224*7509ff7cSJens Wiklander 
225*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
226*7509ff7cSJens Wiklander 
227*7509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
228*7509ff7cSJens Wiklander 	if (sym_tab_idx) {
229*7509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
230*7509ff7cSJens Wiklander 
231*7509ff7cSJens Wiklander 		assert(sym_tab_idx < elf->e_shnum);
232*7509ff7cSJens Wiklander 
233*7509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
234*7509ff7cSJens Wiklander 
235*7509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
236*7509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
237*7509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
238*7509ff7cSJens Wiklander 			err(TEE_ERROR_SECURITY, "Overflow");
239*7509ff7cSJens Wiklander 		assert(sh_end < (elf->max_addr - elf->load_addr));
240*7509ff7cSJens Wiklander 
241*7509ff7cSJens Wiklander 		sym_tab = (Elf64_Sym *)(elf->load_addr +
242*7509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
243*7509ff7cSJens Wiklander 
244*7509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
245*7509ff7cSJens Wiklander 
246*7509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
247*7509ff7cSJens Wiklander 		if (str_tab_idx) {
248*7509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
249*7509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
250*7509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
251*7509ff7cSJens Wiklander 				err(TEE_ERROR_SECURITY, "Overflow");
252*7509ff7cSJens Wiklander 			assert(sh_end < (elf->max_addr - elf->load_addr));
253*7509ff7cSJens Wiklander 
254*7509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
255*7509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
256*7509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
257*7509ff7cSJens Wiklander 		}
258*7509ff7cSJens Wiklander 	}
259*7509ff7cSJens Wiklander 
260*7509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
261*7509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr));
262*7509ff7cSJens Wiklander 	rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
263*7509ff7cSJens Wiklander 
264*7509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
265*7509ff7cSJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size,
266*7509ff7cSJens Wiklander 			 &sh_end))
267*7509ff7cSJens Wiklander 		err(TEE_ERROR_SECURITY, "Overflow");
268*7509ff7cSJens Wiklander 	assert(sh_end < (elf->max_addr - elf->load_addr));
269*7509ff7cSJens Wiklander 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
270*7509ff7cSJens Wiklander 	for (; rela < rela_end; rela++) {
271*7509ff7cSJens Wiklander 		Elf64_Addr *where = NULL;
272*7509ff7cSJens Wiklander 		size_t sym_idx = 0;
273*7509ff7cSJens Wiklander 
274*7509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
275*7509ff7cSJens Wiklander 		assert(rela->r_offset < (elf->max_addr - elf->load_addr));
276*7509ff7cSJens Wiklander 
277*7509ff7cSJens Wiklander 		where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
278*7509ff7cSJens Wiklander 
279*7509ff7cSJens Wiklander 		switch (ELF64_R_TYPE(rela->r_info)) {
280*7509ff7cSJens Wiklander 		case R_AARCH64_ABS64:
281*7509ff7cSJens Wiklander 			sym_idx = ELF64_R_SYM(rela->r_info);
282*7509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
283*7509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
284*7509ff7cSJens Wiklander 				/* Symbol is external */
285*7509ff7cSJens Wiklander 				e64_process_dyn_rela(sym_tab, num_syms, str_tab,
286*7509ff7cSJens Wiklander 						     str_tab_size, rela, where);
287*7509ff7cSJens Wiklander 			} else {
288*7509ff7cSJens Wiklander 				*where = rela->r_addend + elf->load_addr +
289*7509ff7cSJens Wiklander 					 sym_tab[sym_idx].st_value;
290*7509ff7cSJens Wiklander 			}
291*7509ff7cSJens Wiklander 			break;
292*7509ff7cSJens Wiklander 		case R_AARCH64_RELATIVE:
293*7509ff7cSJens Wiklander 			*where = rela->r_addend + elf->load_addr;
294*7509ff7cSJens Wiklander 			break;
295*7509ff7cSJens Wiklander 		case R_AARCH64_GLOB_DAT:
296*7509ff7cSJens Wiklander 		case R_AARCH64_JUMP_SLOT:
297*7509ff7cSJens Wiklander 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
298*7509ff7cSJens Wiklander 					     str_tab_size, rela, where);
299*7509ff7cSJens Wiklander 			break;
300*7509ff7cSJens Wiklander 		default:
301*7509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
302*7509ff7cSJens Wiklander 			     ELF64_R_TYPE(rela->r_info));
303*7509ff7cSJens Wiklander 		}
304*7509ff7cSJens Wiklander 	}
305*7509ff7cSJens Wiklander }
306*7509ff7cSJens Wiklander #else /*ARM64*/
307*7509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf __unused,
308*7509ff7cSJens Wiklander 			 unsigned int rel_sidx __unused)
309*7509ff7cSJens Wiklander {
310*7509ff7cSJens Wiklander 	err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
311*7509ff7cSJens Wiklander }
312*7509ff7cSJens Wiklander #endif /*ARM64*/
313*7509ff7cSJens Wiklander 
314*7509ff7cSJens Wiklander void ta_elf_relocate(struct ta_elf *elf)
315*7509ff7cSJens Wiklander {
316*7509ff7cSJens Wiklander 	size_t n = 0;
317*7509ff7cSJens Wiklander 
318*7509ff7cSJens Wiklander 	if (elf->is_32bit) {
319*7509ff7cSJens Wiklander 		Elf32_Shdr *shdr = elf->shdr;
320*7509ff7cSJens Wiklander 
321*7509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
322*7509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_REL)
323*7509ff7cSJens Wiklander 				e32_relocate(elf, n);
324*7509ff7cSJens Wiklander 	} else {
325*7509ff7cSJens Wiklander 		Elf64_Shdr *shdr = elf->shdr;
326*7509ff7cSJens Wiklander 
327*7509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
328*7509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_RELA)
329*7509ff7cSJens Wiklander 				e64_relocate(elf, n);
330*7509ff7cSJens Wiklander 
331*7509ff7cSJens Wiklander 	}
332*7509ff7cSJens Wiklander }
333