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