xref: /optee_os/ldelf/ta_elf_rel.c (revision c86f218c5bc8ba0deb6e7c6ff58f8db93c01e32f)
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>
77509ff7cSJens Wiklander #include <elf32.h>
87509ff7cSJens Wiklander #include <elf64.h>
97509ff7cSJens Wiklander #include <elf_common.h>
107509ff7cSJens Wiklander #include <string.h>
117509ff7cSJens Wiklander #include <tee_api_types.h>
127509ff7cSJens Wiklander #include <util.h>
137509ff7cSJens Wiklander 
147509ff7cSJens Wiklander #include "sys.h"
157509ff7cSJens Wiklander #include "ta_elf.h"
167509ff7cSJens Wiklander 
179f392760SJerome Forissier static uint32_t elf_hash(const char *name)
189f392760SJerome Forissier {
199f392760SJerome Forissier 	const unsigned char *p = (const unsigned char *)name;
209f392760SJerome Forissier 	uint32_t h = 0;
219f392760SJerome Forissier 	uint32_t g = 0;
229f392760SJerome Forissier 
239f392760SJerome Forissier 	while (*p) {
249f392760SJerome Forissier 		h = (h << 4) + *p++;
259f392760SJerome Forissier 		g = h & 0xf0000000;
269f392760SJerome Forissier 		if (g)
279f392760SJerome Forissier 			h ^= g >> 24;
289f392760SJerome Forissier 		h &= ~g;
299f392760SJerome Forissier 	}
309f392760SJerome Forissier 	return h;
319f392760SJerome Forissier }
329f392760SJerome Forissier 
337509ff7cSJens Wiklander static bool __resolve_sym(struct ta_elf *elf, unsigned int bind,
347509ff7cSJens Wiklander 			  size_t st_shndx, size_t st_name, size_t st_value,
357509ff7cSJens Wiklander 			  const char *name, vaddr_t *val)
367509ff7cSJens Wiklander {
377509ff7cSJens Wiklander 	if (bind != STB_GLOBAL)
387509ff7cSJens Wiklander 		return false;
397509ff7cSJens Wiklander 	if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX)
407509ff7cSJens Wiklander 		return false;
417509ff7cSJens Wiklander 	if (!st_name)
427509ff7cSJens Wiklander 		return false;
437509ff7cSJens Wiklander 	if (st_name > elf->dynstr_size)
447509ff7cSJens Wiklander 		err(TEE_ERROR_BAD_FORMAT, "Symbol out of range");
457509ff7cSJens Wiklander 
467509ff7cSJens Wiklander 	if (strcmp(name, elf->dynstr + st_name))
477509ff7cSJens Wiklander 		return false;
487509ff7cSJens Wiklander 
497509ff7cSJens Wiklander 	*val = st_value + elf->load_addr;
507509ff7cSJens Wiklander 	return true;
517509ff7cSJens Wiklander }
527509ff7cSJens Wiklander 
53*c86f218cSJens Wiklander TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val)
547509ff7cSJens Wiklander {
559f392760SJerome Forissier 	uint32_t hash = elf_hash(name);
567509ff7cSJens Wiklander 	struct ta_elf *elf = NULL;
577509ff7cSJens Wiklander 	size_t n = 0;
587509ff7cSJens Wiklander 
597509ff7cSJens Wiklander 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
609f392760SJerome Forissier 		/*
619f392760SJerome Forissier 		 * Using uint32_t here for convenience because both Elf64_Word
629f392760SJerome Forissier 		 * and Elf32_Word are 32-bit types
639f392760SJerome Forissier 		 */
649f392760SJerome Forissier 		uint32_t *hashtab = elf->hashtab;
659f392760SJerome Forissier 		uint32_t nbuckets = hashtab[0];
669f392760SJerome Forissier 		uint32_t nchains = hashtab[1];
679f392760SJerome Forissier 		uint32_t *bucket = &hashtab[2];
689f392760SJerome Forissier 		uint32_t *chain = &bucket[nbuckets];
699f392760SJerome Forissier 
707509ff7cSJens Wiklander 		if (elf->is_32bit) {
717509ff7cSJens Wiklander 			Elf32_Sym *sym = elf->dynsymtab;
727509ff7cSJens Wiklander 
739f392760SJerome Forissier 			for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
749f392760SJerome Forissier 				assert(n < nchains);
757509ff7cSJens Wiklander 				if (__resolve_sym(elf,
767509ff7cSJens Wiklander 						  ELF32_ST_BIND(sym[n].st_info),
777509ff7cSJens Wiklander 						  sym[n].st_shndx,
787509ff7cSJens Wiklander 						  sym[n].st_name,
797509ff7cSJens Wiklander 						  sym[n].st_value, name, val))
80*c86f218cSJens Wiklander 					return TEE_SUCCESS;
817509ff7cSJens Wiklander 			}
827509ff7cSJens Wiklander 		} else {
837509ff7cSJens Wiklander 			Elf64_Sym *sym = elf->dynsymtab;
847509ff7cSJens Wiklander 
859f392760SJerome Forissier 			for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
869f392760SJerome Forissier 				assert(n < nchains);
877509ff7cSJens Wiklander 				if (__resolve_sym(elf,
887509ff7cSJens Wiklander 						  ELF64_ST_BIND(sym[n].st_info),
897509ff7cSJens Wiklander 						  sym[n].st_shndx,
907509ff7cSJens Wiklander 						  sym[n].st_name,
917509ff7cSJens Wiklander 						  sym[n].st_value, name, val))
92*c86f218cSJens Wiklander 					return TEE_SUCCESS;
937509ff7cSJens Wiklander 			}
947509ff7cSJens Wiklander 		}
957509ff7cSJens Wiklander 	}
96*c86f218cSJens Wiklander 
97*c86f218cSJens Wiklander 	return TEE_ERROR_ITEM_NOT_FOUND;
98*c86f218cSJens Wiklander }
99*c86f218cSJens Wiklander 
100*c86f218cSJens Wiklander static void resolve_sym(const char *name, vaddr_t *val)
101*c86f218cSJens Wiklander {
102*c86f218cSJens Wiklander 	TEE_Result res = ta_elf_resolve_sym(name, val);
103*c86f218cSJens Wiklander 
104*c86f218cSJens Wiklander 	if (res)
105*c86f218cSJens Wiklander 		err(res, "Symbol %s not found", name);
1067509ff7cSJens Wiklander }
1077509ff7cSJens Wiklander 
1087509ff7cSJens Wiklander static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms,
1097509ff7cSJens Wiklander 				const char *str_tab, size_t str_tab_size,
1107509ff7cSJens Wiklander 				Elf32_Rel *rel, Elf32_Addr *where)
1117509ff7cSJens Wiklander {
1127509ff7cSJens Wiklander 	size_t sym_idx = 0;
1137509ff7cSJens Wiklander 	const char *name = NULL;
1147509ff7cSJens Wiklander 	vaddr_t val = 0;
1157509ff7cSJens Wiklander 	size_t name_idx = 0;
1167509ff7cSJens Wiklander 
1177509ff7cSJens Wiklander 	sym_idx = ELF32_R_SYM(rel->r_info);
1187509ff7cSJens Wiklander 	assert(sym_idx < num_syms);
1197509ff7cSJens Wiklander 
1207509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
1217509ff7cSJens Wiklander 	assert(name_idx < str_tab_size);
1227509ff7cSJens Wiklander 	name = str_tab + name_idx;
1237509ff7cSJens Wiklander 
1247509ff7cSJens Wiklander 	resolve_sym(name, &val);
1257509ff7cSJens Wiklander 	*where = val;
1267509ff7cSJens Wiklander }
1277509ff7cSJens Wiklander 
1287509ff7cSJens Wiklander static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx)
1297509ff7cSJens Wiklander {
1307509ff7cSJens Wiklander 	Elf32_Shdr *shdr = elf->shdr;
1317509ff7cSJens Wiklander 	Elf32_Rel *rel = NULL;
1327509ff7cSJens Wiklander 	Elf32_Rel *rel_end = NULL;
1337509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
1347509ff7cSJens Wiklander 	Elf32_Sym *sym_tab = NULL;
1357509ff7cSJens Wiklander 	size_t num_syms = 0;
1367509ff7cSJens Wiklander 	size_t sh_end = 0;
1377509ff7cSJens Wiklander 	const char *str_tab = NULL;
1387509ff7cSJens Wiklander 	size_t str_tab_size = 0;
1397509ff7cSJens Wiklander 
1407509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_REL);
1417509ff7cSJens Wiklander 
1427509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel));
1437509ff7cSJens Wiklander 
1447509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
1457509ff7cSJens Wiklander 	if (sym_tab_idx) {
1467509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
1477509ff7cSJens Wiklander 
1487509ff7cSJens Wiklander 		assert(sym_tab_idx < elf->e_shnum);
1497509ff7cSJens Wiklander 
1507509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym));
1517509ff7cSJens Wiklander 
1527509ff7cSJens Wiklander 		/* Check the address is inside ELF memory */
1537509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
1547509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
1557509ff7cSJens Wiklander 			err(TEE_ERROR_SECURITY, "Overflow");
1567509ff7cSJens Wiklander 		assert(sh_end < (elf->max_addr - elf->load_addr));
1577509ff7cSJens Wiklander 
1587509ff7cSJens Wiklander 		sym_tab = (Elf32_Sym *)(elf->load_addr +
1597509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
1607509ff7cSJens Wiklander 
1617509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym);
1627509ff7cSJens Wiklander 
1637509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
1647509ff7cSJens Wiklander 		if (str_tab_idx) {
1657509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
1667509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
1677509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
1687509ff7cSJens Wiklander 				err(TEE_ERROR_SECURITY, "Overflow");
1697509ff7cSJens Wiklander 			assert(sh_end < (elf->max_addr - elf->load_addr));
1707509ff7cSJens Wiklander 
1717509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
1727509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
1737509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
1747509ff7cSJens Wiklander 		}
1757509ff7cSJens Wiklander 	}
1767509ff7cSJens Wiklander 
1777509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
1787509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr));
1797509ff7cSJens Wiklander 	rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr);
1807509ff7cSJens Wiklander 
1817509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
1827509ff7cSJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size,
1837509ff7cSJens Wiklander 			 &sh_end))
1847509ff7cSJens Wiklander 		err(TEE_ERROR_SECURITY, "Overflow");
1857509ff7cSJens Wiklander 	assert(sh_end < (elf->max_addr - elf->load_addr));
1867509ff7cSJens Wiklander 	rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel);
1877509ff7cSJens Wiklander 	for (; rel < rel_end; rel++) {
1887509ff7cSJens Wiklander 		Elf32_Addr *where = NULL;
1897509ff7cSJens Wiklander 		size_t sym_idx = 0;
1907509ff7cSJens Wiklander 
1917509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
1927509ff7cSJens Wiklander 		assert(rel->r_offset < (elf->max_addr - elf->load_addr));
1937509ff7cSJens Wiklander 		where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
1947509ff7cSJens Wiklander 
1957509ff7cSJens Wiklander 		switch (ELF32_R_TYPE(rel->r_info)) {
1967509ff7cSJens Wiklander 		case R_ARM_ABS32:
1977509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
1987509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
1997509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
2007509ff7cSJens Wiklander 				/* Symbol is external */
2017509ff7cSJens Wiklander 				e32_process_dyn_rel(sym_tab, num_syms, str_tab,
2027509ff7cSJens Wiklander 						    str_tab_size, rel, where);
2037509ff7cSJens Wiklander 			} else {
2047509ff7cSJens Wiklander 				*where += elf->load_addr +
2057509ff7cSJens Wiklander 					  sym_tab[sym_idx].st_value;
2067509ff7cSJens Wiklander 			}
2077509ff7cSJens Wiklander 			break;
2087509ff7cSJens Wiklander 		case R_ARM_REL32:
2097509ff7cSJens Wiklander 			sym_idx = ELF32_R_SYM(rel->r_info);
2107509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
2117509ff7cSJens Wiklander 			*where += sym_tab[sym_idx].st_value - rel->r_offset;
2127509ff7cSJens Wiklander 			break;
2137509ff7cSJens Wiklander 		case R_ARM_RELATIVE:
2147509ff7cSJens Wiklander 			*where += elf->load_addr;
2157509ff7cSJens Wiklander 			break;
2167509ff7cSJens Wiklander 		case R_ARM_GLOB_DAT:
2177509ff7cSJens Wiklander 		case R_ARM_JUMP_SLOT:
2187509ff7cSJens Wiklander 			e32_process_dyn_rel(sym_tab, num_syms, str_tab,
2197509ff7cSJens Wiklander 					    str_tab_size, rel, where);
2207509ff7cSJens Wiklander 			break;
2217509ff7cSJens Wiklander 		default:
2227509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
2237509ff7cSJens Wiklander 			     ELF32_R_TYPE(rel->r_info));
2247509ff7cSJens Wiklander 		}
2257509ff7cSJens Wiklander 	}
2267509ff7cSJens Wiklander }
2277509ff7cSJens Wiklander 
2287509ff7cSJens Wiklander #ifdef ARM64
2297509ff7cSJens Wiklander static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
2307509ff7cSJens Wiklander 				 const char *str_tab, size_t str_tab_size,
2317509ff7cSJens Wiklander 				 Elf64_Rela *rela, Elf64_Addr *where)
2327509ff7cSJens Wiklander {
2337509ff7cSJens Wiklander 	size_t sym_idx = 0;
2347509ff7cSJens Wiklander 	const char *name = NULL;
2357509ff7cSJens Wiklander 	uintptr_t val = 0;
2367509ff7cSJens Wiklander 	size_t name_idx = 0;
2377509ff7cSJens Wiklander 
2387509ff7cSJens Wiklander 	sym_idx = ELF64_R_SYM(rela->r_info);
2397509ff7cSJens Wiklander 	assert(sym_idx < num_syms);
2407509ff7cSJens Wiklander 
2417509ff7cSJens Wiklander 	name_idx = sym_tab[sym_idx].st_name;
2427509ff7cSJens Wiklander 	assert(name_idx < str_tab_size);
2437509ff7cSJens Wiklander 	name = str_tab + name_idx;
2447509ff7cSJens Wiklander 
2457509ff7cSJens Wiklander 	resolve_sym(name, &val);
2467509ff7cSJens Wiklander 	*where = val;
2477509ff7cSJens Wiklander }
2487509ff7cSJens Wiklander 
2497509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
2507509ff7cSJens Wiklander {
2517509ff7cSJens Wiklander 	Elf64_Shdr *shdr = elf->shdr;
2527509ff7cSJens Wiklander 	Elf64_Rela *rela = NULL;
2537509ff7cSJens Wiklander 	Elf64_Rela *rela_end = NULL;
2547509ff7cSJens Wiklander 	size_t sym_tab_idx = 0;
2557509ff7cSJens Wiklander 	Elf64_Sym *sym_tab = NULL;
2567509ff7cSJens Wiklander 	size_t num_syms = 0;
2577509ff7cSJens Wiklander 	size_t sh_end = 0;
2587509ff7cSJens Wiklander 	const char *str_tab = NULL;
2597509ff7cSJens Wiklander 	size_t str_tab_size = 0;
2607509ff7cSJens Wiklander 
2617509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_type == SHT_RELA);
2627509ff7cSJens Wiklander 
2637509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
2647509ff7cSJens Wiklander 
2657509ff7cSJens Wiklander 	sym_tab_idx = shdr[rel_sidx].sh_link;
2667509ff7cSJens Wiklander 	if (sym_tab_idx) {
2677509ff7cSJens Wiklander 		size_t str_tab_idx = 0;
2687509ff7cSJens Wiklander 
2697509ff7cSJens Wiklander 		assert(sym_tab_idx < elf->e_shnum);
2707509ff7cSJens Wiklander 
2717509ff7cSJens Wiklander 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
2727509ff7cSJens Wiklander 
2737509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
2747509ff7cSJens Wiklander 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
2757509ff7cSJens Wiklander 				 shdr[sym_tab_idx].sh_size, &sh_end))
2767509ff7cSJens Wiklander 			err(TEE_ERROR_SECURITY, "Overflow");
2777509ff7cSJens Wiklander 		assert(sh_end < (elf->max_addr - elf->load_addr));
2787509ff7cSJens Wiklander 
2797509ff7cSJens Wiklander 		sym_tab = (Elf64_Sym *)(elf->load_addr +
2807509ff7cSJens Wiklander 					shdr[sym_tab_idx].sh_addr);
2817509ff7cSJens Wiklander 
2827509ff7cSJens Wiklander 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
2837509ff7cSJens Wiklander 
2847509ff7cSJens Wiklander 		str_tab_idx = shdr[sym_tab_idx].sh_link;
2857509ff7cSJens Wiklander 		if (str_tab_idx) {
2867509ff7cSJens Wiklander 			/* Check the address is inside ELF memory */
2877509ff7cSJens Wiklander 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
2887509ff7cSJens Wiklander 					 shdr[str_tab_idx].sh_size, &sh_end))
2897509ff7cSJens Wiklander 				err(TEE_ERROR_SECURITY, "Overflow");
2907509ff7cSJens Wiklander 			assert(sh_end < (elf->max_addr - elf->load_addr));
2917509ff7cSJens Wiklander 
2927509ff7cSJens Wiklander 			str_tab = (const char *)(elf->load_addr +
2937509ff7cSJens Wiklander 						 shdr[str_tab_idx].sh_addr);
2947509ff7cSJens Wiklander 			str_tab_size = shdr[str_tab_idx].sh_size;
2957509ff7cSJens Wiklander 		}
2967509ff7cSJens Wiklander 	}
2977509ff7cSJens Wiklander 
2987509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
2997509ff7cSJens Wiklander 	assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr));
3007509ff7cSJens Wiklander 	rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
3017509ff7cSJens Wiklander 
3027509ff7cSJens Wiklander 	/* Check the address is inside TA memory */
3037509ff7cSJens Wiklander 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size,
3047509ff7cSJens Wiklander 			 &sh_end))
3057509ff7cSJens Wiklander 		err(TEE_ERROR_SECURITY, "Overflow");
3067509ff7cSJens Wiklander 	assert(sh_end < (elf->max_addr - elf->load_addr));
3077509ff7cSJens Wiklander 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
3087509ff7cSJens Wiklander 	for (; rela < rela_end; rela++) {
3097509ff7cSJens Wiklander 		Elf64_Addr *where = NULL;
3107509ff7cSJens Wiklander 		size_t sym_idx = 0;
3117509ff7cSJens Wiklander 
3127509ff7cSJens Wiklander 		/* Check the address is inside TA memory */
3137509ff7cSJens Wiklander 		assert(rela->r_offset < (elf->max_addr - elf->load_addr));
3147509ff7cSJens Wiklander 
3157509ff7cSJens Wiklander 		where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
3167509ff7cSJens Wiklander 
3177509ff7cSJens Wiklander 		switch (ELF64_R_TYPE(rela->r_info)) {
3187509ff7cSJens Wiklander 		case R_AARCH64_ABS64:
3197509ff7cSJens Wiklander 			sym_idx = ELF64_R_SYM(rela->r_info);
3207509ff7cSJens Wiklander 			assert(sym_idx < num_syms);
3217509ff7cSJens Wiklander 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
3227509ff7cSJens Wiklander 				/* Symbol is external */
3237509ff7cSJens Wiklander 				e64_process_dyn_rela(sym_tab, num_syms, str_tab,
3247509ff7cSJens Wiklander 						     str_tab_size, rela, where);
3257509ff7cSJens Wiklander 			} else {
3267509ff7cSJens Wiklander 				*where = rela->r_addend + elf->load_addr +
3277509ff7cSJens Wiklander 					 sym_tab[sym_idx].st_value;
3287509ff7cSJens Wiklander 			}
3297509ff7cSJens Wiklander 			break;
3307509ff7cSJens Wiklander 		case R_AARCH64_RELATIVE:
3317509ff7cSJens Wiklander 			*where = rela->r_addend + elf->load_addr;
3327509ff7cSJens Wiklander 			break;
3337509ff7cSJens Wiklander 		case R_AARCH64_GLOB_DAT:
3347509ff7cSJens Wiklander 		case R_AARCH64_JUMP_SLOT:
3357509ff7cSJens Wiklander 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
3367509ff7cSJens Wiklander 					     str_tab_size, rela, where);
3377509ff7cSJens Wiklander 			break;
3387509ff7cSJens Wiklander 		default:
3397509ff7cSJens Wiklander 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
3407509ff7cSJens Wiklander 			     ELF64_R_TYPE(rela->r_info));
3417509ff7cSJens Wiklander 		}
3427509ff7cSJens Wiklander 	}
3437509ff7cSJens Wiklander }
3447509ff7cSJens Wiklander #else /*ARM64*/
3457509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf __unused,
3467509ff7cSJens Wiklander 			 unsigned int rel_sidx __unused)
3477509ff7cSJens Wiklander {
3487509ff7cSJens Wiklander 	err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
3497509ff7cSJens Wiklander }
3507509ff7cSJens Wiklander #endif /*ARM64*/
3517509ff7cSJens Wiklander 
3527509ff7cSJens Wiklander void ta_elf_relocate(struct ta_elf *elf)
3537509ff7cSJens Wiklander {
3547509ff7cSJens Wiklander 	size_t n = 0;
3557509ff7cSJens Wiklander 
3567509ff7cSJens Wiklander 	if (elf->is_32bit) {
3577509ff7cSJens Wiklander 		Elf32_Shdr *shdr = elf->shdr;
3587509ff7cSJens Wiklander 
3597509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
3607509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_REL)
3617509ff7cSJens Wiklander 				e32_relocate(elf, n);
3627509ff7cSJens Wiklander 	} else {
3637509ff7cSJens Wiklander 		Elf64_Shdr *shdr = elf->shdr;
3647509ff7cSJens Wiklander 
3657509ff7cSJens Wiklander 		for (n = 0; n < elf->e_shnum; n++)
3667509ff7cSJens Wiklander 			if (shdr[n].sh_type == SHT_RELA)
3677509ff7cSJens Wiklander 				e64_relocate(elf, n);
3687509ff7cSJens Wiklander 
3697509ff7cSJens Wiklander 	}
3707509ff7cSJens Wiklander }
371