xref: /optee_os/ldelf/ta_elf_rel.c (revision 4584d00c9f447821f3c6f1c69a8d41b48fccc1dc)
17509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
27509ff7cSJens Wiklander /*
37509ff7cSJens Wiklander  * Copyright (c) 2019, Linaro Limited
47509ff7cSJens Wiklander  */
57509ff7cSJens Wiklander 
67509ff7cSJens Wiklander #include <assert.h>
75548a710SJerome Forissier #include <compiler.h>
855e64090SJens Wiklander #include <confine_array_index.h>
97509ff7cSJens Wiklander #include <elf32.h>
107509ff7cSJens Wiklander #include <elf64.h>
117509ff7cSJens Wiklander #include <elf_common.h>
127509ff7cSJens Wiklander #include <string.h>
137509ff7cSJens Wiklander #include <tee_api_types.h>
147509ff7cSJens Wiklander #include <util.h>
157509ff7cSJens Wiklander 
167509ff7cSJens Wiklander #include "sys.h"
177509ff7cSJens Wiklander #include "ta_elf.h"
187509ff7cSJens Wiklander 
199f392760SJerome Forissier static uint32_t elf_hash(const char *name)
209f392760SJerome Forissier {
219f392760SJerome Forissier 	const unsigned char *p = (const unsigned char *)name;
229f392760SJerome Forissier 	uint32_t h = 0;
239f392760SJerome Forissier 	uint32_t g = 0;
249f392760SJerome Forissier 
259f392760SJerome Forissier 	while (*p) {
269f392760SJerome Forissier 		h = (h << 4) + *p++;
279f392760SJerome Forissier 		g = h & 0xf0000000;
289f392760SJerome Forissier 		if (g)
299f392760SJerome Forissier 			h ^= g >> 24;
309f392760SJerome Forissier 		h &= ~g;
319f392760SJerome Forissier 	}
329f392760SJerome Forissier 	return h;
339f392760SJerome Forissier }
349f392760SJerome Forissier 
35bdf82531SJerome Forissier static uint32_t gnu_hash(const char *name)
36bdf82531SJerome Forissier {
37bdf82531SJerome Forissier 	const unsigned char *p = (const unsigned char *)name;
38bdf82531SJerome Forissier 	uint32_t h = 5381;
39bdf82531SJerome Forissier 
40bdf82531SJerome Forissier 	while (*p)
41bdf82531SJerome Forissier 		h = (h << 5) + h + *p++;
42bdf82531SJerome Forissier 
43bdf82531SJerome Forissier 	return h;
44bdf82531SJerome Forissier }
45bdf82531SJerome Forissier 
46bdf82531SJerome Forissier static bool sym_compare(struct ta_elf *elf, unsigned int st_bind,
4797c5ac19SJens Wiklander 			unsigned int st_type, size_t st_shndx,
4897c5ac19SJens Wiklander 			size_t st_name, size_t st_value, const char *name,
49cf830b2bSJerome Forissier 			vaddr_t *val, bool weak_ok)
507509ff7cSJens Wiklander {
51cf830b2bSJerome Forissier 	bool bind_ok = false;
52cf830b2bSJerome Forissier 
537509ff7cSJens Wiklander 	if (!st_name)
547509ff7cSJens Wiklander 		return false;
557509ff7cSJens Wiklander 	if (st_name > elf->dynstr_size)
5697c5ac19SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range");
577509ff7cSJens Wiklander 	if (strcmp(name, elf->dynstr + st_name))
587509ff7cSJens Wiklander 		return false;
59cf830b2bSJerome Forissier 	if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK))
60cf830b2bSJerome Forissier 		bind_ok = true;
61cf830b2bSJerome Forissier 	if (!bind_ok)
62cf830b2bSJerome Forissier 		return false;
63cf830b2bSJerome Forissier 	if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) {
64cf830b2bSJerome Forissier 		if (val)
65cf830b2bSJerome Forissier 			*val = 0;
66cf830b2bSJerome Forissier 		return true;
67cf830b2bSJerome Forissier 	}
68cf830b2bSJerome Forissier 	if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX)
69cf830b2bSJerome Forissier 		return false;
707509ff7cSJens Wiklander 
7197c5ac19SJens Wiklander 	switch (st_type) {
72bb8cd6f0SJerome Forissier 	case STT_NOTYPE:
7397c5ac19SJens Wiklander 	case STT_OBJECT:
7497c5ac19SJens Wiklander 	case STT_FUNC:
75c88ba125SJerome Forissier 		if (st_value > (elf->max_addr - elf->load_addr))
76c88ba125SJerome Forissier 			err(TEE_ERROR_BAD_FORMAT,
77c88ba125SJerome Forissier 			    "Symbol location out of range");
78c88ba125SJerome Forissier 		if (val)
797509ff7cSJens Wiklander 			*val = st_value + elf->load_addr;
8097c5ac19SJens Wiklander 		break;
81c88ba125SJerome Forissier 	case STT_TLS:
82c88ba125SJerome Forissier 		if (val)
83c88ba125SJerome Forissier 			*val = st_value;
84c88ba125SJerome Forissier 		break;
8597c5ac19SJens Wiklander 	default:
8697c5ac19SJens Wiklander 		err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported");
8797c5ac19SJens Wiklander 	}
8897c5ac19SJens Wiklander 
897509ff7cSJens Wiklander 	return true;
907509ff7cSJens Wiklander }
917509ff7cSJens Wiklander 
92bdf82531SJerome Forissier static bool check_found_sym(struct ta_elf *elf, const char *name, vaddr_t *val,
93bdf82531SJerome Forissier 			    bool weak_ok, size_t n)
947509ff7cSJens Wiklander {
95bdf82531SJerome Forissier 	Elf32_Sym *sym32 = NULL;
96bdf82531SJerome Forissier 	Elf64_Sym *sym64 = NULL;
97bdf82531SJerome Forissier 	unsigned int st_bind = 0;
98bdf82531SJerome Forissier 	unsigned int st_type = 0;
99bdf82531SJerome Forissier 	size_t st_shndx = 0;
100bdf82531SJerome Forissier 	size_t st_name = 0;
101bdf82531SJerome Forissier 	size_t st_value = 0;
102bdf82531SJerome Forissier 
103bdf82531SJerome Forissier 	if (n >= elf->num_dynsyms)
104bdf82531SJerome Forissier 		err(TEE_ERROR_BAD_FORMAT, "Index out of range");
105bdf82531SJerome Forissier 
106bdf82531SJerome Forissier 	/*
107bdf82531SJerome Forissier 	 * We're loading values from sym[] which later
108bdf82531SJerome Forissier 	 * will be used to load something.
109bdf82531SJerome Forissier 	 * => Spectre V1 pattern, need to cap the index
110bdf82531SJerome Forissier 	 * against speculation.
111bdf82531SJerome Forissier 	 */
112bdf82531SJerome Forissier 	n = confine_array_index(n, elf->num_dynsyms);
113bdf82531SJerome Forissier 
114bdf82531SJerome Forissier 	if (elf->is_32bit) {
115bdf82531SJerome Forissier 		sym32 = elf->dynsymtab;
116bdf82531SJerome Forissier 		st_bind = ELF32_ST_BIND(sym32[n].st_info);
117bdf82531SJerome Forissier 		st_type = ELF32_ST_TYPE(sym32[n].st_info);
118bdf82531SJerome Forissier 		st_shndx = sym32[n].st_shndx;
119bdf82531SJerome Forissier 		st_name = sym32[n].st_name;
120bdf82531SJerome Forissier 		st_value = sym32[n].st_value;
121bdf82531SJerome Forissier 	} else {
122bdf82531SJerome Forissier 		sym64 = elf->dynsymtab;
123bdf82531SJerome Forissier 		st_bind = ELF64_ST_BIND(sym64[n].st_info);
124bdf82531SJerome Forissier 		st_type = ELF64_ST_TYPE(sym64[n].st_info);
125bdf82531SJerome Forissier 		st_shndx = sym64[n].st_shndx;
126bdf82531SJerome Forissier 		st_name = sym64[n].st_name;
127bdf82531SJerome Forissier 		st_value = sym64[n].st_value;
128bdf82531SJerome Forissier 	}
129bdf82531SJerome Forissier 
130bdf82531SJerome Forissier 	return sym_compare(elf, st_bind, st_type, st_shndx, st_name, st_value,
131bdf82531SJerome Forissier 			   name, val, weak_ok);
132bdf82531SJerome Forissier }
133bdf82531SJerome Forissier 
134bdf82531SJerome Forissier static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val,
135bdf82531SJerome Forissier 				     struct ta_elf *elf, bool weak_ok)
136bdf82531SJerome Forissier {
137bdf82531SJerome Forissier 	uint32_t n = 0;
138bdf82531SJerome Forissier 	uint32_t hash = 0;
139bdf82531SJerome Forissier 
140bdf82531SJerome Forissier 	if (elf->gnu_hashtab) {
141bdf82531SJerome Forissier 		struct gnu_hashtab *h = elf->gnu_hashtab;
142bdf82531SJerome Forissier 		uint32_t *end = (void *)((uint8_t *)elf->gnu_hashtab +
143bdf82531SJerome Forissier 					 elf->gnu_hashtab_size);
144bdf82531SJerome Forissier 		uint32_t *bucket = NULL;
145bdf82531SJerome Forissier 		uint32_t *chain = NULL;
146bdf82531SJerome Forissier 		uint32_t hashval = 0;
147bdf82531SJerome Forissier 
148bdf82531SJerome Forissier 		hash = gnu_hash(name);
149bdf82531SJerome Forissier 
150bdf82531SJerome Forissier 		if (elf->is_32bit) {
151bdf82531SJerome Forissier 			uint32_t *bloom = (void *)(h + 1);
152bdf82531SJerome Forissier 			uint32_t word = bloom[(hash / 32) % h->bloom_size];
153bdf82531SJerome Forissier 			uint32_t mask = BIT32(hash % 32) |
154bdf82531SJerome Forissier 					BIT32((hash >> h->bloom_shift) % 32);
155bdf82531SJerome Forissier 
156bdf82531SJerome Forissier 			if ((word & mask) != mask)
157bdf82531SJerome Forissier 				return TEE_ERROR_ITEM_NOT_FOUND;
158bdf82531SJerome Forissier 			bucket = bloom + h->bloom_size;
159bdf82531SJerome Forissier 		} else {
160bdf82531SJerome Forissier 			uint64_t *bloom = (void *)(h + 1);
161bdf82531SJerome Forissier 			uint64_t word = bloom[(hash / 64) % h->bloom_size];
162bdf82531SJerome Forissier 			uint64_t mask = BIT64(hash % 64) |
163bdf82531SJerome Forissier 					BIT64((hash >> h->bloom_shift) % 64);
164bdf82531SJerome Forissier 
165bdf82531SJerome Forissier 			if ((word & mask) != mask)
166bdf82531SJerome Forissier 				return TEE_ERROR_ITEM_NOT_FOUND;
167bdf82531SJerome Forissier 			bucket = (uint32_t *)(bloom + h->bloom_size);
168bdf82531SJerome Forissier 		}
169bdf82531SJerome Forissier 		chain = bucket + h->nbuckets;
170bdf82531SJerome Forissier 
171bdf82531SJerome Forissier 		n = bucket[hash % h->nbuckets];
172bdf82531SJerome Forissier 		if (n < h->symoffset)
173bdf82531SJerome Forissier 			return TEE_ERROR_ITEM_NOT_FOUND;
174bdf82531SJerome Forissier 
175bdf82531SJerome Forissier 		hash |= 1;
176bdf82531SJerome Forissier 		do {
177bdf82531SJerome Forissier 			size_t idx = n - h->symoffset;
178bdf82531SJerome Forissier 
179bdf82531SJerome Forissier 			if (chain + idx > end)
180bdf82531SJerome Forissier 				return TEE_ERROR_ITEM_NOT_FOUND;
181bdf82531SJerome Forissier 
182bdf82531SJerome Forissier 			hashval = chain[idx];
183bdf82531SJerome Forissier 
184bdf82531SJerome Forissier 			if ((hashval | 1) == hash &&
185bdf82531SJerome Forissier 			    check_found_sym(elf, name, val, weak_ok, n))
186bdf82531SJerome Forissier 				return TEE_SUCCESS;
187bdf82531SJerome Forissier 
188bdf82531SJerome Forissier 			n++;
189bdf82531SJerome Forissier 		} while (!(hashval & 1));
190bdf82531SJerome Forissier 	} else if (elf->hashtab) {
1919f392760SJerome Forissier 		/*
1929f392760SJerome Forissier 		 * Using uint32_t here for convenience because both Elf64_Word
1939f392760SJerome Forissier 		 * and Elf32_Word are 32-bit types
1949f392760SJerome Forissier 		 */
1959f392760SJerome Forissier 		uint32_t *hashtab = elf->hashtab;
1969f392760SJerome Forissier 		uint32_t nbuckets = hashtab[0];
1979f392760SJerome Forissier 		uint32_t nchains = hashtab[1];
1989f392760SJerome Forissier 		uint32_t *bucket = &hashtab[2];
1999f392760SJerome Forissier 		uint32_t *chain = &bucket[nbuckets];
2009f392760SJerome Forissier 
201bdf82531SJerome Forissier 		hash = elf_hash(name);
2027509ff7cSJens Wiklander 
2039f392760SJerome Forissier 		for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
204bdf82531SJerome Forissier 			if (n >= nchains)
205bdf82531SJerome Forissier 				err(TEE_ERROR_BAD_FORMAT, "Index out of range");
206bdf82531SJerome Forissier 			if (check_found_sym(elf, name, val, weak_ok, n))
207c86f218cSJens Wiklander 				return TEE_SUCCESS;
2087509ff7cSJens Wiklander 		}
2097509ff7cSJens Wiklander 	}
210ebef121cSJerome Forissier 
211ebef121cSJerome Forissier 	return TEE_ERROR_ITEM_NOT_FOUND;
2127509ff7cSJens Wiklander }
213c86f218cSJens Wiklander 
214cf830b2bSJerome Forissier /*
215cf830b2bSJerome Forissier  * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols
216cf830b2bSJerome Forissier  * are searched first, then weak ones. Last option, when at least one weak but
217cf830b2bSJerome Forissier  * undefined symbol exists, resolve to zero. Otherwise return
218cf830b2bSJerome Forissier  * TEE_ERROR_ITEM_NOT_FOUND.
219c88ba125SJerome Forissier  * @val (if != 0) receives the symbol value
220c88ba125SJerome Forissier  * @found_elf (if != 0) receives the module where the symbol is found
221cf830b2bSJerome Forissier  */
222ebef121cSJerome Forissier TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
223c88ba125SJerome Forissier 			      struct ta_elf **found_elf,
224ebef121cSJerome Forissier 			      struct ta_elf *elf)
225ebef121cSJerome Forissier {
226cf830b2bSJerome Forissier 	if (elf) {
227cf830b2bSJerome Forissier 		/* Search global symbols */
228bdf82531SJerome Forissier 		if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */))
229c88ba125SJerome Forissier 			goto success;
230cf830b2bSJerome Forissier 		/* Search weak symbols */
231bdf82531SJerome Forissier 		if (!resolve_sym_helper(name, val, elf, true /* weak_ok */))
232c88ba125SJerome Forissier 			goto success;
233cf830b2bSJerome Forissier 	}
234cf830b2bSJerome Forissier 
235cf830b2bSJerome Forissier 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
236bdf82531SJerome Forissier 		if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */))
237c88ba125SJerome Forissier 			goto success;
238bdf82531SJerome Forissier 		if (!resolve_sym_helper(name, val, elf, true /* weak_ok */))
239c88ba125SJerome Forissier 			goto success;
240cf830b2bSJerome Forissier 	}
241ebef121cSJerome Forissier 
242c86f218cSJens Wiklander 	return TEE_ERROR_ITEM_NOT_FOUND;
243c88ba125SJerome Forissier 
244c88ba125SJerome Forissier success:
245c88ba125SJerome Forissier 	if (found_elf)
246c88ba125SJerome Forissier 		*found_elf = elf;
247c88ba125SJerome Forissier 	return TEE_SUCCESS;
248c86f218cSJens Wiklander }
249c86f218cSJens Wiklander 
250c88ba125SJerome Forissier static void e32_get_sym_name(const Elf32_Sym *sym_tab, size_t num_syms,
2517509ff7cSJens Wiklander 			     const char *str_tab, size_t str_tab_size,
252c44d734bSJerome Forissier 			     Elf32_Rel *rel, const char **name,
253c44d734bSJerome Forissier 			     bool *weak_undef)
2547509ff7cSJens Wiklander {
2557509ff7cSJens Wiklander 	size_t sym_idx = 0;
2567509ff7cSJens Wiklander 	size_t name_idx = 0;
2577509ff7cSJens Wiklander 
2587509ff7cSJens Wiklander 	sym_idx = ELF32_R_SYM(rel->r_info);
259447354c6SJens Wiklander 	if (sym_idx >= num_syms)
260e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
26155e64090SJens Wiklander 	sym_idx = confine_array_index(sym_idx, num_syms);
2627509ff7cSJens Wiklander 
2637509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
264447354c6SJens Wiklander 	if (name_idx >= str_tab_size)
265e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
266c88ba125SJerome Forissier 	*name = str_tab + name_idx;
267c44d734bSJerome Forissier 
268c44d734bSJerome Forissier 	if (!weak_undef)
269c44d734bSJerome Forissier 		return;
270c44d734bSJerome Forissier 	if (sym_tab[sym_idx].st_shndx == SHN_UNDEF &&
271c44d734bSJerome Forissier 	    ELF32_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK)
272c44d734bSJerome Forissier 		*weak_undef = true;
273c44d734bSJerome Forissier 	else
274c44d734bSJerome Forissier 		*weak_undef = false;
275c88ba125SJerome Forissier }
2767509ff7cSJens Wiklander 
277c44d734bSJerome Forissier static void resolve_sym(const char *name, vaddr_t *val, struct ta_elf **mod,
278c44d734bSJerome Forissier 			bool err_if_not_found)
279c88ba125SJerome Forissier {
280c88ba125SJerome Forissier 	TEE_Result res = ta_elf_resolve_sym(name, val, mod, NULL);
281c88ba125SJerome Forissier 
282c44d734bSJerome Forissier 	if (res) {
283c44d734bSJerome Forissier 		if (err_if_not_found)
284c88ba125SJerome Forissier 			err(res, "Symbol %s not found", name);
285*4584d00cSClement Faure 		else if (val)
286c44d734bSJerome Forissier 			*val = 0;
287c44d734bSJerome Forissier 	}
288c88ba125SJerome Forissier }
289c88ba125SJerome Forissier 
290c88ba125SJerome Forissier static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms,
291c88ba125SJerome Forissier 				const char *str_tab, size_t str_tab_size,
292c88ba125SJerome Forissier 				Elf32_Rel *rel, Elf32_Addr *where)
293c88ba125SJerome Forissier {
294c88ba125SJerome Forissier 	const char *name = NULL;
295c88ba125SJerome Forissier 	vaddr_t val = 0;
296c44d734bSJerome Forissier 	bool weak_undef = false;
297c88ba125SJerome Forissier 
298c44d734bSJerome Forissier 	e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
299c44d734bSJerome Forissier 			 &weak_undef);
300c44d734bSJerome Forissier 	resolve_sym(name, &val, NULL, !weak_undef);
3017509ff7cSJens Wiklander 	*where = val;
3027509ff7cSJens Wiklander }
3037509ff7cSJens Wiklander 
304c88ba125SJerome Forissier static void e32_tls_get_module(const Elf32_Sym *sym_tab, size_t num_syms,
305c88ba125SJerome Forissier 			       const char *str_tab, size_t str_tab_size,
306c88ba125SJerome Forissier 			       Elf32_Rel *rel, struct ta_elf **mod)
307c88ba125SJerome Forissier {
308c88ba125SJerome Forissier 	const char *name = NULL;
309c88ba125SJerome Forissier 	size_t sym_idx = 0;
310c88ba125SJerome Forissier 
311c88ba125SJerome Forissier 	sym_idx = ELF32_R_SYM(rel->r_info);
312c88ba125SJerome Forissier 	if (sym_idx >= num_syms)
313c88ba125SJerome Forissier 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
314c88ba125SJerome Forissier 	sym_idx = confine_array_index(sym_idx, num_syms);
315c88ba125SJerome Forissier 	if (!sym_idx || sym_tab[sym_idx].st_shndx != SHN_UNDEF) {
316c88ba125SJerome Forissier 		/* No symbol, or symbol is defined in current module */
317c88ba125SJerome Forissier 		return;
318c88ba125SJerome Forissier 	}
319c88ba125SJerome Forissier 
320c44d734bSJerome Forissier 	e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
321c44d734bSJerome Forissier 			 NULL);
322c44d734bSJerome Forissier 	resolve_sym(name, NULL, mod, false);
323c88ba125SJerome Forissier }
324c88ba125SJerome Forissier 
325c88ba125SJerome Forissier static void e32_tls_resolve(const Elf32_Sym *sym_tab, size_t num_syms,
326c88ba125SJerome Forissier 			    const char *str_tab, size_t str_tab_size,
327c88ba125SJerome Forissier 			    Elf32_Rel *rel, vaddr_t *val)
328c88ba125SJerome Forissier {
329c88ba125SJerome Forissier 	const char *name = NULL;
330c88ba125SJerome Forissier 
331c44d734bSJerome Forissier 	e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
332c44d734bSJerome Forissier 			 NULL);
333c44d734bSJerome Forissier 	resolve_sym(name, val, NULL, false);
334c88ba125SJerome Forissier }
335c88ba125SJerome Forissier 
3367509ff7cSJens Wiklander static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx)
3377509ff7cSJens Wiklander {
3387509ff7cSJens Wiklander 	Elf32_Shdr *shdr = elf->shdr;
3397509ff7cSJens Wiklander 	Elf32_Rel *rel = NULL;
3407509ff7cSJens Wiklander 	Elf32_Rel *rel_end = NULL;
3417509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
3427509ff7cSJens Wiklander 	Elf32_Sym *sym_tab = NULL;
3437509ff7cSJens Wiklander 	size_t num_syms = 0;
3447509ff7cSJens Wiklander 	size_t sh_end = 0;
3457509ff7cSJens Wiklander 	const char *str_tab = NULL;
3467509ff7cSJens Wiklander 	size_t str_tab_size = 0;
3477509ff7cSJens Wiklander 
3487509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_REL);
3497509ff7cSJens Wiklander 
3507509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel));
3517509ff7cSJens Wiklander 
3527509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
3537509ff7cSJens Wiklander 	if (sym_tab_idx) {
3547509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
3557509ff7cSJens Wiklander 
356447354c6SJens Wiklander 		if (sym_tab_idx >= elf->e_shnum)
357dcf64f87SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
35855e64090SJens Wiklander 		sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
3597509ff7cSJens Wiklander 
3607509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym));
3617509ff7cSJens Wiklander 
3627509ff7cSJens Wiklander 		/* Check the address is inside ELF memory */
3637509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
3647509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
365e97bbbb2SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Overflow");
366447354c6SJens Wiklander 		if (sh_end >= (elf->max_addr - elf->load_addr))
367dcf64f87SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
3687509ff7cSJens Wiklander 
3697509ff7cSJens Wiklander 		sym_tab = (Elf32_Sym *)(elf->load_addr +
3707509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
3717509ff7cSJens Wiklander 
3727509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym);
3737509ff7cSJens Wiklander 
3747509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
3757509ff7cSJens Wiklander 		if (str_tab_idx) {
37655e64090SJens Wiklander 			if (str_tab_idx >= elf->e_shnum)
377e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
378dcf64f87SJens Wiklander 				    "STRTAB index out of range");
37955e64090SJens Wiklander 			str_tab_idx = confine_array_index(str_tab_idx,
38055e64090SJens Wiklander 							  elf->e_shnum);
38155e64090SJens Wiklander 
3827509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
3837509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
3847509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
385e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT, "Overflow");
386447354c6SJens Wiklander 			if (sh_end >= (elf->max_addr - elf->load_addr))
387e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
388dcf64f87SJens Wiklander 				    "STRTAB out of range");
3897509ff7cSJens Wiklander 
3907509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
3917509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
3927509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
3937509ff7cSJens Wiklander 		}
3947509ff7cSJens Wiklander 	}
3957509ff7cSJens Wiklander 
3967509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
397447354c6SJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
398447354c6SJens Wiklander 			 shdr[rel_sidx].sh_size, &sh_end))
399e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Overflow");
400447354c6SJens Wiklander 	if (sh_end >= (elf->max_addr - elf->load_addr))
401dcf64f87SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
4027509ff7cSJens Wiklander 	rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr);
4037509ff7cSJens Wiklander 
4047509ff7cSJens Wiklander 	rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel);
4057509ff7cSJens Wiklander 	for (; rel < rel_end; rel++) {
406c88ba125SJerome Forissier 		struct ta_elf *mod = NULL;
4077509ff7cSJens Wiklander 		Elf32_Addr *where = NULL;
4087509ff7cSJens Wiklander 		size_t sym_idx = 0;
409c88ba125SJerome Forissier 		vaddr_t val = 0;
4107509ff7cSJens Wiklander 
4117509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
412447354c6SJens Wiklander 		if (rel->r_offset >= (elf->max_addr - elf->load_addr))
413e97bbbb2SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT,
414447354c6SJens Wiklander 			    "Relocation offset out of range");
4157509ff7cSJens Wiklander 		where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
4167509ff7cSJens Wiklander 
4177509ff7cSJens Wiklander 		switch (ELF32_R_TYPE(rel->r_info)) {
418f104c8eeSEtienne Carriere 		case R_ARM_NONE:
419f104c8eeSEtienne Carriere 			/*
420f104c8eeSEtienne Carriere 			 * One would expect linker prevents such useless entry
421f104c8eeSEtienne Carriere 			 * in the relocation table. We still handle this type
422f104c8eeSEtienne Carriere 			 * here in case such entries exist.
423f104c8eeSEtienne Carriere 			 */
424f104c8eeSEtienne Carriere 			break;
4257509ff7cSJens Wiklander 		case R_ARM_ABS32:
4267509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
427447354c6SJens Wiklander 			if (sym_idx >= num_syms)
428e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
429447354c6SJens Wiklander 				    "Symbol index out of range");
4307509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
4317509ff7cSJens Wiklander 				/* Symbol is external */
4327509ff7cSJens Wiklander 				e32_process_dyn_rel(sym_tab, num_syms, str_tab,
4337509ff7cSJens Wiklander 						    str_tab_size, rel, where);
4347509ff7cSJens Wiklander 			} else {
4357509ff7cSJens Wiklander 				*where += elf->load_addr +
4367509ff7cSJens Wiklander 					  sym_tab[sym_idx].st_value;
4377509ff7cSJens Wiklander 			}
4387509ff7cSJens Wiklander 			break;
4397509ff7cSJens Wiklander 		case R_ARM_REL32:
4407509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
441447354c6SJens Wiklander 			if (sym_idx >= num_syms)
442e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
443447354c6SJens Wiklander 				    "Symbol index out of range");
4447509ff7cSJens Wiklander 			*where += sym_tab[sym_idx].st_value - rel->r_offset;
4457509ff7cSJens Wiklander 			break;
4467509ff7cSJens Wiklander 		case R_ARM_RELATIVE:
4477509ff7cSJens Wiklander 			*where += elf->load_addr;
4487509ff7cSJens Wiklander 			break;
4497509ff7cSJens Wiklander 		case R_ARM_GLOB_DAT:
4507509ff7cSJens Wiklander 		case R_ARM_JUMP_SLOT:
4516897ad0fSJens Wiklander 			if (!sym_tab)
4526897ad0fSJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
4536897ad0fSJens Wiklander 				    "Missing symbol table");
4547509ff7cSJens Wiklander 			e32_process_dyn_rel(sym_tab, num_syms, str_tab,
4557509ff7cSJens Wiklander 					    str_tab_size, rel, where);
4567509ff7cSJens Wiklander 			break;
457c88ba125SJerome Forissier 		case R_ARM_TLS_DTPMOD32:
4586897ad0fSJens Wiklander 			if (!sym_tab)
4596897ad0fSJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
4606897ad0fSJens Wiklander 				    "Missing symbol table");
461c88ba125SJerome Forissier 			mod = elf;
462c88ba125SJerome Forissier 			e32_tls_get_module(sym_tab, num_syms, str_tab,
463c88ba125SJerome Forissier 					   str_tab_size, rel, &mod);
464c88ba125SJerome Forissier 			*where = mod->tls_mod_id;
465c88ba125SJerome Forissier 			break;
466c88ba125SJerome Forissier 		case R_ARM_TLS_DTPOFF32:
4676897ad0fSJens Wiklander 			if (!sym_tab)
4686897ad0fSJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
4696897ad0fSJens Wiklander 				    "Missing symbol table");
470c88ba125SJerome Forissier 			e32_tls_resolve(sym_tab, num_syms, str_tab,
471c88ba125SJerome Forissier 					str_tab_size, rel, &val);
472c88ba125SJerome Forissier 			*where = val;
473c88ba125SJerome Forissier 			break;
4747509ff7cSJens Wiklander 		default:
4757509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
4767509ff7cSJens Wiklander 			     ELF32_R_TYPE(rel->r_info));
4777509ff7cSJens Wiklander 		}
4787509ff7cSJens Wiklander 	}
4797509ff7cSJens Wiklander }
4807509ff7cSJens Wiklander 
4818fab4371Sliushiwei #if defined(ARM64) || defined(RV64)
482fe684948SJerome Forissier static void e64_get_sym_name(const Elf64_Sym *sym_tab, size_t num_syms,
4837509ff7cSJens Wiklander 			     const char *str_tab, size_t str_tab_size,
484c44d734bSJerome Forissier 			     Elf64_Rela *rela, const char **name,
485c44d734bSJerome Forissier 			     bool *weak_undef)
4867509ff7cSJens Wiklander {
4877509ff7cSJens Wiklander 	size_t sym_idx = 0;
4887509ff7cSJens Wiklander 	size_t name_idx = 0;
4897509ff7cSJens Wiklander 
4907509ff7cSJens Wiklander 	sym_idx = ELF64_R_SYM(rela->r_info);
491447354c6SJens Wiklander 	if (sym_idx >= num_syms)
492e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
49355e64090SJens Wiklander 	sym_idx = confine_array_index(sym_idx, num_syms);
4947509ff7cSJens Wiklander 
4957509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
496447354c6SJens Wiklander 	if (name_idx >= str_tab_size)
497e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
498fe684948SJerome Forissier 	*name = str_tab + name_idx;
499c44d734bSJerome Forissier 
500c44d734bSJerome Forissier 	if (sym_tab[sym_idx].st_shndx == SHN_UNDEF &&
501c44d734bSJerome Forissier 	    ELF64_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK)
502c44d734bSJerome Forissier 		*weak_undef = true;
503c44d734bSJerome Forissier 	else
504c44d734bSJerome Forissier 		*weak_undef = false;
505fe684948SJerome Forissier }
5067509ff7cSJens Wiklander 
507fe684948SJerome Forissier static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
508fe684948SJerome Forissier 				 const char *str_tab, size_t str_tab_size,
509fe684948SJerome Forissier 				 Elf64_Rela *rela, Elf64_Addr *where)
510fe684948SJerome Forissier {
511fe684948SJerome Forissier 	const char *name = NULL;
512fe684948SJerome Forissier 	uintptr_t val = 0;
513c44d734bSJerome Forissier 	bool weak_undef = false;
514fe684948SJerome Forissier 
515c44d734bSJerome Forissier 	e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name,
516c44d734bSJerome Forissier 			 &weak_undef);
517c44d734bSJerome Forissier 	resolve_sym(name, &val, NULL, !weak_undef);
5187509ff7cSJens Wiklander 	*where = val;
5197509ff7cSJens Wiklander }
5207509ff7cSJens Wiklander 
5218fab4371Sliushiwei #ifdef ARM64
5227bc927faSJerome Forissier static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab,
5237bc927faSJerome Forissier 				       size_t num_syms, const char *str_tab,
5247bc927faSJerome Forissier 				       size_t str_tab_size, Elf64_Rela *rela,
5257bc927faSJerome Forissier 				       Elf64_Addr *where, struct ta_elf *elf)
526fe684948SJerome Forissier {
527fe684948SJerome Forissier 	struct ta_elf *mod = NULL;
528c44d734bSJerome Forissier 	bool weak_undef = false;
529fe684948SJerome Forissier 	const char *name = NULL;
5307bc927faSJerome Forissier 	size_t sym_idx = 0;
531fe684948SJerome Forissier 	vaddr_t symval = 0;
532fe684948SJerome Forissier 
5337bc927faSJerome Forissier 	sym_idx = ELF64_R_SYM(rela->r_info);
5347bc927faSJerome Forissier 	if (sym_idx) {
5357bc927faSJerome Forissier 		e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela,
536c44d734bSJerome Forissier 				 &name, &weak_undef);
537c44d734bSJerome Forissier 		resolve_sym(name, &symval, &mod, !weak_undef);
5387bc927faSJerome Forissier 	} else {
5397bc927faSJerome Forissier 		mod = elf;
5407bc927faSJerome Forissier 	}
541fe684948SJerome Forissier 	*where = symval + mod->tls_tcb_offs + rela->r_addend;
542fe684948SJerome Forissier }
543fe684948SJerome Forissier 
5447bc927faSJerome Forissier struct tlsdesc {
5457bc927faSJerome Forissier 	long (*resolver)(struct tlsdesc *td);
5467bc927faSJerome Forissier 	long value;
5477bc927faSJerome Forissier };
5487bc927faSJerome Forissier 
5497bc927faSJerome Forissier /* Helper function written in assembly due to the calling convention */
5507bc927faSJerome Forissier long tlsdesc_resolve(struct tlsdesc *td);
5517bc927faSJerome Forissier 
5527bc927faSJerome Forissier static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms,
5537bc927faSJerome Forissier 				     const char *str_tab, size_t str_tab_size,
5547bc927faSJerome Forissier 				     Elf64_Rela *rela, Elf64_Addr *where,
5557bc927faSJerome Forissier 				     struct ta_elf *elf)
5567bc927faSJerome Forissier {
5577bc927faSJerome Forissier 	/*
5587bc927faSJerome Forissier 	 * @where points to a pair of 64-bit words in the GOT or PLT which is
5597bc927faSJerome Forissier 	 * mapped to a struct tlsdesc:
5607bc927faSJerome Forissier 	 *
5617bc927faSJerome Forissier 	 * - resolver() must return the offset of the thread-local variable
5627bc927faSJerome Forissier 	 *   relative to TPIDR_EL0.
5637bc927faSJerome Forissier 	 * - value is implementation-dependent. The TLS_TPREL handling code is
5647bc927faSJerome Forissier 	 *   re-used to get the desired offset so that tlsdesc_resolve() just
5657bc927faSJerome Forissier 	 *   needs to return this value.
5667bc927faSJerome Forissier 	 *
5677bc927faSJerome Forissier 	 * Both the TA and ldelf are AArch64 so it is OK to point to a function
5687bc927faSJerome Forissier 	 * in ldelf.
5697bc927faSJerome Forissier 	 */
5707bc927faSJerome Forissier 	*where = (Elf64_Addr)tlsdesc_resolve;
5717bc927faSJerome Forissier 	e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size,
5727bc927faSJerome Forissier 				   rela, where + 1, elf);
5737bc927faSJerome Forissier }
5748fab4371Sliushiwei #endif /*ARM64*/
5757bc927faSJerome Forissier 
5767509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
5777509ff7cSJens Wiklander {
5787509ff7cSJens Wiklander 	Elf64_Shdr *shdr = elf->shdr;
5797509ff7cSJens Wiklander 	Elf64_Rela *rela = NULL;
5807509ff7cSJens Wiklander 	Elf64_Rela *rela_end = NULL;
5817509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
5827509ff7cSJens Wiklander 	Elf64_Sym *sym_tab = NULL;
5837509ff7cSJens Wiklander 	size_t num_syms = 0;
5847509ff7cSJens Wiklander 	size_t sh_end = 0;
5857509ff7cSJens Wiklander 	const char *str_tab = NULL;
5867509ff7cSJens Wiklander 	size_t str_tab_size = 0;
5877509ff7cSJens Wiklander 
5887509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_RELA);
5897509ff7cSJens Wiklander 
5907509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
5917509ff7cSJens Wiklander 
5927509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
5937509ff7cSJens Wiklander 	if (sym_tab_idx) {
5947509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
5957509ff7cSJens Wiklander 
596447354c6SJens Wiklander 		if (sym_tab_idx >= elf->e_shnum)
597dcf64f87SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
59855e64090SJens Wiklander 		sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
5997509ff7cSJens Wiklander 
6007509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
6017509ff7cSJens Wiklander 
6027509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
6037509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
6047509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
605e97bbbb2SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Overflow");
606447354c6SJens Wiklander 		if (sh_end >= (elf->max_addr - elf->load_addr))
607dcf64f87SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
6087509ff7cSJens Wiklander 
6097509ff7cSJens Wiklander 		sym_tab = (Elf64_Sym *)(elf->load_addr +
6107509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
6117509ff7cSJens Wiklander 
6127509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
6137509ff7cSJens Wiklander 
6147509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
6157509ff7cSJens Wiklander 		if (str_tab_idx) {
61655e64090SJens Wiklander 			if (str_tab_idx >= elf->e_shnum)
617e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
618dcf64f87SJens Wiklander 				    "STRTAB index out of range");
61955e64090SJens Wiklander 			str_tab_idx = confine_array_index(str_tab_idx,
62055e64090SJens Wiklander 							  elf->e_shnum);
62155e64090SJens Wiklander 
6227509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
6237509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
6247509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
625e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT, "Overflow");
626447354c6SJens Wiklander 			if (sh_end >= (elf->max_addr - elf->load_addr))
627e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
628dcf64f87SJens Wiklander 				    "STRTAB out of range");
6297509ff7cSJens Wiklander 
6307509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
6317509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
6327509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
6337509ff7cSJens Wiklander 		}
6347509ff7cSJens Wiklander 	}
6357509ff7cSJens Wiklander 
6367509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
637447354c6SJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
638447354c6SJens Wiklander 			 shdr[rel_sidx].sh_size, &sh_end))
639e97bbbb2SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Overflow");
640447354c6SJens Wiklander 	if (sh_end >= (elf->max_addr - elf->load_addr))
641dcf64f87SJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
6427509ff7cSJens Wiklander 	rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
6437509ff7cSJens Wiklander 
6447509ff7cSJens Wiklander 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
6457509ff7cSJens Wiklander 	for (; rela < rela_end; rela++) {
6467509ff7cSJens Wiklander 		Elf64_Addr *where = NULL;
6477509ff7cSJens Wiklander 		size_t sym_idx = 0;
6487509ff7cSJens Wiklander 
6497509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
650447354c6SJens Wiklander 		if (rela->r_offset >= (elf->max_addr - elf->load_addr))
651e97bbbb2SJens Wiklander 			err(TEE_ERROR_BAD_FORMAT,
652447354c6SJens Wiklander 			    "Relocation offset out of range");
6537509ff7cSJens Wiklander 
6547509ff7cSJens Wiklander 		where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
6557509ff7cSJens Wiklander 
6567509ff7cSJens Wiklander 		switch (ELF64_R_TYPE(rela->r_info)) {
6578fab4371Sliushiwei #ifdef ARM64
6587a4dc765SEtienne Carriere 		case R_AARCH64_NONE:
6597a4dc765SEtienne Carriere 			/*
6607a4dc765SEtienne Carriere 			 * One would expect linker prevents such useless entry
6617a4dc765SEtienne Carriere 			 * in the relocation table. We still handle this type
6627a4dc765SEtienne Carriere 			 * here in case such entries exist.
6637a4dc765SEtienne Carriere 			 */
6647a4dc765SEtienne Carriere 			break;
6657509ff7cSJens Wiklander 		case R_AARCH64_ABS64:
6667509ff7cSJens Wiklander 			sym_idx = ELF64_R_SYM(rela->r_info);
667447354c6SJens Wiklander 			if (sym_idx >= num_syms)
668e97bbbb2SJens Wiklander 				err(TEE_ERROR_BAD_FORMAT,
669447354c6SJens Wiklander 				    "Symbol index out of range");
67055e64090SJens Wiklander 			sym_idx = confine_array_index(sym_idx, num_syms);
6717509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
6727509ff7cSJens Wiklander 				/* Symbol is external */
6737509ff7cSJens Wiklander 				e64_process_dyn_rela(sym_tab, num_syms, str_tab,
6747509ff7cSJens Wiklander 						     str_tab_size, rela, where);
6757509ff7cSJens Wiklander 			} else {
6767509ff7cSJens Wiklander 				*where = rela->r_addend + elf->load_addr +
6777509ff7cSJens Wiklander 					 sym_tab[sym_idx].st_value;
6787509ff7cSJens Wiklander 			}
6797509ff7cSJens Wiklander 			break;
6807509ff7cSJens Wiklander 		case R_AARCH64_RELATIVE:
6817509ff7cSJens Wiklander 			*where = rela->r_addend + elf->load_addr;
6827509ff7cSJens Wiklander 			break;
6837509ff7cSJens Wiklander 		case R_AARCH64_GLOB_DAT:
6847509ff7cSJens Wiklander 		case R_AARCH64_JUMP_SLOT:
6857509ff7cSJens Wiklander 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
6867509ff7cSJens Wiklander 					     str_tab_size, rela, where);
6877509ff7cSJens Wiklander 			break;
688fe684948SJerome Forissier 		case R_AARCH64_TLS_TPREL:
6897bc927faSJerome Forissier 			e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab,
6907bc927faSJerome Forissier 						   str_tab_size, rela, where,
6917bc927faSJerome Forissier 						   elf);
6927bc927faSJerome Forissier 			break;
6937bc927faSJerome Forissier 		case R_AARCH64_TLSDESC:
6947bc927faSJerome Forissier 			e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab,
6957bc927faSJerome Forissier 						 str_tab_size, rela, where,
6967bc927faSJerome Forissier 						 elf);
697fe684948SJerome Forissier 			break;
6988fab4371Sliushiwei #endif /*ARM64*/
6998fab4371Sliushiwei #ifdef RV64
7008fab4371Sliushiwei 		case R_RISCV_NONE:
7018fab4371Sliushiwei 			/*
7028fab4371Sliushiwei 			 * One would expect linker prevents such useless entry
7038fab4371Sliushiwei 			 * in the relocation table. We still handle this type
7048fab4371Sliushiwei 			 * here in case such entries exist.
7058fab4371Sliushiwei 			 */
7068fab4371Sliushiwei 			break;
7078fab4371Sliushiwei 		case R_RISCV_RELATIVE:
7088fab4371Sliushiwei 			*where = rela->r_addend + elf->load_addr;
7098fab4371Sliushiwei 			break;
7108fab4371Sliushiwei 		case R_RISCV_64:
7118fab4371Sliushiwei 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
7128fab4371Sliushiwei 					     str_tab_size, rela, where);
7138fab4371Sliushiwei 			*where += rela->r_addend;
7148fab4371Sliushiwei 			break;
7158fab4371Sliushiwei 		case R_RISCV_JUMP_SLOT:
7168fab4371Sliushiwei 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
7178fab4371Sliushiwei 					     str_tab_size, rela, where);
7188fab4371Sliushiwei 			break;
7198fab4371Sliushiwei #endif /*RV64*/
7207509ff7cSJens Wiklander 		default:
7217509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
7227509ff7cSJens Wiklander 			     ELF64_R_TYPE(rela->r_info));
7237509ff7cSJens Wiklander 		}
7247509ff7cSJens Wiklander 	}
7257509ff7cSJens Wiklander }
7268fab4371Sliushiwei #else /*ARM64 || RV64*/
7275548a710SJerome Forissier static void __noreturn e64_relocate(struct ta_elf *elf __unused,
7287509ff7cSJens Wiklander 				    unsigned int rel_sidx __unused)
7297509ff7cSJens Wiklander {
7307509ff7cSJens Wiklander 	err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
7317509ff7cSJens Wiklander }
7328fab4371Sliushiwei #endif /*ARM64 || RV64*/
7337509ff7cSJens Wiklander 
7347509ff7cSJens Wiklander void ta_elf_relocate(struct ta_elf *elf)
7357509ff7cSJens Wiklander {
7367509ff7cSJens Wiklander 	size_t n = 0;
7377509ff7cSJens Wiklander 
7387509ff7cSJens Wiklander 	if (elf->is_32bit) {
7397509ff7cSJens Wiklander 		Elf32_Shdr *shdr = elf->shdr;
7407509ff7cSJens Wiklander 
7417509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
7427509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_REL)
7437509ff7cSJens Wiklander 				e32_relocate(elf, n);
7447509ff7cSJens Wiklander 	} else {
7457509ff7cSJens Wiklander 		Elf64_Shdr *shdr = elf->shdr;
7467509ff7cSJens Wiklander 
7477509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
7487509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_RELA)
7497509ff7cSJens Wiklander 				e64_relocate(elf, n);
7507509ff7cSJens Wiklander 
7517509ff7cSJens Wiklander 	}
7527509ff7cSJens Wiklander }
753