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
25static int
26relocate_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
80status_t
81arch_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