xref: /haiku/src/system/kernel/arch/riscv64/arch_elf.cpp (revision 4a850ca730d8282b5b924e49e09b4ba4d6db7f54)
1 /*
2  * Copyright 2004-2018 Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  * Copyright 2002, Travis Geiselbrecht. All rights reserved.
5  * Distributed under the terms of the NewOS License.
6  */
7 
8 
9 #ifdef _BOOT_MODE
10 #	include <boot/arch.h>
11 #endif
12 
13 #include <KernelExport.h>
14 
15 #include <elf_priv.h>
16 #include <arch/elf.h>
17 
18 
19 //#define TRACE_ARCH_ELF
20 #ifdef TRACE_ARCH_ELF
21 #	define TRACE(x) dprintf x
22 #else
23 #	define TRACE(x) ;
24 #endif
25 
26 
27 #ifndef _BOOT_MODE
28 static bool
29 is_in_image(struct elf_image_info *image, addr_t address)
30 {
31 	return (address >= image->text_region.start
32 			&& address < image->text_region.start
33 				+ image->text_region.size)
34 		|| (address >= image->data_region.start
35 			&& address < image->data_region.start
36 				+ image->data_region.size);
37 }
38 #endif	// !_BOOT_MODE
39 
40 
41 #ifdef _BOOT_MODE
42 status_t
43 boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel,
44 	int relLength)
45 #else
46 int
47 arch_elf_relocate_rel(struct elf_image_info *image,
48 	struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength)
49 #endif
50 {
51 	dprintf("arch_elf_relocate_rel: not supported on riscv64\n");
52 	return B_ERROR;
53 }
54 
55 
56 #ifdef _BOOT_MODE
57 status_t
58 boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel,
59 	int relLength)
60 #else
61 int
62 arch_elf_relocate_rela(struct elf_image_info *image,
63 	struct elf_image_info *resolveImage, Elf64_Rela *rel, int relLength)
64 #endif
65 {
66 	for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) {
67 		int type = ELF64_R_TYPE(rel[i].r_info);
68 		int symIndex = ELF64_R_SYM(rel[i].r_info);
69 		Elf64_Addr symAddr = 0;
70 
71 		// Resolve the symbol, if any.
72 		if (symIndex != 0) {
73 			Elf64_Sym* symbol = SYMBOL(image, symIndex);
74 
75 			status_t status;
76 #ifdef _BOOT_MODE
77 			status = boot_elf_resolve_symbol(image, symbol,
78 				&symAddr);
79 #else
80 			status = elf_resolve_symbol(image, symbol, resolveImage,
81 				&symAddr);
82 #endif
83 			if (status < B_OK)
84 				return status;
85 		}
86 
87 		// Address of the relocation.
88 		Elf64_Addr relocAddr = image->text_region.delta
89 			+ rel[i].r_offset;
90 
91 		// Calculate the relocation value.
92 		Elf64_Addr relocValue;
93 		switch (type) {
94 			case R_RISCV_NONE:
95 				continue;
96 			case R_RISCV_64:
97 			case R_RISCV_JUMP_SLOT:
98 				relocValue = symAddr + rel[i].r_addend;
99 				break;
100 			case R_RISCV_RELATIVE:
101 				relocValue = image->text_region.delta
102 					+ rel[i].r_addend;
103 				break;
104 			default:
105 				dprintf("arch_elf_relocate_rela: unhandled"
106 					"relocation type %d\n", type);
107 				return B_BAD_DATA;
108 		}
109 #ifdef _BOOT_MODE
110 		boot_elf64_set_relocation(relocAddr, relocValue);
111 #else
112 		if (!is_in_image(image, relocAddr)) {
113 			dprintf("arch_elf_relocate_rela: invalid offset %#lx\n",
114 				rel[i].r_offset);
115 			return B_BAD_ADDRESS;
116 		}
117 		*(Elf64_Addr *)relocAddr = relocValue;
118 #endif
119 	}
120 
121 	return B_OK;
122 }
123