xref: /haiku/src/system/runtime_loader/arch/x86/arch_relocate.cpp (revision c302a243e15e640fae0f689e32cdf0c18749afee)
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
relocate_rel(image_t * rootImage,image_t * image,Elf32_Rel * rel,int rel_len,SymbolLookupCache * cache)21 relocate_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 
110 status_t
arch_relocate_image(image_t * rootImage,image_t * image,SymbolLookupCache * cache)111 arch_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