xref: /haiku/src/system/runtime_loader/arch/arm/arch_relocate.cpp (revision a127b88ecbfab58f64944c98aa47722a18e363b2)
1 /*
2  * Copyright 2012-2022, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ithamar R. Adema <ithamar@upgrade-android.com>
7  */
8 
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 #include "runtime_loader_private.h"
14 
15 #include <runtime_loader.h>
16 
17 //#define TRACE_RLD
18 #ifdef TRACE_RLD
19 #	define TRACE(x...) dprintf(x)
20 #else
21 #	define TRACE(x...) ;
22 #endif
23 
24 
25 static int
26 relocate_rel(image_t *rootImage, image_t *image, Elf32_Rel *rel, int rel_len,
27 	SymbolLookupCache* cache)
28 {
29 # define P	((addr_t *)(image->regions[0].delta + rel[i].r_offset))
30 # define A	(*(P))
31 # define B	(image->regions[0].delta)
32 
33 	for (int i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) {
34 		unsigned type = ELF32_R_TYPE(rel[i].r_info);
35 		unsigned symbolIndex = ELF32_R_SYM(rel[i].r_info);
36 		addr_t final_val;
37 		addr_t S;
38 
39 		image_t* symbolImage = NULL;
40 		if (symbolIndex != 0) {
41 			Elf32_Sym* sym = SYMBOL(image, symbolIndex);
42 			status_t status = resolve_symbol(rootImage, image, sym, cache, &S,
43 					&symbolImage);
44 			if (status < B_OK) {
45 				TRACE("resolve symbol \"%s\" returned: %ld\n",
46 					SYMNAME(image, sym), status);
47 				return status;
48 			}
49 		}
50 
51 		switch (type) {
52 			case R_ARM_NONE:
53 				continue;
54 			case R_ARM_RELATIVE:
55 				final_val = B + A;
56 				break;
57 			case R_ARM_JMP_SLOT:
58 			case R_ARM_GLOB_DAT:
59 				final_val = S;
60 				break;
61 			case R_ARM_ABS32:
62 				final_val = S + A;
63 				break;
64 			default:
65 				TRACE("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
66 				return B_NOT_ALLOWED;
67 		}
68 
69 		*P = final_val;
70 	}
71 
72 # undef P
73 # undef A
74 # undef B
75 
76 	return B_NO_ERROR;
77 }
78 
79 
80 status_t
81 arch_relocate_image(image_t *rootImage, image_t *image,
82 	SymbolLookupCache* cache)
83 {
84 	status_t status;
85 
86 	// deal with the rels first
87 	if (image->rel) {
88 		status = relocate_rel(rootImage, image, image->rel, image->rel_len,
89 			cache);
90 		if (status < B_OK)
91 			return status;
92 	}
93 
94 	if (image->pltrel) {
95 		status = relocate_rel(rootImage, image, image->pltrel,
96 			image->pltrel_len, cache);
97 		if (status < B_OK)
98 			return status;
99 	}
100 
101 	if (image->rela) {
102 		TRACE("RELA relocations not supported\n");
103 		return EOPNOTSUPP;
104 	}
105 
106 	return B_OK;
107 }
108