Wed Jun 8 17:19:20 2011 UTC ()
Rework to support more relocations.  Reorganize so code doesn't need to be
replicated over and over.


(matt)
diff -r1.4 -r1.5 src/sys/arch/powerpc/powerpc/kobj_machdep.c

cvs diff -r1.4 -r1.5 src/sys/arch/powerpc/powerpc/kobj_machdep.c (expand / switch to unified diff)

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