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