1/*
2 * Copyright 2003-2006, Axel D��rfler, axeld@pinc-software.de
3 * Distributed under the terms of the MIT License.
4 *
5 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
6 * Copyright 2002, Manuel J. Petit. All rights reserved.
7 * Distributed under the terms of the NewOS License.
8 */
9
10
11#include "runtime_loader_private.h"
12
13#include <runtime_loader.h>
14
15#include <string.h>
16#include <stdio.h>
17#include <stdlib.h>
18
19
20static int
21relocate_rel(image_t *rootImage, image_t *image, Elf32_Rel *rel, int rel_len,
22	SymbolLookupCache* cache)
23{
24	int i;
25	addr_t S;
26	addr_t final_val;
27
28# define P	((addr_t *)(image->regions[0].delta + rel[i].r_offset))
29# define A	(*(P))
30# define B	(image->regions[0].delta)
31
32	for (i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) {
33		unsigned type = ELF32_R_TYPE(rel[i].r_info);
34		unsigned symbolIndex = ELF32_R_SYM(rel[i].r_info);
35
36		image_t* symbolImage = NULL;
37		if (symbolIndex != 0) {
38			Elf32_Sym* sym = SYMBOL(image, symbolIndex);
39			status_t status = resolve_symbol(rootImage, image, sym, cache, &S,
40					&symbolImage);
41			if (status < B_OK) {
42				TRACE(("resolve symbol \"%s\" returned: %ld\n",
43					SYMNAME(image, sym), status));
44				printf("resolve symbol \"%s\" returned: %ld\n",
45					SYMNAME(image, sym), status);
46				return status;
47			}
48		}
49
50		switch (type) {
51			case R_386_NONE:
52				continue;
53			case R_386_32:
54				final_val = S + A;
55				break;
56			case R_386_PC32:
57				final_val = S + A - (addr_t)P;
58				break;
59#if 0
60			case R_386_GOT32:
61				final_val = G + A;
62				break;
63			case R_386_PLT32:
64				final_val = L + A - (addr_t)P;
65				break;
66#endif
67			case R_386_COPY:
68				/* what ? */
69				continue;
70			case R_386_GLOB_DAT:
71				final_val = S;
72				break;
73			case R_386_JMP_SLOT:
74				final_val = S;
75				break;
76			case R_386_RELATIVE:
77				final_val = B + A;
78				break;
79#if 0
80			case R_386_GOTOFF:
81				final_val = S + A - GOT;
82				break;
83			case R_386_GOTPC:
84				final_val = GOT + A - P;
85				break;
86#endif
87			case R_386_TLS_DTPMOD32:
88				final_val = symbolImage == NULL
89							? image->dso_tls_id : symbolImage->dso_tls_id;
90				break;
91			case R_386_TLS_DTPOFF32:
92				final_val = S;
93				break;
94			default:
95				TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)));
96				return B_NOT_ALLOWED;
97		}
98
99		*P = final_val;
100	}
101
102# undef P
103# undef A
104# undef B
105
106	return B_NO_ERROR;
107}
108
109
110status_t
111arch_relocate_image(image_t* rootImage, image_t* image,
112	SymbolLookupCache* cache)
113{
114	status_t status;
115
116	// deal with the rels first
117	if (image->rel) {
118		status = relocate_rel(rootImage, image, image->rel, image->rel_len,
119			cache);
120		if (status < B_OK)
121			return status;
122	}
123
124	if (image->pltrel) {
125		status = relocate_rel(rootImage, image, image->pltrel,
126			image->pltrel_len, cache);
127		if (status < B_OK)
128			return status;
129	}
130
131	if (image->rela) {
132		//int i;
133		TRACE(("RELA relocations not supported\n"));
134		return EOPNOTSUPP;
135
136		//for (i = 1; i * (int)sizeof(Elf32_Rela) < image->rela_len; i++) {
137		//	printf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info));
138		//}
139	}
140
141	return B_OK;
142}
143