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 35*bdf82531SJerome Forissier static uint32_t gnu_hash(const char *name) 36*bdf82531SJerome Forissier { 37*bdf82531SJerome Forissier const unsigned char *p = (const unsigned char *)name; 38*bdf82531SJerome Forissier uint32_t h = 5381; 39*bdf82531SJerome Forissier 40*bdf82531SJerome Forissier while (*p) 41*bdf82531SJerome Forissier h = (h << 5) + h + *p++; 42*bdf82531SJerome Forissier 43*bdf82531SJerome Forissier return h; 44*bdf82531SJerome Forissier } 45*bdf82531SJerome Forissier 46*bdf82531SJerome 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 92*bdf82531SJerome Forissier static bool check_found_sym(struct ta_elf *elf, const char *name, vaddr_t *val, 93*bdf82531SJerome Forissier bool weak_ok, size_t n) 947509ff7cSJens Wiklander { 95*bdf82531SJerome Forissier Elf32_Sym *sym32 = NULL; 96*bdf82531SJerome Forissier Elf64_Sym *sym64 = NULL; 97*bdf82531SJerome Forissier unsigned int st_bind = 0; 98*bdf82531SJerome Forissier unsigned int st_type = 0; 99*bdf82531SJerome Forissier size_t st_shndx = 0; 100*bdf82531SJerome Forissier size_t st_name = 0; 101*bdf82531SJerome Forissier size_t st_value = 0; 102*bdf82531SJerome Forissier 103*bdf82531SJerome Forissier if (n >= elf->num_dynsyms) 104*bdf82531SJerome Forissier err(TEE_ERROR_BAD_FORMAT, "Index out of range"); 105*bdf82531SJerome Forissier 106*bdf82531SJerome Forissier /* 107*bdf82531SJerome Forissier * We're loading values from sym[] which later 108*bdf82531SJerome Forissier * will be used to load something. 109*bdf82531SJerome Forissier * => Spectre V1 pattern, need to cap the index 110*bdf82531SJerome Forissier * against speculation. 111*bdf82531SJerome Forissier */ 112*bdf82531SJerome Forissier n = confine_array_index(n, elf->num_dynsyms); 113*bdf82531SJerome Forissier 114*bdf82531SJerome Forissier if (elf->is_32bit) { 115*bdf82531SJerome Forissier sym32 = elf->dynsymtab; 116*bdf82531SJerome Forissier st_bind = ELF32_ST_BIND(sym32[n].st_info); 117*bdf82531SJerome Forissier st_type = ELF32_ST_TYPE(sym32[n].st_info); 118*bdf82531SJerome Forissier st_shndx = sym32[n].st_shndx; 119*bdf82531SJerome Forissier st_name = sym32[n].st_name; 120*bdf82531SJerome Forissier st_value = sym32[n].st_value; 121*bdf82531SJerome Forissier } else { 122*bdf82531SJerome Forissier sym64 = elf->dynsymtab; 123*bdf82531SJerome Forissier st_bind = ELF64_ST_BIND(sym64[n].st_info); 124*bdf82531SJerome Forissier st_type = ELF64_ST_TYPE(sym64[n].st_info); 125*bdf82531SJerome Forissier st_shndx = sym64[n].st_shndx; 126*bdf82531SJerome Forissier st_name = sym64[n].st_name; 127*bdf82531SJerome Forissier st_value = sym64[n].st_value; 128*bdf82531SJerome Forissier } 129*bdf82531SJerome Forissier 130*bdf82531SJerome Forissier return sym_compare(elf, st_bind, st_type, st_shndx, st_name, st_value, 131*bdf82531SJerome Forissier name, val, weak_ok); 132*bdf82531SJerome Forissier } 133*bdf82531SJerome Forissier 134*bdf82531SJerome Forissier static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val, 135*bdf82531SJerome Forissier struct ta_elf *elf, bool weak_ok) 136*bdf82531SJerome Forissier { 137*bdf82531SJerome Forissier uint32_t n = 0; 138*bdf82531SJerome Forissier uint32_t hash = 0; 139*bdf82531SJerome Forissier 140*bdf82531SJerome Forissier if (elf->gnu_hashtab) { 141*bdf82531SJerome Forissier struct gnu_hashtab *h = elf->gnu_hashtab; 142*bdf82531SJerome Forissier uint32_t *end = (void *)((uint8_t *)elf->gnu_hashtab + 143*bdf82531SJerome Forissier elf->gnu_hashtab_size); 144*bdf82531SJerome Forissier uint32_t *bucket = NULL; 145*bdf82531SJerome Forissier uint32_t *chain = NULL; 146*bdf82531SJerome Forissier uint32_t hashval = 0; 147*bdf82531SJerome Forissier 148*bdf82531SJerome Forissier hash = gnu_hash(name); 149*bdf82531SJerome Forissier 150*bdf82531SJerome Forissier if (elf->is_32bit) { 151*bdf82531SJerome Forissier uint32_t *bloom = (void *)(h + 1); 152*bdf82531SJerome Forissier uint32_t word = bloom[(hash / 32) % h->bloom_size]; 153*bdf82531SJerome Forissier uint32_t mask = BIT32(hash % 32) | 154*bdf82531SJerome Forissier BIT32((hash >> h->bloom_shift) % 32); 155*bdf82531SJerome Forissier 156*bdf82531SJerome Forissier if ((word & mask) != mask) 157*bdf82531SJerome Forissier return TEE_ERROR_ITEM_NOT_FOUND; 158*bdf82531SJerome Forissier bucket = bloom + h->bloom_size; 159*bdf82531SJerome Forissier } else { 160*bdf82531SJerome Forissier uint64_t *bloom = (void *)(h + 1); 161*bdf82531SJerome Forissier uint64_t word = bloom[(hash / 64) % h->bloom_size]; 162*bdf82531SJerome Forissier uint64_t mask = BIT64(hash % 64) | 163*bdf82531SJerome Forissier BIT64((hash >> h->bloom_shift) % 64); 164*bdf82531SJerome Forissier 165*bdf82531SJerome Forissier if ((word & mask) != mask) 166*bdf82531SJerome Forissier return TEE_ERROR_ITEM_NOT_FOUND; 167*bdf82531SJerome Forissier bucket = (uint32_t *)(bloom + h->bloom_size); 168*bdf82531SJerome Forissier } 169*bdf82531SJerome Forissier chain = bucket + h->nbuckets; 170*bdf82531SJerome Forissier 171*bdf82531SJerome Forissier n = bucket[hash % h->nbuckets]; 172*bdf82531SJerome Forissier if (n < h->symoffset) 173*bdf82531SJerome Forissier return TEE_ERROR_ITEM_NOT_FOUND; 174*bdf82531SJerome Forissier 175*bdf82531SJerome Forissier hash |= 1; 176*bdf82531SJerome Forissier do { 177*bdf82531SJerome Forissier size_t idx = n - h->symoffset; 178*bdf82531SJerome Forissier 179*bdf82531SJerome Forissier if (chain + idx > end) 180*bdf82531SJerome Forissier return TEE_ERROR_ITEM_NOT_FOUND; 181*bdf82531SJerome Forissier 182*bdf82531SJerome Forissier hashval = chain[idx]; 183*bdf82531SJerome Forissier 184*bdf82531SJerome Forissier if ((hashval | 1) == hash && 185*bdf82531SJerome Forissier check_found_sym(elf, name, val, weak_ok, n)) 186*bdf82531SJerome Forissier return TEE_SUCCESS; 187*bdf82531SJerome Forissier 188*bdf82531SJerome Forissier n++; 189*bdf82531SJerome Forissier } while (!(hashval & 1)); 190*bdf82531SJerome 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 201*bdf82531SJerome Forissier hash = elf_hash(name); 2027509ff7cSJens Wiklander 2039f392760SJerome Forissier for (n = bucket[hash % nbuckets]; n; n = chain[n]) { 204*bdf82531SJerome Forissier if (n >= nchains) 205*bdf82531SJerome Forissier err(TEE_ERROR_BAD_FORMAT, "Index out of range"); 206*bdf82531SJerome 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 */ 228*bdf82531SJerome Forissier if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) 229c88ba125SJerome Forissier goto success; 230cf830b2bSJerome Forissier /* Search weak symbols */ 231*bdf82531SJerome 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) { 236*bdf82531SJerome Forissier if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) 237c88ba125SJerome Forissier goto success; 238*bdf82531SJerome 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); 285c44d734bSJerome Forissier else 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 4817509ff7cSJens Wiklander #ifdef ARM64 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 5217bc927faSJerome Forissier static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab, 5227bc927faSJerome Forissier size_t num_syms, const char *str_tab, 5237bc927faSJerome Forissier size_t str_tab_size, Elf64_Rela *rela, 5247bc927faSJerome Forissier Elf64_Addr *where, struct ta_elf *elf) 525fe684948SJerome Forissier { 526fe684948SJerome Forissier struct ta_elf *mod = NULL; 527c44d734bSJerome Forissier bool weak_undef = false; 528fe684948SJerome Forissier const char *name = NULL; 5297bc927faSJerome Forissier size_t sym_idx = 0; 530fe684948SJerome Forissier vaddr_t symval = 0; 531fe684948SJerome Forissier 5327bc927faSJerome Forissier sym_idx = ELF64_R_SYM(rela->r_info); 5337bc927faSJerome Forissier if (sym_idx) { 5347bc927faSJerome Forissier e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, 535c44d734bSJerome Forissier &name, &weak_undef); 536c44d734bSJerome Forissier resolve_sym(name, &symval, &mod, !weak_undef); 5377bc927faSJerome Forissier } else { 5387bc927faSJerome Forissier mod = elf; 5397bc927faSJerome Forissier } 540fe684948SJerome Forissier *where = symval + mod->tls_tcb_offs + rela->r_addend; 541fe684948SJerome Forissier } 542fe684948SJerome Forissier 5437bc927faSJerome Forissier struct tlsdesc { 5447bc927faSJerome Forissier long (*resolver)(struct tlsdesc *td); 5457bc927faSJerome Forissier long value; 5467bc927faSJerome Forissier }; 5477bc927faSJerome Forissier 5487bc927faSJerome Forissier /* Helper function written in assembly due to the calling convention */ 5497bc927faSJerome Forissier long tlsdesc_resolve(struct tlsdesc *td); 5507bc927faSJerome Forissier 5517bc927faSJerome Forissier static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms, 5527bc927faSJerome Forissier const char *str_tab, size_t str_tab_size, 5537bc927faSJerome Forissier Elf64_Rela *rela, Elf64_Addr *where, 5547bc927faSJerome Forissier struct ta_elf *elf) 5557bc927faSJerome Forissier { 5567bc927faSJerome Forissier /* 5577bc927faSJerome Forissier * @where points to a pair of 64-bit words in the GOT or PLT which is 5587bc927faSJerome Forissier * mapped to a struct tlsdesc: 5597bc927faSJerome Forissier * 5607bc927faSJerome Forissier * - resolver() must return the offset of the thread-local variable 5617bc927faSJerome Forissier * relative to TPIDR_EL0. 5627bc927faSJerome Forissier * - value is implementation-dependent. The TLS_TPREL handling code is 5637bc927faSJerome Forissier * re-used to get the desired offset so that tlsdesc_resolve() just 5647bc927faSJerome Forissier * needs to return this value. 5657bc927faSJerome Forissier * 5667bc927faSJerome Forissier * Both the TA and ldelf are AArch64 so it is OK to point to a function 5677bc927faSJerome Forissier * in ldelf. 5687bc927faSJerome Forissier */ 5697bc927faSJerome Forissier *where = (Elf64_Addr)tlsdesc_resolve; 5707bc927faSJerome Forissier e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size, 5717bc927faSJerome Forissier rela, where + 1, elf); 5727bc927faSJerome Forissier } 5737bc927faSJerome Forissier 5747509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) 5757509ff7cSJens Wiklander { 5767509ff7cSJens Wiklander Elf64_Shdr *shdr = elf->shdr; 5777509ff7cSJens Wiklander Elf64_Rela *rela = NULL; 5787509ff7cSJens Wiklander Elf64_Rela *rela_end = NULL; 5797509ff7cSJens Wiklander size_t sym_tab_idx = 0; 5807509ff7cSJens Wiklander Elf64_Sym *sym_tab = NULL; 5817509ff7cSJens Wiklander size_t num_syms = 0; 5827509ff7cSJens Wiklander size_t sh_end = 0; 5837509ff7cSJens Wiklander const char *str_tab = NULL; 5847509ff7cSJens Wiklander size_t str_tab_size = 0; 5857509ff7cSJens Wiklander 5867509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_type == SHT_RELA); 5877509ff7cSJens Wiklander 5887509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); 5897509ff7cSJens Wiklander 5907509ff7cSJens Wiklander sym_tab_idx = shdr[rel_sidx].sh_link; 5917509ff7cSJens Wiklander if (sym_tab_idx) { 5927509ff7cSJens Wiklander size_t str_tab_idx = 0; 5937509ff7cSJens Wiklander 594447354c6SJens Wiklander if (sym_tab_idx >= elf->e_shnum) 595dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); 59655e64090SJens Wiklander sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); 5977509ff7cSJens Wiklander 5987509ff7cSJens Wiklander assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); 5997509ff7cSJens Wiklander 6007509ff7cSJens Wiklander /* Check the address is inside TA memory */ 6017509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 6027509ff7cSJens Wiklander shdr[sym_tab_idx].sh_size, &sh_end)) 603e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 604447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 605dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); 6067509ff7cSJens Wiklander 6077509ff7cSJens Wiklander sym_tab = (Elf64_Sym *)(elf->load_addr + 6087509ff7cSJens Wiklander shdr[sym_tab_idx].sh_addr); 6097509ff7cSJens Wiklander 6107509ff7cSJens Wiklander num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); 6117509ff7cSJens Wiklander 6127509ff7cSJens Wiklander str_tab_idx = shdr[sym_tab_idx].sh_link; 6137509ff7cSJens Wiklander if (str_tab_idx) { 61455e64090SJens Wiklander if (str_tab_idx >= elf->e_shnum) 615e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 616dcf64f87SJens Wiklander "STRTAB index out of range"); 61755e64090SJens Wiklander str_tab_idx = confine_array_index(str_tab_idx, 61855e64090SJens Wiklander elf->e_shnum); 61955e64090SJens Wiklander 6207509ff7cSJens Wiklander /* Check the address is inside ELF memory */ 6217509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 6227509ff7cSJens Wiklander shdr[str_tab_idx].sh_size, &sh_end)) 623e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 624447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 625e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 626dcf64f87SJens Wiklander "STRTAB out of range"); 6277509ff7cSJens Wiklander 6287509ff7cSJens Wiklander str_tab = (const char *)(elf->load_addr + 6297509ff7cSJens Wiklander shdr[str_tab_idx].sh_addr); 6307509ff7cSJens Wiklander str_tab_size = shdr[str_tab_idx].sh_size; 6317509ff7cSJens Wiklander } 6327509ff7cSJens Wiklander } 6337509ff7cSJens Wiklander 6347509ff7cSJens Wiklander /* Check the address is inside TA memory */ 635447354c6SJens Wiklander if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, 636447354c6SJens Wiklander shdr[rel_sidx].sh_size, &sh_end)) 637e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 638447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 639dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); 6407509ff7cSJens Wiklander rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); 6417509ff7cSJens Wiklander 6427509ff7cSJens Wiklander rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); 6437509ff7cSJens Wiklander for (; rela < rela_end; rela++) { 6447509ff7cSJens Wiklander Elf64_Addr *where = NULL; 6457509ff7cSJens Wiklander size_t sym_idx = 0; 6467509ff7cSJens Wiklander 6477509ff7cSJens Wiklander /* Check the address is inside TA memory */ 648447354c6SJens Wiklander if (rela->r_offset >= (elf->max_addr - elf->load_addr)) 649e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 650447354c6SJens Wiklander "Relocation offset out of range"); 6517509ff7cSJens Wiklander 6527509ff7cSJens Wiklander where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); 6537509ff7cSJens Wiklander 6547509ff7cSJens Wiklander switch (ELF64_R_TYPE(rela->r_info)) { 6557a4dc765SEtienne Carriere case R_AARCH64_NONE: 6567a4dc765SEtienne Carriere /* 6577a4dc765SEtienne Carriere * One would expect linker prevents such useless entry 6587a4dc765SEtienne Carriere * in the relocation table. We still handle this type 6597a4dc765SEtienne Carriere * here in case such entries exist. 6607a4dc765SEtienne Carriere */ 6617a4dc765SEtienne Carriere break; 6627509ff7cSJens Wiklander case R_AARCH64_ABS64: 6637509ff7cSJens Wiklander sym_idx = ELF64_R_SYM(rela->r_info); 664447354c6SJens Wiklander if (sym_idx >= num_syms) 665e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 666447354c6SJens Wiklander "Symbol index out of range"); 66755e64090SJens Wiklander sym_idx = confine_array_index(sym_idx, num_syms); 6687509ff7cSJens Wiklander if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 6697509ff7cSJens Wiklander /* Symbol is external */ 6707509ff7cSJens Wiklander e64_process_dyn_rela(sym_tab, num_syms, str_tab, 6717509ff7cSJens Wiklander str_tab_size, rela, where); 6727509ff7cSJens Wiklander } else { 6737509ff7cSJens Wiklander *where = rela->r_addend + elf->load_addr + 6747509ff7cSJens Wiklander sym_tab[sym_idx].st_value; 6757509ff7cSJens Wiklander } 6767509ff7cSJens Wiklander break; 6777509ff7cSJens Wiklander case R_AARCH64_RELATIVE: 6787509ff7cSJens Wiklander *where = rela->r_addend + elf->load_addr; 6797509ff7cSJens Wiklander break; 6807509ff7cSJens Wiklander case R_AARCH64_GLOB_DAT: 6817509ff7cSJens Wiklander case R_AARCH64_JUMP_SLOT: 6827509ff7cSJens Wiklander e64_process_dyn_rela(sym_tab, num_syms, str_tab, 6837509ff7cSJens Wiklander str_tab_size, rela, where); 6847509ff7cSJens Wiklander break; 685fe684948SJerome Forissier case R_AARCH64_TLS_TPREL: 6867bc927faSJerome Forissier e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, 6877bc927faSJerome Forissier str_tab_size, rela, where, 6887bc927faSJerome Forissier elf); 6897bc927faSJerome Forissier break; 6907bc927faSJerome Forissier case R_AARCH64_TLSDESC: 6917bc927faSJerome Forissier e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab, 6927bc927faSJerome Forissier str_tab_size, rela, where, 6937bc927faSJerome Forissier elf); 694fe684948SJerome Forissier break; 6957509ff7cSJens Wiklander default: 6967509ff7cSJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", 6977509ff7cSJens Wiklander ELF64_R_TYPE(rela->r_info)); 6987509ff7cSJens Wiklander } 6997509ff7cSJens Wiklander } 7007509ff7cSJens Wiklander } 7017509ff7cSJens Wiklander #else /*ARM64*/ 7025548a710SJerome Forissier static void __noreturn e64_relocate(struct ta_elf *elf __unused, 7037509ff7cSJens Wiklander unsigned int rel_sidx __unused) 7047509ff7cSJens Wiklander { 7057509ff7cSJens Wiklander err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); 7067509ff7cSJens Wiklander } 7077509ff7cSJens Wiklander #endif /*ARM64*/ 7087509ff7cSJens Wiklander 7097509ff7cSJens Wiklander void ta_elf_relocate(struct ta_elf *elf) 7107509ff7cSJens Wiklander { 7117509ff7cSJens Wiklander size_t n = 0; 7127509ff7cSJens Wiklander 7137509ff7cSJens Wiklander if (elf->is_32bit) { 7147509ff7cSJens Wiklander Elf32_Shdr *shdr = elf->shdr; 7157509ff7cSJens Wiklander 7167509ff7cSJens Wiklander for (n = 0; n < elf->e_shnum; n++) 7177509ff7cSJens Wiklander if (shdr[n].sh_type == SHT_REL) 7187509ff7cSJens Wiklander e32_relocate(elf, n); 7197509ff7cSJens Wiklander } else { 7207509ff7cSJens Wiklander Elf64_Shdr *shdr = elf->shdr; 7217509ff7cSJens Wiklander 7227509ff7cSJens Wiklander for (n = 0; n < elf->e_shnum; n++) 7237509ff7cSJens Wiklander if (shdr[n].sh_type == SHT_RELA) 7247509ff7cSJens Wiklander e64_relocate(elf, n); 7257509ff7cSJens Wiklander 7267509ff7cSJens Wiklander } 7277509ff7cSJens Wiklander } 728