xref: /haiku/src/system/kernel/arch/arm/arch_elf.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
1 /*
2  * Copyright 2010, Ithamar R. Adema <ithamar.adema@team-embedded.nl>
3  * All rights reserved. Distributed under the terms of the MIT License.
4  *
5  * Copyright 2009, Johannes Wischert, johanneswi@gmail.com.
6  * All rights reserved. Distributed under the terms of the MIT License.
7  *
8  * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
9  * All rights reserved. Distributed under the terms of the MIT License.
10  *
11  * Copyright 2002, Travis Geiselbrecht. All rights reserved.
12  * Distributed under the terms of the NewOS License.
13  */
14 
15 #ifdef _BOOT_MODE
16 #include <boot/arch.h>
17 #endif
18 
19 #include <KernelExport.h>
20 
21 #include <elf_priv.h>
22 #include <arch/elf.h>
23 
24 
25 //#define TRACE_ARCH_ELF
26 #ifdef TRACE_ARCH_ELF
27 #	define TRACE(x) dprintf x
28 #	define CHATTY 1
29 #else
30 #	define TRACE(x) ;
31 #	define CHATTY 0
32 #endif
33 
34 
35 #ifdef TRACE_ARCH_ELF
36 static const char *kRelocations[] = {
37 	"R_ARM_NONE",		//0	Static	Miscellaneous
38 	"R_ARM_PC24",		//1	Deprecated	ARM	((S + A) | T) ? P
39 	"R_ARM_ABS32",		//2	Static	Data	(S + A) | T
40 	"R_ARM_REL32",		//3	Static	Data	((S + A) | T) ? P
41 	"R_ARM_LDR_PC_G0",	//4	Static	ARM	S + A ? P
42 	"R_ARM_ABS16",		//5	Static	Data	S + A
43 	"R_ARM_ABS12",		//6	Static	ARM	S + A
44 	"R_ARM_THM_ABS5",	//7	Static	Thumb16	S + A
45 	"R_ARM_ABS8",		//8	Static	Data	S + A
46 	"R_ARM_SBREL32",	//9	Static	Data	((S + A) | T) ? B(S)
47 	"R_ARM_THM_CALL",	//10	Static	Thumb32	((S + A) | T) ? P
48 	"R_ARM_THM_PC8",	//11	Static	Thumb16	S + A ? Pa
49 	"R_ARM_BREL_ADJ",	//12	Dynamic	Data	?B(S) + A
50 	"R_ARM_TLS_DESC",	//13	Dynamic	Data
51 	"R_ARM_THM_SWI8",	//14	Obsolete
52 	"R_ARM_XPC25",		//15	Obsolete
53 	"R_ARM_THM_XPC22",	//16	Obsolete	Encodings reserved for future
54 		// Dynamic relocations
55 	"R_ARM_TLS_DTPMOD32",	//17	Dynamic	Data	Module[S]
56 	"R_ARM_TLS_DTPOFF32",	//18	Dynamic	Data	S + A ? TLS
57 	"R_ARM_TLS_TPOFF32",	//19	Dynamic	Data	S + A ? tp
58 	"R_ARM_COPY",		//20	Dynamic	Miscellaneous
59 	"R_ARM_GLOB_DAT",	//21	Dynamic	Data	(S + A) | T
60 	"R_ARM_JUMP_SLOT",	//22	Dynamic	Data	(S + A) | T
61 	"R_ARM_RELATIVE",	//23	Dynamic	Data	B(S) + A [Note: see Table 4-16]
62 	"R_ARM_GOTOFF32",	//24	Static	Data	((S + A) | T) ? GOT_ORG
63 	"R_ARM_BASE_PREL",	//25	Static	Data	B(S) + A ? P
64 	"R_ARM_GOT_BREL",	//26	Static	Data	GOT(S) + A ? GOT_ORG
65 	"R_ARM_PLT32",		//27	Deprecated	ARM	((S + A) | T) ? P
66 	"R_ARM_CALL",		//28	Static	ARM	((S + A) | T) ? P
67 	"R_ARM_JUMP24",		//29	Static	ARM	((S + A) | T) ? P
68 	"R_ARM_THM_JUMP24",	//30	Static	Thumb32	((S + A) | T) ? P
69 	"R_ARM_BASE_ABS",	//31	Static	Data	B(S) + A
70 	"R_ARM_ALU_PCREL_7_0",	//32	Obsolete
71 	"R_ARM_ALU_PCREL_15_8",	//33	Obsolete
72 	"R_ARM_ALU_PCREL_23_15",	//34	Obsolete	Note ? Legacy (ARM ELF B02)
73 		// names have been retained for these obsolete relocations.
74 	"R_ARM_LDR_SBREL_11_0_NC",	//35	Deprecated	ARM	S + A ? B(S)
75 	"R_ARM_ALU_SBREL_19_12_NC",	//36	Deprecated	ARM	S + A ? B(S)
76 	"R_ARM_ALU_SBREL_27_20_CK",	//37	Deprecated	ARM	S + A ? B(S)
77 	"R_ARM_TARGET1",	//38	Static	Miscellaneous	(S + A) | T or ((S + A) | T) ? P
78 	"R_ARM_SBREL31",	//39	Deprecated	Data	((S + A) | T) ? B(S)
79 	"R_ARM_V4BX",		//40	Static	Miscellaneous
80 	"R_ARM_TARGET2",	//41	Static	Miscellaneous
81 	"R_ARM_PREL31",		//42	Static	Data	((S + A) | T) ? P
82 	"R_ARM_MOVW_ABS_NC",	//43	Static	ARM	(S + A) | T
83 	"R_ARM_MOVT_ABS",	//44	Static	ARM	S + A
84 	"R_ARM_MOVW_PREL_NC",	//45	Static	ARM	((S + A) | T) ? P
85 	"R_ARM_MOVT_PREL",	//46	Static	ARM	S + A ? P
86 	"R_ARM_THM_MOVW_ABS_NC",	//47	Static	Thumb32	(S + A) | T
87 	"R_ARM_THM_MOVT_ABS",	//48	Static	Thumb32	S + A
88 	"R_ARM_THM_MOVW_PREL_NC",	//49	Static	Thumb32	((S + A) | T) ? P
89 	"R_ARM_THM_MOVT_PREL",	//50	Static	Thumb32	S + A ? P
90 	"R_ARM_THM_JUMP19",	//51	Static	Thumb32	((S + A) | T) ? P
91 	"R_ARM_THM_JUMP6",	//52	Static	Thumb16	S + A ? P
92 	"R_ARM_THM_ALU_PREL_11_0",	//53	Static	Thumb32	((S + A) | T) ? Pa
93 	"R_ARM_THM_PC12",	//54	Static	Thumb32	S + A ? Pa
94 	"R_ARM_ABS32_NOI",	//55	Static	Data	S + A
95 	"R_ARM_REL32_NOI",	//56	Static	Data	S + A ? P
96 	"R_ARM_ALU_PC_G0_NC",	//57	Static	ARM	((S + A) | T) ? P
97 	"R_ARM_ALU_PC_G0",	//58	Static	ARM	((S + A) | T) ? P
98 	"R_ARM_ALU_PC_G1_NC",	//59	Static	ARM	((S + A) | T) ? P
99 	"R_ARM_ALU_PC_G1",	//60	Static	ARM	((S + A) | T) ? P
100 	"R_ARM_ALU_PC_G2",	//61	Static	ARM	((S + A) | T) ? P
101 	"R_ARM_LDR_PC_G1",	//62	Static	ARM	S + A ? P
102 	"R_ARM_LDR_PC_G2",	//63	Static	ARM	S + A ? P
103 	"R_ARM_LDRS_PC_G0",	//64	Static	ARM	S + A ? P
104 	"R_ARM_LDRS_PC_G1",	//65	Static	ARM	S + A ? P
105 	"R_ARM_LDRS_PC_G2",	//66	Static	ARM	S + A ? P
106 	"R_ARM_LDC_PC_G0",	//67	Static	ARM	S + A ? P
107 	"R_ARM_LDC_PC_G1",	//68	Static	ARM	S + A ? P
108 	"R_ARM_LDC_PC_G2",	//69	Static	ARM	S + A ? P
109 	"R_ARM_ALU_SB_G0_NC",	//70	Static	ARM	((S + A) | T) ? B(S)
110 	"R_ARM_ALU_SB_G0",	//71	Static	ARM	((S + A) | T) ? B(S)
111 	"R_ARM_ALU_SB_G1_NC",	//72	Static	ARM	((S + A) | T) ? B(S)
112 	"R_ARM_ALU_SB_G1",	//73	Static	ARM	((S + A) | T) ? B(S)
113 	"R_ARM_ALU_SB_G2",	//74	Static	ARM	((S + A) | T) ? B(S)
114 	"R_ARM_LDR_SB_G0",	//75	Static	ARM	S + A ? B(S)
115 	"R_ARM_LDR_SB_G1",	//76	Static	ARM	S + A ? B(S)
116 	"R_ARM_LDR_SB_G2",	//77	Static	ARM	S + A ? B(S)
117 	"R_ARM_LDRS_SB_G0",	//78	Static	ARM	S + A ? B(S)
118 	"R_ARM_LDRS_SB_G1",	//79	Static	ARM	S + A ? B(S)
119 	"R_ARM_LDRS_SB_G2",	//80	Static	ARM	S + A ? B(S)
120 	"R_ARM_LDC_SB_G0",	//81	Static	ARM	S + A ? B(S)
121 	"R_ARM_LDC_SB_G1",	//82	Static	ARM	S + A ? B(S)
122 	"R_ARM_LDC_SB_G2",	//83	Static	ARM	S + A ? B(S)
123 	"R_ARM_MOVW_BREL_NC",	//84	Static	ARM	((S + A) | T) ? B(S)
124 	"R_ARM_MOVT_BREL",	//85	Static	ARM	S + A ? B(S)
125 	"R_ARM_MOVW_BREL",	//86	Static	ARM	((S + A) | T) ? B(S)
126 	"R_ARM_THM_MOVW_BREL_NC",	//87	Static	Thumb32	((S + A) | T) ? B(S)
127 	"R_ARM_THM_MOVT_BREL",	//88	Static	Thumb32	S + A ? B(S)
128 	"R_ARM_THM_MOVW_BREL",	//89	Static	Thumb32	((S + A) | T) ? B(S)
129 	"R_ARM_TLS_GOTDESC",	//90	Static	Data
130 	"R_ARM_TLS_CALL",	//91	Static	ARM
131 	"R_ARM_TLS_DESCSEQ",	//92	Static	ARM	TLS relaxation
132 	"R_ARM_THM_TLS_CALL",	//93	Static	Thumb32
133 	"R_ARM_PLT32_ABS",	//94	Static	Data	PLT(S) + A
134 	"R_ARM_GOT_ABS",	//95	Static	Data	GOT(S) + A
135 	"R_ARM_GOT_PREL",	//96	Static	Data	GOT(S) + A ? P
136 	"R_ARM_GOT_BREL12",	//97	Static	ARM	GOT(S) + A ? GOT_ORG
137 	"R_ARM_GOTOFF12",	//98	Static	ARM	S + A ? GOT_ORG
138 	"R_ARM_GOTRELAX",	//99	Static	Miscellaneous
139 	"R_ARM_GNU_VTENTRY",	//100	Deprecated	Data	???
140 	"R_ARM_GNU_VTINHERIT",	//101	Deprecated	Data	???
141 	"R_ARM_THM_JUMP11",	//102	Static	Thumb16	S + A ? P
142 	"R_ARM_THM_JUMP8",	//103	Static	Thumb16	S + A ? P
143 	"R_ARM_TLS_GD32",	//104	Static	Data	GOT(S) + A ? P
144 	"R_ARM_TLS_LDM32",	//105	Static	Data	GOT(S) + A ? P
145 	"R_ARM_TLS_LDO32",	//106	Static	Data	S + A ? TLS
146 	"R_ARM_TLS_IE32",	//107	Static	Data	GOT(S) + A ? P
147 	"R_ARM_TLS_LE32",	//108	Static	Data	S + A ? tp
148 	"R_ARM_TLS_LDO12",	//109	Static	ARM	S + A ? TLS
149 	"R_ARM_TLS_LE12",	//110	Static	ARM	S + A ? tp
150 	"R_ARM_TLS_IE12GP",	//111	Static	ARM	GOT(S) + A ? GOT_ORG
151 };
152 #endif
153 
154 
155 #ifndef _BOOT_MODE
156 static bool
157 is_in_image(struct elf_image_info *image, addr_t address)
158 {
159 	return (address >= image->text_region.start
160 			&& address < image->text_region.start + image->text_region.size)
161 		|| (address >= image->data_region.start
162 			&& address < image->data_region.start + image->data_region.size);
163 }
164 #endif	// !_BOOT_MODE
165 
166 
167 #ifdef _BOOT_MODE
168 status_t
169 boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, Elf32_Rel *rel,
170 	int relLength)
171 #else
172 int
173 arch_elf_relocate_rel(struct elf_image_info *image,
174 	struct elf_image_info *resolveImage, Elf32_Rel *rel, int relLength)
175 #endif
176 {
177 	elf_addr S;
178 	addr_t A;
179 	addr_t P;
180 	addr_t finalAddress;
181 	addr_t *resolveAddress;
182 	int i;
183 
184 	S = A = P = 0;
185 
186 	for (i = 0; i * (int)sizeof(Elf32_Rel) < relLength; i++) {
187 		TRACE(("looking at rel type %s, offset 0x%lx\n",
188 			kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset));
189 
190 		// calc S
191 		switch (ELF32_R_TYPE(rel[i].r_info)) {
192 			case R_ARM_JMP_SLOT:
193 			case R_ARM_GLOB_DAT:
194 			case R_ARM_ABS32:
195 			{
196 				Elf32_Sym *symbol;
197 				status_t status;
198 
199 				symbol = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
200 
201 #ifdef _BOOT_MODE
202 				status = boot_elf_resolve_symbol(image, symbol, &S);
203 #else
204 				status = elf_resolve_symbol(image, symbol, resolveImage, &S);
205 #endif
206 				if (status < B_OK) {
207 #ifndef _BOOT_MODE
208 					TRACE(("failed relocating %s\n", SYMNAME(image, symbol)));
209 #endif
210 //IRA					return status;
211 					return B_OK;
212 				}
213 #ifndef _BOOT_MODE
214 				TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, symbol)));
215 #endif
216 			}
217 		}
218 
219 		// calc A
220 		switch (ELF32_R_TYPE(rel[i].r_info)) {
221 			case R_ARM_ABS32:
222 			case R_ARM_RELATIVE:
223 #ifndef _BOOT_MODE
224 				A = *(addr_t *)(image->text_region.delta + rel[i].r_offset);
225 #else
226 				A = boot_elf32_get_relocation(image->text_region.delta + rel[i].r_offset);
227 #endif
228 				TRACE(("A %p\n", (void *)A));
229 				break;
230 		}
231 
232 		switch (ELF32_R_TYPE(rel[i].r_info)) {
233 			case R_ARM_NONE:
234 				continue;
235 			case R_ARM_RELATIVE:
236 				// B + A;
237 				finalAddress = image->text_region.delta + A;
238 				break;
239 			case R_ARM_JMP_SLOT:
240 			case R_ARM_GLOB_DAT:
241 				finalAddress = S;
242 				break;
243 			case R_ARM_ABS32:
244 				finalAddress = S + A;
245 				break;
246 			default:
247 				dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n",
248 					ELF32_R_TYPE(rel[i].r_info));
249 				return B_BAD_DATA;
250 		}
251 
252 		resolveAddress = (addr_t *)(image->text_region.delta + rel[i].r_offset);
253 #ifndef _BOOT_MODE
254 		if (!is_in_image(image, (addr_t)resolveAddress)) {
255 			dprintf("arch_elf_relocate_rel: invalid offset %#lx\n",
256 				rel[i].r_offset);
257 			return B_BAD_ADDRESS;
258 		}
259 		*resolveAddress = finalAddress;
260 #else
261 		boot_elf32_set_relocation((Elf32_Addr)resolveAddress, finalAddress);
262 #endif
263 		TRACE(("-> offset %#lx = %#lx\n",
264 			(image->text_region.delta + rel[i].r_offset), finalAddress));
265 	}
266 
267 	return B_NO_ERROR;
268 }
269 
270 
271 static inline void
272 write_32(addr_t P, Elf32_Word value)
273 {
274 	*(Elf32_Word*)P = value;
275 }
276 
277 
278 static inline void
279 write_16(addr_t P, Elf32_Word value)
280 {
281 	// bits 16:29
282 	*(Elf32_Half*)P = (Elf32_Half)value;
283 }
284 
285 
286 static inline bool
287 write_16_check(addr_t P, Elf32_Word value)
288 {
289 	// bits 15:0
290 	if ((value & 0xffff0000) && (~value & 0xffff8000))
291 		return false;
292 	*(Elf32_Half*)P = (Elf32_Half)value;
293 	return true;
294 }
295 
296 
297 static inline bool
298 write_8(addr_t P, Elf32_Word value)
299 {
300 	// bits 7:0
301 	*(uint8 *)P = (uint8)value;
302 	return true;
303 }
304 
305 
306 static inline bool
307 write_8_check(addr_t P, Elf32_Word value)
308 {
309 	// bits 7:0
310 	if ((value & 0xffffff00) && (~value & 0xffffff80))
311 		return false;
312 	*(uint8 *)P = (uint8)value;
313 	return true;
314 }
315 
316 
317 #ifdef _BOOT_MODE
318 status_t
319 boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image,
320 	Elf32_Rela *rel, int rel_len)
321 #else
322 int
323 arch_elf_relocate_rela(struct elf_image_info *image,
324 	struct elf_image_info *resolve_image, Elf32_Rela *rel, int rel_len)
325 #endif
326 {
327 	int i;
328 	Elf32_Sym *sym;
329 	int vlErr;
330 	elf_addr S = 0; // symbol address
331 	addr_t R = 0;   // section relative symbol address
332 
333 	addr_t G = 0;   // GOT address
334 	addr_t L = 0;   // PLT address
335 
336 	#define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
337 	#define A ((addr_t)rel[i].r_addend)
338 	#define B (image->text_region.delta)
339 	#warning ARM:define T correctly for thumb!!!
340 	#define	T 0
341 
342 	// TODO: Get the GOT address!
343 	#define REQUIRE_GOT     \
344 		if (G == 0) {   \
345 			dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
346 			return B_ERROR; \
347 		}
348 
349 	// TODO: Get the PLT address!
350 	#define REQUIRE_PLT     \
351 	if (L == 0) {   \
352 		dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
353 		return B_ERROR; \
354 	}
355 
356 	for (i = 0; i * (int)sizeof(Elf32_Rela) < rel_len; i++) {
357 		#if CHATTY
358 		dprintf("looking at rel type %d, offset 0x%lx, "
359 		"sym 0x%lx, addend 0x%lx\n", ELF32_R_TYPE(rel[i].r_info),
360 		rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
361 		#endif
362 		switch (ELF32_R_TYPE(rel[i].r_info)) {
363 		#warning ARM:ADDOTHERREL
364 			case R_ARM_GLOB_DAT:
365 				sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
366 
367 				#ifdef _BOOT_MODE
368 				vlErr = boot_elf_resolve_symbol(image, sym, &S);
369 				#else
370 				vlErr = elf_resolve_symbol(image, sym, resolve_image, &S);
371 				#endif
372 				if (vlErr < 0) {
373 					dprintf("%s(): Failed to relocate "
374 						"entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, "
375 						"addend 0x%lx\n", __FUNCTION__, i,
376 						ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset,
377 						ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
378 					return vlErr;
379 				}
380 				break;
381 		}
382 
383 		#warning ARM:ADDOTHERREL
384 		switch (ELF32_R_TYPE(rel[i].r_info)) {
385 			case R_ARM_GLOB_DAT:
386 				write_32(P, (S + A) | T);
387 				break;
388 
389 			case R_ARM_NONE:
390 				break;
391 
392 			default:
393 				dprintf("arch_elf_relocate_rela(): unhandled "
394 					"relocation type %d!\n", ELF32_R_TYPE(rel[i].r_info));
395 				return B_ERROR;
396 		}
397 	}
398 
399 	#warning ARM: FIXME!!!!!!!
400 	return B_NO_ERROR;
401 }
402