16699 viona should expose kstats
[illumos-gate.git] / usr / src / uts / sparc / krtld / doreloc.c
blobecb213a5fcb65b42b08080d4cf59ad572fea485a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
26 #if defined(_KERNEL)
27 #include <sys/types.h>
28 #include "krtld/reloc.h"
29 #else
30 #define ELF_TARGET_SPARC
31 #if defined(DO_RELOC_LIBLD)
32 #undef DO_RELOC_LIBLD
33 #define DO_RELOC_LIBLD_SPARC
34 #endif
35 #include <stdio.h>
36 #include "sgs.h"
37 #include "machdep.h"
38 #include "libld.h"
39 #include "reloc.h"
40 #include "conv.h"
41 #include "msg.h"
42 #endif
45 * We need to build this code differently when it is used for
46 * cross linking:
47 * - Data alignment requirements can differ from those
48 * of the running system, so we can't access data
49 * in units larger than a byte
50 * - We have to include code to do byte swapping when the
51 * target and linker host use different byte ordering,
52 * but such code is a waste when running natively.
54 #if !defined(DO_RELOC_LIBLD) || defined(__sparc)
55 #define DORELOC_NATIVE
56 #endif
59 * This table represents the current relocations that do_reloc() is able to
60 * process. The relocations below that are marked SPECIAL are relocations that
61 * take special processing and shouldn't actually ever be passed to do_reloc().
63 const Rel_entry reloc_table[R_SPARC_NUM] = {
64 /* R_SPARC_NONE */ {0x0, FLG_RE_NOTREL, 0, 0, 0},
65 /* R_SPARC_8 */ {0x0, FLG_RE_VERIFY, 1, 0, 0},
66 /* R_SPARC_16 */ {0x0, FLG_RE_VERIFY, 2, 0, 0},
67 /* R_SPARC_32 */ {0x0, FLG_RE_VERIFY, 4, 0, 0},
68 /* R_SPARC_DISP8 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
69 1, 0, 0},
70 /* R_SPARC_DISP16 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
71 2, 0, 0},
72 /* R_SPARC_DISP32 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
73 4, 0, 0},
74 /* R_SPARC_WDISP30 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
75 4, 2, 30},
76 /* R_SPARC_WDISP22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
77 4, 2, 22},
78 #if defined(_ELF64)
79 /* R_SPARC_HI22 */ {0x0, FLG_RE_VERIFY, 4, 10, 22},
80 #else
81 /* R_SPARC_HI22 */ {0x0, FLG_RE_NOTREL, 4, 10, 22},
82 #endif
83 /* R_SPARC_22 */ {0x0, FLG_RE_VERIFY, 4, 0, 22},
84 /* R_SPARC_13 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 13},
85 /* R_SPARC_LO10 */ {0x3ff, FLG_RE_SIGN, 4, 0, 13},
86 /* R_SPARC_GOT10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_SIGN, 4, 0, 13},
87 /* R_SPARC_GOT13 */ {0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN,
88 4, 0, 13},
89 /* R_SPARC_GOT22 */ {0x0, FLG_RE_GOTADD, 4, 10, 22},
90 /* R_SPARC_PC10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND,
91 4, 0, 13},
92 /* R_SPARC_PC22 */ {0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY |
93 FLG_RE_LOCLBND, 4, 10, 22},
94 /* R_SPARC_WPLT30 */ {0x0, FLG_RE_PCREL | FLG_RE_PLTREL |
95 FLG_RE_VERIFY | FLG_RE_SIGN,
96 4, 2, 30},
97 /* R_SPARC_COPY */ {0x0, 0, 0, 0, 0}, /* SPECIAL */
98 #if defined(_ELF64)
99 /* R_SPARC_GLOB_DAT */ {0x0, FLG_RE_NOTREL, 8, 0, 0},
100 #else
101 /* R_SPARC_GLOB_DAT */ {0x0, FLG_RE_NOTREL, 4, 0, 0},
102 #endif
103 /* R_SPARC_JMP_SLOT */ {0x0, 0, 0, 0, 0}, /* SPECIAL */
104 #if defined(_ELF64)
105 /* R_SPARC_RELATIVE */ {0x0, FLG_RE_NOTREL, 8, 0, 0},
106 #else
107 /* R_SPARC_RELATIVE */ {0x0, FLG_RE_NOTREL, 4, 0, 0},
108 #endif
109 /* R_SPARC_UA32 */ {0x0, FLG_RE_UNALIGN, 4, 0, 0},
110 /* R_SPARC_PLT32 */ {0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
111 FLG_RE_ADDRELATIVE, 4, 0, 0},
112 /* R_SPARC_HIPLT22 */ {0x0, FLG_RE_PLTREL, 4, 10, 22},
113 /* R_SPARC_LOPLT10 */ {0x3ff, FLG_RE_PLTREL, 4, 0, 13},
114 /* R_SPARC_PCPLT32 */ {0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
115 4, 0, 0},
116 /* R_SPARC_PCPLT22 */ {0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
117 4, 10, 22},
118 /* R_SPARC_PCPLT10 */ {0x3ff, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
119 4, 0, 13},
120 /* R_SPARC_10 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 10},
121 /* R_SPARC_11 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 11},
122 /* R_SPARC_64 */ {0x0, FLG_RE_VERIFY, 8, 0, 0}, /* V9 */
123 /* R_SPARC_OLO10 */ {0x3ff, FLG_RE_EXTOFFSET | FLG_RE_SIGN,
124 4, 0, 13}, /* V9 */
125 /* R_SPARC_HH22 */ {0x0, FLG_RE_VERIFY, 4, 42, 22}, /* V9 */
126 /* R_SPARC_HM10 */ {0x3ff, FLG_RE_SIGN, 4, 32, 13}, /* V9 */
127 /* R_SPARC_LM22 */ {0x0, FLG_RE_NOTREL, 4, 10, 22}, /* V9 */
128 /* R_SPARC_PC_HH22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY,
129 4, 42, 22}, /* V9 */
130 /* R_SPARC_PC_HM10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN,
131 4, 32, 13}, /* V9 */
132 /* R_SPARC_PC_LM22 */ {0x0, FLG_RE_PCREL,
133 4, 10, 22}, /* V9 */
134 /* R_SPARC_WDISP16 */ {0x0, FLG_RE_PCREL | FLG_RE_WDISP16 |
135 FLG_RE_VERIFY | FLG_RE_SIGN,
136 4, 2, 16},
137 /* R_SPARC_WDISP19 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
138 4, 2, 19},
139 /* R_SPARC_GLOB_JMP */ {0x0, 0, 0, 0, 0}, /* V9 - not implemented */
140 /* removed from v9 ABI */
141 /* R_SPARC_7 */ {0x0, FLG_RE_NOTREL, 4, 0, 7},
142 /* R_SPARC_5 */ {0x0, FLG_RE_NOTREL, 4, 0, 5},
143 /* R_SPARC_6 */ {0x0, FLG_RE_NOTREL, 4, 0, 6},
144 /* R_SPARC_DISP64 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
145 8, 0, 0},
146 /* R_SPARC_PLT64 */ {0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
147 FLG_RE_ADDRELATIVE, 8, 0, 0},
148 /* R_SPARC_HIX22 */ {(Xword)(-1LL), FLG_RE_VERIFY,
149 4, 10, 22}, /* V9 - HaL */
150 /* R_SPARC_LOX10 */ {0x3ff, FLG_RE_SIGN, 4, 0, 13}, /* V9 - HaL */
151 /* R_SPARC_H44 */ {0x0, FLG_RE_VERIFY, 4, 22, 22}, /* V9 */
152 /* R_SPARC_M44 */ {0x3ff, FLG_RE_NOTREL, 4, 12, 10}, /* V9 */
153 /* R_SPARC_L44 */ {0xfff, FLG_RE_NOTREL, 4, 0, 13}, /* V9 */
154 /* R_SPARC_REGISTER */ {0x0, FLG_RE_REGISTER, 0, 0, 0}, /* SPECIAL */
155 /* R_SPARC_UA64 */ {0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
156 8, 0, 0}, /* V9 */
157 /* R_SPARC_UA16 */ {0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
158 2, 0, 0},
159 /* R_SPARC_TLS_GD_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22},
160 /* R_SPARC_TLS_GD_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD |
161 FLG_RE_SIGN, 4, 0, 13},
162 /* R_SPARC_TLS_GD_ADD */ {0x0, FLG_RE_TLSGD, 0, 0, 0},
163 /* R_SPARC_TLS_GD_CALL */ {0x0, FLG_RE_TLSGD, 0, 0, 0},
164 /* R_SPARC_TLS_LDM_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22},
165 /* R_SPARC_TLS_LDM_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD |
166 FLG_RE_SIGN, 4, 0, 13},
167 /* R_SPARC_TLS_LDM_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0},
168 /* R_SPARC_TLS_LDM_CALL */ {0x0, FLG_RE_TLSLD, 0, 0, 0},
169 /* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22},
170 /* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13},
171 /* R_SPARC_TLS_LDO_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0},
172 /* R_SPARC_TLS_IE_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22},
173 /* R_SPARC_TLS_IE_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE |
174 FLG_RE_SIGN, 4, 0, 13},
175 /* R_SPARC_TLS_IE_LD */ {0x0, FLG_RE_TLSIE, 0, 0, 0},
176 /* R_SPARC_TLS_IE_LDX */ {0x0, FLG_RE_TLSIE, 0, 0, 0},
177 /* R_SPARC_TLS_IE_ADD */ {0x0, FLG_RE_TLSIE, 0, 0, 0},
178 /* R_SPARC_TLS_LE_HIX22 */ {(Xword)(-1LL),
179 FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22},
180 /* R_SPARC_TLS_LE_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13},
181 /* R_SPARC_TLS_DTPMOD32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0},
182 /* R_SPARC_TLS_DTPMOD64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0},
183 /* R_SPARC_TLS_DTPOFF32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0},
184 /* R_SPARC_TLS_DTPOFF64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0},
185 /* R_SPARC_TLS_TPOFF32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0},
186 /* R_SPARC_TLS_TPOFF64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0},
187 /* R_SPARC_GOTDATA_HIX22 */ {0, FLG_RE_SIGN | FLG_RE_GOTREL |
188 FLG_RE_VERIFY, 4, 10, 22},
189 /* R_SPARC_GOTDATA_LOX10 */ { 0x3ff, FLG_RE_GOTREL | FLG_RE_SIGN, 4, 0, 13},
190 /* R_SPARC_GOTDATA_OP_HIX22 */ { 0x0, FLG_RE_GOTOPINS | FLG_RE_GOTADD,
191 4, 10, 22},
192 /* R_SPARC_GOTDATA_OP_LOX10 */ { 0x3ff, FLG_RE_SIGN | FLG_RE_GOTOPINS |
193 FLG_RE_GOTADD, 4, 0, 13},
194 /* R_SPARC_GOTDATA_OP */ { 0x0, FLG_RE_GOTOPINS, 0, 0, 0},
195 /* R_SPARC_H34 */ {0x0, FLG_RE_VERIFY, 4, 12, 22}, /* V9 */
196 /* R_SPARC_SIZE32 */ {0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0},
197 /* R_SPARC_SIZE64 */ {0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 8, 0, 0},
202 * Write a single relocated value to its reference location.
203 * We assume we wish to add the relocation amount, value, to the
204 * value of the address already present in the instruction.
206 * NAME VALUE FIELD CALCULATION
208 * R_SPARC_NONE 0 none none
209 * R_SPARC_8 1 V-byte8 S + A
210 * R_SPARC_16 2 V-half16 S + A
211 * R_SPARC_32 3 V-word32 S + A
212 * R_SPARC_DISP8 4 V-byte8 S + A - P
213 * R_SPARC_DISP16 5 V-half16 S + A - P
214 * R_SPARC_DISP32 6 V-word32 S + A - P
215 * R_SPARC_WDISP30 7 V-disp30 (S + A - P) >> 2
216 * R_SPARC_WDISP22 8 V-disp22 (S + A - P) >> 2
217 * R_SPARC_HI22 9 T-imm22 (S + A) >> 10
218 * R_SPARC_22 10 V-imm22 S + A
219 * R_SPARC_13 11 V-simm13 S + A
220 * R_SPARC_LO10 12 T-simm13 (S + A) & 0x3ff
221 * R_SPARC_GOT10 13 T-simm13 G & 0x3ff
222 * R_SPARC_GOT13 14 V-simm13 G
223 * R_SPARC_GOT22 15 T-imm22 G >> 10
224 * R_SPARC_PC10 16 T-simm13 (S + A - P) & 0x3ff
225 * R_SPARC_PC22 17 V-disp22 (S + A - P) >> 10
226 * R_SPARC_WPLT30 18 V-disp30 (L + A - P) >> 2
227 * R_SPARC_COPY 19 none none
228 * R_SPARC_GLOB_DAT 20 V-word32 S + A
229 * R_SPARC_JMP_SLOT 21 V-plt22 S + A
230 * R_SPARC_RELATIVE 22 V-word32 S + A
231 * R_SPARC_UA32 23 V-word32 S + A
232 * R_SPARC_PLT32 24 V-word32 L + A
233 * R_SPARC_HIPLT22 25 T-imm22 (L + A) >> 10
234 * R_SPARC_LOPLT10 26 T-simm13 (L + A) & 0x3ff
235 * R_SPARC_PCPLT32 27 V-word32 L + A - P
236 * R_SPARC_PCPLT22 28 V-disp22 (L + A - P) >> 10
237 * R_SPARC_PCPLT10 29 V-simm13 (L + A - P) & 0x3ff
238 * R_SPARC_10 30 V-simm10 S + A
239 * R_SPARC_11 31 V-simm11 S + A
240 * R_SPARC_64 32 V-xword64 S + A
241 * R_SPARC_OLO10 33 V-simm13 ((S + A) & 0x3ff) + O
242 * R_SPARC_HH22 34 V-imm22 (S + A) >> 42
243 * R_SPARC_HM10 35 T-simm13 ((S + A) >> 32) & 0x3ff
244 * R_SPARC_LM22 36 T-imm22 (S + A) >> 10
245 * R_SPARC_PC_HH22 37 V-imm22 (S + A - P) >> 42
246 * R_SPARC_PC_HM10 38 T-simm13 ((S + A - P) >> 32) & 0x3ff
247 * R_SPARC_PC_LM22 39 T-imm22 (S + A - P) >> 10
248 * R_SPARC_WDISP16 40 V-d2/disp14 (S + A - P) >> 2
249 * R_SPARC_WDISP19 41 V-disp19 (S + A - P) >> 2
250 * R_SPARC_GLOB_JMP 42 V-xword64 S + A
251 * R_SPARC_7 43 V-imm7 S + A
252 * R_SPARC_5 44 V-imm5 S + A
253 * R_SPARC_6 45 V-imm6 S + A
254 * R_SPARC_DISP64 46 V-xword64 S + A - P
255 * R_SPARC_PLT64 47 V-xword64 L + A
256 * R_SPARC_HIX22 48 V-imm22 ((S + A) ^
257 * 0xffffffffffffffff) >> 10
258 * R_SPARC_LOX10 49 T-simm13 ((S + A) & 0x3ff) | 0x1c00
259 * R_SPARC_H44 50 V-imm22 (S + A) >> 22
260 * R_SPARC_M44 51 T-imm10 ((S + A) >> 12) & 0x3ff
261 * R_SPARC_L44 52 T-imm13 (S + A) & 0xfff
262 * R_SPARC_REGISTER 53 V-xword64 S + A
263 * R_SPARC_UA64 54 V-xword64 S + A
264 * R_SPARC_UA16 55 V-half16 S + A
265 * R_SPARC_TLS_GD_HI22 56 T-simm22 @dtlndx(S + A) >> 10
266 * R_SPARC_TLS_GD_LO10 57 T-simm13 @dtlndx(S + A) & 0x3ff
267 * R_SPARC_TLS_GD_ADD 58 none SPECIAL
268 * R_SPARC_TLS_GD_CALL 59 V-disp30 SPECIAL
269 * R_SPARC_TLS_LDM_HI22 60 T-simm22 @tmndx(S + A) >> 10
270 * R_SPARC_TLS_LDM_LO10 61 T-simm13 @tmndx(S + A) & 0x3ff
271 * R_SPARC_TLS_LDM_ADD 62 none SPECIAL
272 * R_SPARC_TLS_LDM_CALL 63 V-disp30 SPECIAL
273 * R_SPARC_TLS_LDO_HIX22 64 V-simm22 @dtpoff(S + A) >> 10
274 * R_SPARC_TLS_LDO_LOX10 65 T-simm13 @dtpoff(S + A) & 0x3ff
275 * R_SPARC_TLS_LDO_ADD 66 none SPECIAL
276 * R_SPARC_TLS_IE_HI22 67 T-simm22 @got(@tpoff(S + A)) >> 10
277 * R_SPARC_TLS_IE_LO10 68 T-simm13 @got(@tpoff(S + A)) & 0x3ff
278 * R_SPARC_TLS_IE_LD 69 none SPECIAL
279 * R_SPARC_TLS_IE_LDX 70 none SPECIAL
280 * R_SPARC_TLS_IE_ADD 71 none SPECIAL
281 * R_SPARC_TLS_LE_HIX22 72 V-simm22 (@tpoff(S + A) ^
282 * 0xffffffff) >> 10
283 * R_SPARC_TLS_LE_LOX10 73 T-simm13 (@tpoff(S + A) & 0x3ff) | 0x1c00
284 * R_SPARC_TLS_DTPMOD32 74 V-word32 @dtmod(S + A)
285 * R_SPARC_TLS_DTPMOD64 75 V-word64 @dtmod(S + A)
286 * R_SPARC_TLS_DTPOFF32 76 V-word32 @dtpoff(S + A)
287 * R_SPARC_TLS_DTPOFF64 77 V-word64 @dtpoff(S + A)
288 * R_SPARC_TLS_TPOFF32 78 V-word32 @tpoff(S + A)
289 * R_SPARC_TLS_TPOFF64 79 V-word64 @tpoff(S + A)
290 * R_SPARC_GOTDATA_HIX22 80 V-imm22 ((S + A - GOT) >> 10) ^
291 * ((S + A - GOT) >> 31)
292 * R_SPARC_GOTDATA_LOX10 81 T-simm13 ((S + A - GOT) & 0x3ff) |
293 * (((S + A - GOT) >> 31) &
294 * 0x1c00)
295 * R_SPARC_GOTDATA_OP_HIX22 82 T-imm22 (G >> 10) & (G >> 31)
296 * R_SPARC_GOTDATA_OP_LOX10 83 T-simm13 (G & 0x3ff) |
297 * ((G >> 31) & 0x1c00)
298 * R_SPARC_GOTDATA_OP 84 Word32 SPECIAL
299 * R_SPARC_H34 85 V-imm22 (S + A) >> 12
300 * R_SPARC_SIZE32 86 V-word32 Z + A
301 * R_SPARC_SIZE64 87 V-xword64 Z + A
303 * This is Figure 4-20: Relocation Types from the Draft Copy of
304 * the ABI, Printed on 11/29/88.
306 * NOTE1: relocations 24->45 are newly registered relocations to support
307 * C++ ABI & SPARC V8+ and SPARC V9 architectures (1/9/94), and
308 * 64-bit relocations 46-55 were added for SPARC V9.
310 * NOTE2: relocations 56->79 are added to support Thread-Local storage
311 * as recorded in PSARC/2001/509
313 * NOTE3: The value to be passed for relocations R_SPARC_HIX22 and
314 * R_SPARC_TLS_HIX22 are negative values. So the upper 10 or 40 bits
315 * are 1. (So when the exclusive OR is applied, the upper bits
316 * will be 0.)
318 * Relocation calculations:
320 * The FIELD names indicate whether the relocation type checks for overflow.
321 * A calculated relocation value may be larger than the intended field, and
322 * the relocation type may verify (V) that the value fits, or truncate (T)
323 * the result.
325 * CALCULATION uses the following notation:
326 * A the addend used
327 * B the base address of the shared object in memory
328 * G the offset into the global offset table
329 * L the procedure linkage entry
330 * P the place of the storage unit being relocated
331 * S the value of the symbol
332 * O secondary addend (extra offset) in v9 r_info field
333 * Z the size of the symbol whose index resides in the relocation
334 * entry
336 * @dtlndx(x): Allocate two contiguous entries in the GOT table to hold
337 * a Tls_index structure (for passing to __tls_get_addr()). The
338 * instructions referencing this entry will be bound to the first
339 * of the two GOT entries.
341 * @tmndx(x): Allocate two contiguous entries in the GOT table to hold
342 * a Tls_index structure (for passing to __tls_get_addr()). The
343 * ti_offset field of the Tls_index will be set to 0 (zero) and the
344 * ti_module will be filled in at run-time. The call to
345 * __tls_get_addr() will return the starting offset of the dynamic
346 * TLS block.
348 * @dtpoff(x): calculate the tlsoffset relative to the TLS block.
350 * @tpoff(x): calculate the negative tlsoffset relative to the static
351 * TLS block. This value can be added to the thread-pointer to
352 * calculate the tls address.
354 * @dtpmod(x): calculate the module id of the object containing symbol x.
356 * The calculations in the CALCULATION column are assumed to have been performed
357 * before calling this function except for the addition of the addresses in the
358 * instructions.
360 * Upon successful completion of do_reloc() *value will be set to the
361 * 'bit-shifted' value that will be or'ed into memory.
363 #if defined(_KERNEL)
364 #define lml 0 /* Needed by arglist of REL_ERR_* macros */
366 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
367 const char *file)
368 #elif defined(DO_RELOC_LIBLD)
369 /*ARGSUSED5*/
371 do_reloc_ld(Rel_desc *rdesc, uchar_t *off, Xword *value,
372 rel_desc_sname_func_t rel_desc_sname_func,
373 const char *file, int bswap, void *lml)
374 #else
376 do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
377 const char *file, void *lml)
378 #endif
380 #ifdef DO_RELOC_LIBLD
381 #define sym (* rel_desc_sname_func)(rdesc)
382 uchar_t rtype = rdesc->rel_rtype;
383 #endif
384 Xword uvalue = 0;
385 Xword basevalue, sigbit_mask, sigfit_mask;
386 Xword corevalue = *value;
387 uchar_t bshift;
388 int field_size, re_flags;
389 const Rel_entry *rep;
391 rep = &reloc_table[rtype];
392 bshift = rep->re_bshift;
393 field_size = rep->re_fsize;
394 re_flags = rep->re_flags;
395 sigbit_mask = S_MASK(rep->re_sigbits);
397 if ((re_flags & FLG_RE_SIGN) && sigbit_mask) {
399 * sigfit_mask takes into account that a value
400 * might be signed and discards the signbit for
401 * comparison.
403 sigfit_mask = S_MASK(rep->re_sigbits - 1);
404 } else
405 sigfit_mask = sigbit_mask;
407 if (field_size == 0) {
408 REL_ERR_UNIMPL(lml, file, sym, rtype);
409 return (0);
413 * We have two ways to retrieve the base value, a general one
414 * that will work with data of any alignment, and another that is
415 * fast, but which requires the data to be aligned according to
416 * sparc alignment rules.
418 * For non-native linking, we always use the general path. For
419 * native linking, the FLG_RE_UNALIGN determines it.
421 #if defined(DORELOC_NATIVE)
422 if (re_flags & FLG_RE_UNALIGN)
423 #endif
425 int i;
426 uchar_t *dest = (uchar_t *)&basevalue;
428 basevalue = 0;
429 #if !defined(DORELOC_NATIVE)
430 if (bswap) {
431 int j = field_size - 1;
433 for (i = 0; i < field_size; i++, j--)
434 dest[i] = off[j];
436 } else
437 #endif
440 * Adjust the offset
442 /* LINTED */
443 i = (int)(sizeof (Xword) - field_size);
444 if (i > 0)
445 dest += i;
446 for (i = field_size - 1; i >= 0; i--)
447 dest[i] = off[i];
452 * Non-native linker: We have already fetched the value above,
453 * but if the relocation does not have the FLG_RE_UNALIGN
454 * flag set, we still need to do the same error checking we
455 * would do on a native linker.
456 * Native-linker: If this is an aligned relocation, we need to
457 * fetch the value and also do the error checking.
459 * The FETCH macro is used to conditionalize the fetching so that
460 * it only happens in the native case.
462 #if defined(DORELOC_NATIVE)
463 #define FETCH(_type) basevalue = (Xword)*((_type *)off);
464 #else
465 #define FETCH(_type)
466 #endif
467 if ((re_flags & FLG_RE_UNALIGN) == 0) {
468 if (((field_size == 2) && ((uintptr_t)off & 0x1)) ||
469 ((field_size == 4) && ((uintptr_t)off & 0x3)) ||
470 ((field_size == 8) && ((uintptr_t)off & 0x7))) {
471 REL_ERR_NONALIGN(lml, file, sym, rtype, (uintptr_t)off);
472 return (0);
474 switch (field_size) {
475 case 1:
476 /* LINTED */
477 FETCH(uchar_t);
478 break;
479 case 2:
480 /* LINTED */
481 FETCH(Half);
482 break;
483 case 4:
484 /* LINTED */
485 FETCH(Word);
486 break;
487 case 8:
488 /* LINTED */
489 FETCH(Xword);
490 break;
491 default:
492 REL_ERR_UNNOBITS(lml, file, sym, rtype,
493 (rep->re_fsize * 8));
494 return (0);
497 #undef FETCH
499 if (sigbit_mask) {
501 * The WDISP16 relocation is an unusual one in that it's bits
502 * are not all contiguous. We have to selectivly pull them out.
504 if (re_flags & FLG_RE_WDISP16) {
505 uvalue = ((basevalue & 0x300000) >> 6) |
506 (basevalue & 0x3fff);
507 basevalue &= ~0x303fff;
508 } else {
509 uvalue = sigbit_mask & basevalue;
510 basevalue &= ~sigbit_mask;
513 * If value is signed make sure that we signextend the uvalue.
515 if (re_flags & FLG_RE_SIGN) {
516 if (uvalue & (~sigbit_mask & sigfit_mask))
517 uvalue |= ~sigbit_mask;
519 } else
520 uvalue = basevalue;
522 if (bshift)
523 uvalue <<= bshift;
525 uvalue += *value;
527 if (rep->re_mask &&
528 ((rtype == R_SPARC_HIX22) || (rtype == R_SPARC_TLS_LE_HIX22)))
529 uvalue ^= rep->re_mask;
531 if (bshift) {
533 * This is to check that we are not attempting to
534 * jump to a non-4 byte aligned address.
536 if ((bshift == 2) && (uvalue & 0x3)) {
537 REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, 2, off);
538 return (0);
541 if (re_flags & FLG_RE_SIGN) {
542 uvalue = (Sxword)uvalue >> bshift;
543 } else {
544 uvalue >>= bshift;
546 corevalue >>= bshift;
549 if ((rtype == R_SPARC_GOTDATA_HIX22) ||
550 (rtype == R_SPARC_GOTDATA_OP_HIX22)) {
551 uvalue ^= ((Sxword)(*value) >> 31);
552 corevalue ^= ((Sxword)(*value) >> 31);
555 if (rep->re_mask &&
556 (rtype != R_SPARC_HIX22) && (rtype != R_SPARC_TLS_LE_HIX22) &&
557 (rtype != R_SPARC_GOTDATA_HIX22))
558 uvalue &= rep->re_mask;
560 if ((rtype == R_SPARC_LOX10) || (rtype == R_SPARC_TLS_LE_LOX10)) {
561 uvalue |= 0x1c00;
562 corevalue |= 0x1c00;
565 if ((rtype == R_SPARC_GOTDATA_LOX10) ||
566 (rtype == R_SPARC_GOTDATA_OP_LOX10)) {
567 uvalue |= ((Sxword)(*value) >> 31) & 0x1c00;
568 corevalue |= ((Sxword)(*value) >> 31) & 0x1c00;
572 if ((re_flags & FLG_RE_VERIFY) && sigbit_mask) {
573 if (((re_flags & FLG_RE_SIGN) &&
574 (S_INRANGE((Sxword)uvalue, rep->re_sigbits - 1) == 0)) ||
575 (!(re_flags & FLG_RE_SIGN) &&
576 ((sigbit_mask & uvalue) != uvalue))) {
577 REL_ERR_NOFIT(lml, file, sym, rtype, uvalue);
578 return (0);
582 if (sigbit_mask) {
584 * Again the R_SPARC_WDISP16 relocation takes special
585 * processing because of its non-continguous bits.
587 if (re_flags & FLG_RE_WDISP16)
588 uvalue = ((uvalue & 0xc000) << 6) |
589 (uvalue & 0x3fff);
590 else
591 uvalue &= sigbit_mask;
593 * Combine value back with original word
595 uvalue |= basevalue;
597 *value = corevalue;
600 * Now, we store uvalue back at the location given by off.
601 * This is similar to the fetch case above:
602 * - We have general (unaligned) and fast (aligned) cases
603 * - Cross linkers need to use the unaligned case even
604 * when the relocation does not specify FLG_RE_UNALIGN.
605 * - A cross linker that processes a relocation that does not
606 * have FLG_RE_UNALIGN set has to do the same error
607 * checking that a native linker would do, while avoiding
608 * the aligned store (accomplished with the STORE macro).
610 #if defined(DORELOC_NATIVE)
611 if (re_flags & FLG_RE_UNALIGN)
612 #endif
614 int i;
615 uchar_t *src = (uchar_t *)&uvalue;
617 #if !defined(DORELOC_NATIVE)
618 if (bswap) {
619 int j = field_size - 1;
621 for (i = 0; i < field_size; i++, j--)
622 off[i] = src[j];
624 } else
625 #endif
628 * Adjust the offset.
630 /* LINTED */
631 i = (int)(sizeof (Xword) - field_size);
632 if (i > 0)
633 src += i;
634 for (i = field_size - 1; i >= 0; i--)
635 off[i] = src[i];
639 #if defined(DORELOC_NATIVE)
640 #define STORE(_type) *((_type *)off) = (_type)uvalue
641 #else
642 #define STORE(_type)
643 #endif
644 if ((re_flags & FLG_RE_UNALIGN) == 0) {
645 switch (rep->re_fsize) {
646 case 1:
647 /* LINTED */
648 STORE(uchar_t);
649 break;
650 case 2:
651 /* LINTED */
652 STORE(Half);
653 break;
654 case 4:
655 /* LINTED */
656 STORE(Word);
657 break;
658 case 8:
659 /* LINTED */
660 STORE(Xword);
661 break;
662 default:
664 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
666 REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize);
667 return (0);
670 #undef STORE
672 return (1);
674 #ifdef DO_RELOC_LIBLD
675 #undef sym
676 #endif