headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / runtime_loader / arch / x86_64 / arch_relocate.cpp
blobfda4c27c337da1e6c0c3893f31c1ac82f3764b05
1 /*
2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "runtime_loader_private.h"
9 #include <runtime_loader.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
16 static status_t
17 relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
18 size_t relLength, SymbolLookupCache* cache)
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;
26 // Resolve the symbol, if any.
27 if (symIndex != 0) {
28 Elf64_Sym* sym = SYMBOL(image, symIndex);
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;
41 // Address of the relocation.
42 Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset;
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;
73 *(Elf64_Addr *)relocAddr = relocValue;
76 return B_OK;
80 status_t
81 arch_relocate_image(image_t* rootImage, image_t* image,
82 SymbolLookupCache* cache)
84 status_t status;
86 // No REL on x86_64.
88 // Perform RELA relocations.
89 if (image->rela) {
90 status = relocate_rela(rootImage, image, image->rela, image->rela_len,
91 cache);
92 if (status != B_OK)
93 return status;
96 // PLT relocations (they are RELA on x86_64).
97 if (image->pltrel) {
98 status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel,
99 image->pltrel_len, cache);
100 if (status != B_OK)
101 return status;
104 return B_OK;