1 /* 2 * Copyright 2012-2018, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar R. Adema <ithamar@upgrade-android.com> 7 */ 8 9 #include <string.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 13 #include "runtime_loader_private.h" 14 15 #include <runtime_loader.h> 16 17 18 static status_t 19 relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel, 20 size_t relLength, SymbolLookupCache* cache) 21 { 22 for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) { 23 int type = ELF64_R_TYPE(rel[i].r_info); 24 int symIndex = ELF64_R_SYM(rel[i].r_info); 25 Elf64_Addr symAddr = 0; 26 image_t* symbolImage = NULL; 27 28 // Resolve the symbol, if any. 29 if (symIndex != 0) { 30 Elf64_Sym* sym = SYMBOL(image, symIndex); 31 32 status_t status = resolve_symbol(rootImage, image, sym, cache, 33 &symAddr, &symbolImage); 34 if (status != B_OK) { 35 TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n", 36 SYMNAME(image, sym), status)); 37 printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n", 38 SYMNAME(image, sym), status); 39 return status; 40 } 41 } 42 43 // Address of the relocation. 44 Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset; 45 46 // Calculate the relocation value. 47 Elf64_Addr relocValue; 48 switch (type) { 49 case R_RISCV_NONE: 50 continue; 51 case R_RISCV_64: 52 case R_RISCV_JUMP_SLOT: 53 relocValue = symAddr + rel[i].r_addend; 54 break; 55 case R_RISCV_RELATIVE: 56 relocValue = image->regions[0].delta + rel[i].r_addend; 57 break; 58 case R_RISCV_TLS_DTPMOD64: 59 relocValue = symbolImage == NULL 60 ? image->dso_tls_id : symbolImage->dso_tls_id; 61 break; 62 case R_RISCV_TLS_DTPREL64: 63 relocValue = symAddr; 64 break; 65 default: 66 TRACE(("unhandled relocation type %d\n", type)); 67 return B_BAD_DATA; 68 } 69 70 *(Elf64_Addr *)relocAddr = relocValue; 71 } 72 73 return B_OK; 74 } 75 76 77 status_t 78 arch_relocate_image(image_t* rootImage, image_t* image, 79 SymbolLookupCache* cache) 80 { 81 status_t status; 82 83 // Perform RELA relocations. 84 if (image->rela) { 85 status = relocate_rela(rootImage, image, image->rela, image->rela_len, 86 cache); 87 if (status != B_OK) 88 return status; 89 } 90 91 // PLT relocations (they are RELA on riscv64). 92 if (image->pltrel) { 93 status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel, 94 image->pltrel_len, cache); 95 if (status != B_OK) 96 return status; 97 } 98 99 return B_OK; 100 } 101