1 /* $NetBSD: rmreloc.c,v 1.2 2006/06/25 21:32:41 christos Exp $ */
4 * Copyright 1996 John D. Polstra.
5 * Copyright 1996 Matt Thomas <matt@3am-software.com>
6 * Copyright 2002 Charles M. Hannum <root@ihack.net>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by John Polstra.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * rmreloc.c - relocate an ELFish RISC OS relocatable module.
38 * This code is a heavily hacked version of parts of:
39 * lib/libexec/ld.elf_so/headers.c
40 * lib/libexec/ld.elf_so/arch/arm/mdreloc.c
42 * At present it only deals with DT_REL tables containing R_ARM_NONE
43 * and R_ARM_RELATIVE relocations, because those are all that my
44 * linker emits. More can be added as needed. Note that this has to
45 * handle relocating already-relocated code, e.g. after *RMTidy, so
46 * most relocations have to reference oldbase, which ld.elf_so just
47 * assumes is zero. There may be a cleverer way to do this.
50 #include <sys/types.h>
51 #include <sys/stdint.h>
52 #include <lib/libsa/stand.h>
54 #include <sys/exec_elf.h>
56 #include <riscoscalls.h>
58 os_error
*relocate_self(Elf_Dyn
*, void *, void *);
60 #define assert(x) /* nothing */
63 * While relocating ourselves, we must not refer to any global variables.
64 * This includes _DYNAMIC -- the startup code finds it for us and passes
65 * it to us along with the base address of the module.
69 void * relocbase
; /* Reloc const = mapbase - *vaddrbase */
70 Elf_Dyn
*dynamic
; /* Dynamic section */
71 const Elf_Rel
*rel
; /* Relocation entries */
72 const Elf_Rel
*rellim
; /* Limit of Relocation entries */
75 #define rdbg(x) /* nothing */
78 * It is possible for the compiler to emit relocations for unaligned data.
79 * We handle this situation with these inlines.
81 #define RELOC_ALIGNED_P(x) \
82 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
84 static inline Elf_Addr
89 memcpy(&res
, where
, sizeof(res
));
95 store_ptr(void *where
, Elf_Addr val
)
98 memcpy(where
, &val
, sizeof(val
));
101 static struct os_error bad_reloc
= {
102 0, "Unhandled ELF redirection"
106 relocate_self(Elf_Dyn
*dynamic
, void *oldbase
, void *newbase
)
114 obj
= &o
; obj
->dynamic
= dynamic
; obj
->relocbase
= newbase
;
116 for (dynp
= obj
->dynamic
; dynp
->d_tag
!= DT_NULL
; ++dynp
) {
117 switch (dynp
->d_tag
) {
119 obj
->rel
= (const Elf_Rel
*)
120 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
123 relsz
= dynp
->d_un
.d_val
;
126 assert(dynp
->d_un
.d_val
== sizeof(Elf_Rel
));
131 obj
->rellim
= (const Elf_Rel
*)((void *)obj
->rel
+ relsz
);
133 for (rel
= obj
->rel
; rel
< obj
->rellim
; rel
++) {
137 where
= (Elf_Addr
*)(obj
->relocbase
+ rel
->r_offset
);
139 switch (ELF_R_TYPE(rel
->r_info
)) {
143 case R_TYPE(RELATIVE
): /* word32 B + A */
144 if (__predict_true(RELOC_ALIGNED_P(where
))) {
145 tmp
= *where
+ (Elf_Addr
)obj
->relocbase
-
149 tmp
= load_ptr(where
) +
150 (Elf_Addr
)obj
->relocbase
-
152 store_ptr(where
, tmp
);
154 rdbg(("RELATIVE in %s --> %p", obj
->path
,