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
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
156static bool
157is_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
168status_t
169boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, Elf32_Rel *rel,
170	int relLength)
171#else
172int
173arch_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
271static inline void
272write_32(addr_t P, Elf32_Word value)
273{
274	*(Elf32_Word*)P = value;
275}
276
277
278static inline void
279write_16(addr_t P, Elf32_Word value)
280{
281	// bits 16:29
282	*(Elf32_Half*)P = (Elf32_Half)value;
283}
284
285
286static inline bool
287write_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
297static inline bool
298write_8(addr_t P, Elf32_Word value)
299{
300	// bits 7:0
301	*(uint8 *)P = (uint8)value;
302	return true;
303}
304
305
306static inline bool
307write_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
318status_t
319boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image,
320	Elf32_Rela *rel, int rel_len)
321#else
322int
323arch_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