xref: /haiku/src/system/runtime_loader/arch/x86/arch_relocate.cpp (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
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 static int
21 relocate_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 
109 status_t
110 arch_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