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, struct Elf32_Rel *rel,
22	int rel_len, 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(struct Elf32_Rel) < rel_len; i++) {
33		unsigned type = ELF32_R_TYPE(rel[i].r_info);
34
35		switch (type) {
36			case R_386_32:
37			case R_386_PC32:
38			case R_386_GLOB_DAT:
39			case R_386_JMP_SLOT:
40			case R_386_GOTOFF:
41			{
42				struct Elf32_Sym *sym;
43				status_t status;
44				sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
45
46				status = resolve_symbol(rootImage, image, sym, cache, &S);
47				if (status < B_OK) {
48					TRACE(("resolve symbol \"%s\" returned: %ld\n",
49						SYMNAME(image, sym), status));
50					printf("resolve symbol \"%s\" returned: %ld\n",
51						SYMNAME(image, sym), status);
52					return status;
53				}
54			}
55		}
56		switch (type) {
57			case R_386_NONE:
58				continue;
59			case R_386_32:
60				final_val = S + A;
61				break;
62			case R_386_PC32:
63				final_val = S + A - (addr_t)P;
64				break;
65#if 0
66			case R_386_GOT32:
67				final_val = G + A;
68				break;
69			case R_386_PLT32:
70				final_val = L + A - (addr_t)P;
71				break;
72#endif
73			case R_386_COPY:
74				/* what ? */
75				continue;
76			case R_386_GLOB_DAT:
77				final_val = S;
78				break;
79			case R_386_JMP_SLOT:
80				final_val = S;
81				break;
82			case R_386_RELATIVE:
83				final_val = B + A;
84				break;
85#if 0
86			case R_386_GOTOFF:
87				final_val = S + A - GOT;
88				break;
89			case R_386_GOTPC:
90				final_val = GOT + A - P;
91				break;
92#endif
93			default:
94				TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)));
95				return B_NOT_ALLOWED;
96		}
97
98		*P = final_val;
99	}
100
101# undef P
102# undef A
103# undef B
104
105	return B_NO_ERROR;
106}
107
108
109status_t
110arch_relocate_image(image_t* rootImage, image_t* image,
111	SymbolLookupCache* cache)
112{
113	status_t status;
114
115	// deal with the rels first
116	if (image->rel) {
117		status = relocate_rel(rootImage, image, image->rel, image->rel_len,
118			cache);
119		if (status < B_OK)
120			return status;
121	}
122
123	if (image->pltrel) {
124		status = relocate_rel(rootImage, image, image->pltrel,
125			image->pltrel_len, cache);
126		if (status < B_OK)
127			return status;
128	}
129
130	if (image->rela) {
131		//int i;
132		TRACE(("RELA relocations not supported\n"));
133		return EOPNOTSUPP;
134
135		//for (i = 1; i * (int)sizeof(struct Elf32_Rela) < image->rela_len; i++) {
136		//	printf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info));
137		//}
138	}
139
140	return B_OK;
141}
142