1 /*	$NetBSD: kobj_machdep.c,v 1.6 2014/03/06 09:22:52 matt Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*-
30  * Copyright 1996-1998 John D. Polstra.
31  * All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52  */
53 
54 #include <sys/cdefs.h>
55 __KERNEL_RCSID(0, "$NetBSD: kobj_machdep.c,v 1.6 2014/03/06 09:22:52 matt Exp $");
56 
57 #define	ELFSIZE		ARCH_ELFSIZE
58 
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/kobj.h>
62 #include <sys/exec.h>
63 #include <sys/exec_elf.h>
64 
65 int
kobj_reloc(kobj_t ko,uintptr_t relocbase,const void * data,bool isrela,bool local)66 kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data,
67 	   bool isrela, bool local)
68 {
69 #ifdef _LP64
70 	Elf64_Half *wwhere;
71 #endif
72 	Elf_Addr *where;
73 	Elf32_Half *hwhere;
74 	Elf_Addr addr;
75 	Elf_Sword addend;		/* needs to be signed */
76 	u_int rtype, symidx;
77 	const Elf_Rela *rela;
78 
79 	if (!isrela) {
80 		panic("kobj_reloc: REL relocations not supported");
81 	}
82 
83 	rela = (const Elf_Rela *)data;
84 	where = (Elf_Addr *) (relocbase + rela->r_offset);
85 	hwhere = (Elf32_Half *) (relocbase + rela->r_offset);
86 #ifdef _LP64
87 	wwhere = (Elf64_Half *) (relocbase + rela->r_offset);
88 #endif
89 	addend = rela->r_addend;
90 	rtype = ELF_R_TYPE(rela->r_info);
91 	symidx = ELF_R_SYM(rela->r_info);
92 
93 	switch (rtype) {
94 	case R_PPC_NONE:
95 	       	break;
96 
97 	case R_PPC_RELATIVE:	/* word32 B + A */
98 		addend += relocbase;			/* A += B */
99 	       	break;
100 
101 	case R_PPC_REL32:	/* word32 S + A - P */
102 	case R_PPC_REL16:	/* half16* (S + A - P) */
103 	case R_PPC_REL16_LO:	/* half16 #lo(S + A - P) */
104 	case R_PPC_REL16_HI:	/* half16 #hi(S + A - P) */
105 	case R_PPC_REL16_HA:	/* half16 #ha(S + A - P) */
106 		addend -= relocbase + rela->r_offset;	/* A -= P */
107 		/* FALLTHROUGH */
108 
109 #ifdef _LP64
110 	case R_PPC_ADDR64:	/* doubleword64 S + A */
111 #endif
112 	case R_PPC_ADDR32:	/* word32 S + A */
113 	case R_PPC_ADDR16:	/* half16* S + A */
114 	case R_PPC_ADDR16_LO:	/* half16 #lo(S + A) */
115 	case R_PPC_ADDR16_HA:	/* half16 #ha(S + A) */
116 	case R_PPC_ADDR16_HI:	/* half16 #hi(S + A) */
117 		addr = kobj_sym_lookup(ko, symidx);
118 	       	if (addr == 0)
119 	       		return -1;
120 
121 #if 0
122 		/*
123 		 * addend values are sometimes relative to sections
124 		 * (i.e. .rodata) in rela, where in reality they
125 		 * are relative to relocbase. Detect this condition.
126 		 */
127 		if (addr > relocbase && addr <= (relocbase + addend))
128 			addr = relocbase + addend;
129 		else
130 #endif
131 		addend += addr;				/* A += S */
132 		break;
133 
134 	default:
135 		printf("kobj_reloc: unexpected relocation type %u\n", rtype);
136 		return -1;
137 	}
138 
139 
140 	switch (rtype) {
141 	case R_PPC_REL32:	/* word32 S + A - P */
142 #ifdef _LP64
143 		*wwhere = addend;
144 		break;
145 #endif
146 	case R_PPC_RELATIVE:	/* doubleword64/word32 B + A */
147 	case R_PPC_ADDR32:	/* doubleword64/word32 S + A */
148 	       	*where = addend;
149 	       	break;
150 
151 	case R_PPC_REL16:	/* half16* (S + A - P) */
152 	case R_PPC_ADDR16:	/* half16* S + A */
153 		if ((int16_t) addend != addend)
154 			return -1;
155 		/* FALLTHROUGH */
156 	case R_PPC_REL16_LO:	/* half16 #lo(S + A - P) */
157 	case R_PPC_ADDR16_LO:	/* half16 #lo(S + A) */
158 		*hwhere = addend & 0xffff;
159 		break;
160 
161 	case R_PPC_REL16_HA:	/* half16 #ha(S + A - P) */
162 	case R_PPC_ADDR16_HA:	/* half16 #ha(S + A) */
163 		addend += 0x8000;
164 		/* FALLTHROUGH */
165 	case R_PPC_REL16_HI:	/* half16 #hi(S + A - P) */
166 	case R_PPC_ADDR16_HI:	/* half16 #hi(S + A) */
167 		*hwhere = (addend >> 16) & 0xffff;
168 		break;
169 	}
170 
171 	return 0;
172 }
173 
174 int
kobj_machdep(kobj_t ko,void * base,size_t size,bool load)175 kobj_machdep(kobj_t ko, void *base, size_t size, bool load)
176 {
177 	if (load)
178 		__syncicache(base, size);
179 
180 	return 0;
181 }
182