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 25 // Resolve the symbol, if any. 26 if (symIndex != 0) { 27 Elf64_Sym* sym = SYMBOL(image, symIndex); 28 29 status_t status = resolve_symbol(rootImage, image, sym, cache, 30 &symAddr); 31 if (status != B_OK) { 32 TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n", 33 SYMNAME(image, sym), status)); 34 printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n", 35 SYMNAME(image, sym), status); 36 return status; 37 } 38 } 39 40 // Address of the relocation. 41 Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset; 42 43 // Calculate the relocation value. 44 Elf64_Addr relocValue; 45 switch(type) { 46 case R_X86_64_NONE: 47 continue; 48 case R_X86_64_64: 49 case R_X86_64_GLOB_DAT: 50 case R_X86_64_JUMP_SLOT: 51 relocValue = symAddr + rel[i].r_addend; 52 break; 53 case R_X86_64_PC32: 54 relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; 55 break; 56 case R_X86_64_RELATIVE: 57 relocValue = image->regions[0].delta + rel[i].r_addend; 58 break; 59 default: 60 TRACE(("unhandled relocation type %d\n", type)); 61 return B_BAD_DATA; 62 } 63 64 *(Elf64_Addr *)relocAddr = relocValue; 65 } 66 67 return B_OK; 68 } 69 70 71 status_t 72 arch_relocate_image(image_t* rootImage, image_t* image, 73 SymbolLookupCache* cache) 74 { 75 status_t status; 76 77 // No REL on x86_64. 78 79 // Perform RELA relocations. 80 if (image->rela) { 81 status = relocate_rela(rootImage, image, image->rela, image->rela_len, 82 cache); 83 if (status != B_OK) 84 return status; 85 } 86 87 // PLT relocations (they are RELA on x86_64). 88 if (image->pltrel) { 89 status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel, 90 image->pltrel_len, cache); 91 if (status != B_OK) 92 return status; 93 } 94 95 return B_OK; 96 } 97