xref: /haiku/src/system/runtime_loader/arch/riscv64/arch_relocate.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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