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