xref: /haiku/src/system/kernel/arch/arm64/arch_elf.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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 + image->text_region.size)
33 		|| (address >= image->data_region.start
34 			&& address < image->data_region.start + image->data_region.size);
35 }
36 #endif	// !_BOOT_MODE
37 
38 
39 #ifdef _BOOT_MODE
40 status_t
41 boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel,
42 	int relLength)
43 #else
44 int
45 arch_elf_relocate_rel(struct elf_image_info *image,
46 	struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength)
47 #endif
48 {
49 	dprintf("arch_elf_relocate_rel: not supported on arm64\n");
50 	return B_ERROR;
51 }
52 
53 
54 #ifdef _BOOT_MODE
55 status_t
56 boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel,
57 	int relLength)
58 #else
59 int
60 arch_elf_relocate_rela(struct elf_image_info *image,
61 	struct elf_image_info *resolveImage, Elf64_Rela *rel, int relLength)
62 #endif
63 {
64 	for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) {
65 		int type = ELF64_R_TYPE(rel[i].r_info);
66 		int symIndex = ELF64_R_SYM(rel[i].r_info);
67 		Elf64_Addr symAddr = 0;
68 
69 		// Resolve the symbol, if any.
70 		if (symIndex != 0) {
71 			Elf64_Sym* symbol = SYMBOL(image, symIndex);
72 
73 			status_t status;
74 #ifdef _BOOT_MODE
75 			status = boot_elf_resolve_symbol(image, symbol, &symAddr);
76 #else
77 			status = elf_resolve_symbol(image, symbol, resolveImage, &symAddr);
78 #endif
79 			if (status < B_OK)
80 				return status;
81 		}
82 
83 		// Address of the relocation.
84 		Elf64_Addr relocAddr = image->text_region.delta + rel[i].r_offset;
85 
86 		// Calculate the relocation value.
87 		Elf64_Addr relocValue;
88 		switch (type) {
89 			case R_AARCH64_NONE:
90 				continue;
91 			case R_AARCH64_ABS64:
92 				relocValue = symAddr + rel[i].r_addend;
93 				break;
94 			case R_AARCH64_ABS32:
95 			case R_AARCH64_ABS16:
96 			case R_AARCH64_PREL64:
97 			case R_AARCH64_PREL32:
98 			case R_AARCH64_PREL16:
99 			case R_AARCH64_TSTBR14:
100 			case R_AARCH64_CONDBR19:
101 			case R_AARCH64_JUMP26:
102 			case R_AARCH64_CALL26:
103 			case R_AARCH64_COPY:
104 				dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n",
105 					type);
106 				return B_BAD_DATA;
107 			case R_AARCH64_GLOB_DAT:
108 			case R_AARCH64_JUMP_SLOT:
109 				relocValue = symAddr + rel[i].r_addend;
110 				break;
111 			case R_AARCH64_RELATIVE:
112 				relocValue = image->text_region.delta + rel[i].r_addend;
113 				break;
114 			case R_AARCH64_TLS_DTPREL64:
115 			case R_AARCH64_TLS_DTPMOD64:
116 			case R_AARCH64_TLS_TPREL64:
117 			case R_AARCH64_TLSDESC:
118 			case R_AARCH64_IRELATIVE:
119 			default:
120 				dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n",
121 					type);
122 				return B_BAD_DATA;
123 		}
124 
125 #ifdef _BOOT_MODE
126 		boot_elf64_set_relocation(relocAddr, relocValue);
127 #else
128 		if (!is_in_image(image, relocAddr)) {
129 			dprintf("arch_elf_relocate_rela: invalid offset %#lx\n",
130 				rel[i].r_offset);
131 			return B_BAD_ADDRESS;
132 		}
133 		*(Elf64_Addr *)relocAddr = relocValue;
134 #endif
135 	}
136 
137 	return B_OK;
138 }
139