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
36static 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#ifdef _BOOT_MODE
154bool boot_arch_elf_arch_compat(struct elf_image_arch* hostArch,
155	struct elf_image_arch* imageArch)
156#else
157bool arch_elf_arch_compat(struct elf_image_arch* hostArch,
158	struct elf_image_arch* imageArch)
159#endif
160{
161	if (hostArch->osabi != imageArch->osabi)
162		return false;
163
164	if (hostArch->osabi_version != imageArch->osabi_version)
165		return false;
166
167	if (hostArch->word_size != imageArch->word_size)
168		return false;
169
170	if (hostArch->byte_order != imageArch->byte_order)
171		return false;
172
173	if (hostArch->machine == imageArch->machine)
174		return false;
175
176	return true;
177}
178
179
180#ifdef _BOOT_MODE
181uint32_t boot_arch_elf_score_image_arch(struct elf_image_arch *arch)
182#else
183uint32_t arch_elf_score_image_arch(struct elf_image_arch *arch)
184#endif
185{
186	if (arch->osabi != ELFOSABI_HAIKU)
187		return 0;
188
189	if (arch->osabi_version != 0)
190		return 0;
191
192	if (arch->word_size != ELF_CLASS)
193		return 0;
194
195	if (arch->byte_order != ELF_DATA)
196		return 0;
197
198	if (!ELF_MACHINE_OK(arch->machine))
199		return 0;
200}
201
202
203#ifndef _BOOT_MODE
204static bool
205is_in_image(struct elf_image_info *image, addr_t address)
206{
207	return (address >= image->text_region.start
208			&& address < image->text_region.start + image->text_region.size)
209		|| (address >= image->data_region.start
210			&& address < image->data_region.start + image->data_region.size);
211}
212#endif	// !_BOOT_MODE
213
214
215#ifdef _BOOT_MODE
216status_t
217boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image,
218	struct Elf32_Rel *rel, int relLength)
219#else
220int
221arch_elf_relocate_rel(struct elf_image_info *image,
222	struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength)
223#endif
224{
225	addr_t S;
226	addr_t A;
227	addr_t P;
228	addr_t finalAddress;
229	addr_t *resolveAddress;
230	int i;
231
232	S = A = P = 0;
233
234	for (i = 0; i * (int)sizeof(struct Elf32_Rel) < relLength; i++) {
235		TRACE(("looking at rel type %s, offset 0x%lx\n",
236			kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset));
237
238		// calc S
239		switch (ELF32_R_TYPE(rel[i].r_info)) {
240			case R_ARM_JMP_SLOT:
241			case R_ARM_GLOB_DAT:
242			case R_ARM_ABS32:
243			{
244				struct Elf32_Sym *symbol;
245				status_t status;
246
247				symbol = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
248
249#ifdef _BOOT_MODE
250				status = boot_elf_resolve_symbol(image, symbol, &S);
251#else
252				status = elf_resolve_symbol(image, symbol, resolveImage, &S);
253#endif
254				if (status < B_OK) {
255#ifndef _BOOT_MODE
256					TRACE(("failed relocating %s\n", SYMNAME(image, symbol)));
257#endif
258//IRA					return status;
259					return B_OK;
260				}
261#ifndef _BOOT_MODE
262				TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, symbol)));
263#endif
264			}
265		}
266
267		// calc A
268		switch (ELF32_R_TYPE(rel[i].r_info)) {
269			case R_ARM_ABS32:
270			case R_ARM_RELATIVE:
271				A = *(addr_t *)(image->text_region.delta + rel[i].r_offset);
272				TRACE(("A %p\n", (void *)A));
273				break;
274		}
275
276		switch (ELF32_R_TYPE(rel[i].r_info)) {
277			case R_ARM_NONE:
278				continue;
279			case R_ARM_RELATIVE:
280				// B + A;
281				finalAddress = image->text_region.delta + A;
282				break;
283			case R_ARM_JMP_SLOT:
284			case R_ARM_GLOB_DAT:
285				finalAddress = S;
286				break;
287			case R_ARM_ABS32:
288				finalAddress = S + A;
289				break;
290			default:
291				dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n",
292					ELF32_R_TYPE(rel[i].r_info));
293				return B_BAD_DATA;
294		}
295
296		resolveAddress = (addr_t *)(image->text_region.delta + rel[i].r_offset);
297#ifndef _BOOT_MODE
298		if (!is_in_image(image, (addr_t)resolveAddress)) {
299			dprintf("arch_elf_relocate_rel: invalid offset %#lx\n",
300				rel[i].r_offset);
301			return B_BAD_ADDRESS;
302		}
303#endif
304		*resolveAddress = finalAddress;
305		TRACE(("-> offset %#lx = %#lx\n",
306			(image->text_region.delta + rel[i].r_offset), finalAddress));
307	}
308
309	return B_NO_ERROR;
310}
311
312
313static inline void
314write_32(addr_t P, Elf32_Word value)
315{
316	*(Elf32_Word*)P = value;
317}
318
319
320static inline void
321write_16(addr_t P, Elf32_Word value)
322{
323	// bits 16:29
324	*(Elf32_Half*)P = (Elf32_Half)value;
325}
326
327
328static inline bool
329write_16_check(addr_t P, Elf32_Word value)
330{
331	// bits 15:0
332	if ((value & 0xffff0000) && (~value & 0xffff8000))
333		return false;
334	*(Elf32_Half*)P = (Elf32_Half)value;
335	return true;
336}
337
338
339static inline bool
340write_8(addr_t P, Elf32_Word value)
341{
342	// bits 7:0
343	*(uint8 *)P = (uint8)value;
344	return true;
345}
346
347
348static inline bool
349write_8_check(addr_t P, Elf32_Word value)
350{
351	// bits 7:0
352	if ((value & 0xffffff00) && (~value & 0xffffff80))
353		return false;
354	*(uint8 *)P = (uint8)value;
355	return true;
356}
357
358
359#ifdef _BOOT_MODE
360status_t
361boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image,
362	struct Elf32_Rela *rel, int rel_len)
363#else
364int
365arch_elf_relocate_rela(struct elf_image_info *image,
366	struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len)
367#endif
368{
369	int i;
370	struct Elf32_Sym *sym;
371	int vlErr;
372	addr_t S = 0;   // symbol address
373	addr_t R = 0;   // section relative symbol address
374
375	addr_t G = 0;   // GOT address
376	addr_t L = 0;   // PLT address
377
378	#define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
379	#define A ((addr_t)rel[i].r_addend)
380	#define B (image->text_region.delta)
381	#warning ARM:define T correctly for thumb!!!
382	#define	T 0
383
384	// TODO: Get the GOT address!
385	#define REQUIRE_GOT     \
386		if (G == 0) {   \
387			dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
388			return B_ERROR; \
389		}
390
391	// TODO: Get the PLT address!
392	#define REQUIRE_PLT     \
393	if (L == 0) {   \
394		dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
395		return B_ERROR; \
396	}
397
398	for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) {
399		#if CHATTY
400		dprintf("looking at rel type %d, offset 0x%lx, "
401		"sym 0x%lx, addend 0x%lx\n", ELF32_R_TYPE(rel[i].r_info),
402		rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
403		#endif
404		switch (ELF32_R_TYPE(rel[i].r_info)) {
405		#warning ARM:ADDOTHERREL
406			case R_ARM_GLOB_DAT:
407				sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
408
409				#ifdef _BOOT_MODE
410				vlErr = boot_elf_resolve_symbol(image, sym, &S);
411				#else
412				vlErr = elf_resolve_symbol(image, sym, resolve_image, &S);
413				#endif
414				if (vlErr < 0) {
415					dprintf("%s(): Failed to relocate "
416						"entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, "
417						"addend 0x%lx\n", __FUNCTION__, i,
418						ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset,
419						ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
420					return vlErr;
421				}
422				break;
423		}
424
425		#warning ARM:ADDOTHERREL
426		switch (ELF32_R_TYPE(rel[i].r_info)) {
427			case R_ARM_GLOB_DAT:
428				write_32(P, (S + A) | T);
429				break;
430
431			case R_ARM_NONE:
432				break;
433
434			default:
435				dprintf("arch_elf_relocate_rela(): unhandled "
436					"relocation type %d!\n", ELF32_R_TYPE(rel[i].r_info));
437				return B_ERROR;
438		}
439	}
440
441	#warning ARM: FIXME!!!!!!!
442	return B_NO_ERROR;
443}
444