xref: /netbsd-src/sys/arch/i386/stand/efiboot/self_reloc.c (revision d13f4989890263688855b3a1d8371c40c1eccf7f)
1*d13f4989Snonaka /*	$NetBSD: self_reloc.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
2*d13f4989Snonaka 
3*d13f4989Snonaka /*-
4*d13f4989Snonaka  * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org>
5*d13f4989Snonaka  * All rights reserved.
6*d13f4989Snonaka  *
7*d13f4989Snonaka  * Redistribution and use in source and binary forms, with or without
8*d13f4989Snonaka  * modification, are permitted provided that the following conditions
9*d13f4989Snonaka  * are met:
10*d13f4989Snonaka  * 1. Redistributions of source code must retain the above copyright
11*d13f4989Snonaka  *    notice, this list of conditions and the following disclaimer.
12*d13f4989Snonaka  * 2. Redistributions in binary form must reproduce the above copyright
13*d13f4989Snonaka  *    notice, this list of conditions and the following disclaimer in the
14*d13f4989Snonaka  *    documentation and/or other materials provided with the distribution.
15*d13f4989Snonaka  *
16*d13f4989Snonaka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*d13f4989Snonaka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*d13f4989Snonaka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*d13f4989Snonaka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*d13f4989Snonaka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*d13f4989Snonaka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*d13f4989Snonaka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*d13f4989Snonaka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*d13f4989Snonaka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*d13f4989Snonaka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*d13f4989Snonaka  * SUCH DAMAGE.
27*d13f4989Snonaka  */
28*d13f4989Snonaka 
29*d13f4989Snonaka #include <sys/types.h>
30*d13f4989Snonaka #include <sys/exec_elf.h>
31*d13f4989Snonaka 
32*d13f4989Snonaka #include <efi.h>
33*d13f4989Snonaka 
34*d13f4989Snonaka void self_reloc(Elf_Addr, Elf_Dyn *);
35*d13f4989Snonaka 
36*d13f4989Snonaka #if defined(__aarch64__)
37*d13f4989Snonaka #define	USE_RELA
38*d13f4989Snonaka #endif
39*d13f4989Snonaka 
40*d13f4989Snonaka /*
41*d13f4989Snonaka  * A simple elf relocator.
42*d13f4989Snonaka  */
43*d13f4989Snonaka void
self_reloc(Elf_Addr baseaddr,Elf_Dyn * dynamic)44*d13f4989Snonaka self_reloc(Elf_Addr baseaddr, Elf_Dyn *dynamic)
45*d13f4989Snonaka {
46*d13f4989Snonaka 	Elf_Word relsz, relent;
47*d13f4989Snonaka 	Elf_Addr *newaddr;
48*d13f4989Snonaka 	Elf_Rel *rel = NULL;
49*d13f4989Snonaka 	Elf_Dyn *dynp;
50*d13f4989Snonaka 
51*d13f4989Snonaka 	/*
52*d13f4989Snonaka 	 * Find the relocation address, its size and the relocation entry.
53*d13f4989Snonaka 	 */
54*d13f4989Snonaka 	relsz = 0;
55*d13f4989Snonaka 	relent = 0;
56*d13f4989Snonaka 	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
57*d13f4989Snonaka 		switch (dynp->d_tag) {
58*d13f4989Snonaka 		case DT_REL:
59*d13f4989Snonaka 		case DT_RELA:
60*d13f4989Snonaka 			rel = (Elf_Rel *)(dynp->d_un.d_ptr + baseaddr);
61*d13f4989Snonaka 			break;
62*d13f4989Snonaka 		case DT_RELSZ:
63*d13f4989Snonaka 		case DT_RELASZ:
64*d13f4989Snonaka 			relsz = dynp->d_un.d_val;
65*d13f4989Snonaka 			break;
66*d13f4989Snonaka 		case DT_RELENT:
67*d13f4989Snonaka 		case DT_RELAENT:
68*d13f4989Snonaka 			relent = dynp->d_un.d_val;
69*d13f4989Snonaka 			break;
70*d13f4989Snonaka 		default:
71*d13f4989Snonaka 			break;
72*d13f4989Snonaka 		}
73*d13f4989Snonaka 	}
74*d13f4989Snonaka 
75*d13f4989Snonaka 	/*
76*d13f4989Snonaka 	 * Perform the actual relocation.
77*d13f4989Snonaka 	 */
78*d13f4989Snonaka 	for (; relsz > 0; relsz -= relent) {
79*d13f4989Snonaka 		switch (ELF_R_TYPE(rel->r_info)) {
80*d13f4989Snonaka 		case R_TYPE(NONE):
81*d13f4989Snonaka 			/* No relocation needs be performed. */
82*d13f4989Snonaka 			break;
83*d13f4989Snonaka 
84*d13f4989Snonaka 		case R_TYPE(RELATIVE):
85*d13f4989Snonaka 			/* Address relative to the base address. */
86*d13f4989Snonaka 			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
87*d13f4989Snonaka 			*newaddr += baseaddr;
88*d13f4989Snonaka #ifdef USE_RELA
89*d13f4989Snonaka 			/* Add the addend when the ABI uses them */
90*d13f4989Snonaka 			*newaddr += ((Elf_Rela *)rel)->r_addend;
91*d13f4989Snonaka #endif
92*d13f4989Snonaka 			break;
93*d13f4989Snonaka 		default:
94*d13f4989Snonaka 			/* XXX: do we need other relocations ? */
95*d13f4989Snonaka 			break;
96*d13f4989Snonaka 		}
97*d13f4989Snonaka 		rel = (Elf_Rel *) ((char *) rel + relent);
98*d13f4989Snonaka 	}
99*d13f4989Snonaka }
100