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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * SPARC relocation code.
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
38 #include <sys/bootconf.h>
39 #include <sys/modctl.h>
42 #include <sys/kobj_impl.h>
44 #include <sys/tnf_probe.h>
47 #include "krtld/reloc.h"
51 * Probe discovery support
53 #define PROBE_MARKER_SYMBOL "__tnf_probe_version_1"
54 #define TAG_MARKER_SYMBOL "__tnf_tag_version_1"
56 extern int tnf_splice_probes(int, tnf_probe_control_t
*, tnf_tag_data_t
*);
59 * The kernel run-time linker calls this to try to resolve a reference
60 * it can't otherwise resolve. We see if it's marking a probe control
61 * block or a probe tag block; if so, we do the resolution and return 0.
62 * If not, we return 1 to show that we can't resolve it, either.
65 tnf_reloc_resolve(char *symname
, Addr
*value_p
,
66 Elf64_Sxword
*addend_p
,
68 tnf_probe_control_t
**probelist
,
69 tnf_tag_data_t
**taglist
)
71 if (strcmp(symname
, PROBE_MARKER_SYMBOL
) == 0) {
73 ((tnf_probe_control_t
*)offset
)->next
= *probelist
;
74 *probelist
= (tnf_probe_control_t
*)offset
;
77 if (strcmp(symname
, TAG_MARKER_SYMBOL
) == 0) {
79 *value_p
= (Addr
)*taglist
;
80 *taglist
= (tnf_tag_data_t
*)offset
;
86 #define SDT_RESTORE_MASK 0xc1f80000
87 #define SDT_RESTORE 0x81e80000
88 #define SDT_NOP 0x01000000
89 #define SDT_RET 0x81c7e008
90 #define SDT_RETL 0x81c3e008
91 #define SDT_RDO7_MASK 0xbf000000
92 #define SDT_RDO7 0x9e000000
95 sdt_reloc_resolve(struct module
*mp
, char *symname
, uint32_t *instr
, long roff
)
100 * The "statically defined tracing" (SDT) provider for DTrace uses
101 * a mechanism similar to TNF, but somewhat simpler. (Surprise,
102 * surprise.) The SDT mechanism works by replacing calls to the
103 * undefined routine __dtrace_probe_[name] with nop instructions.
104 * The relocations are logged, and SDT itself will later patch the
105 * running binary appropriately.
107 if (strncmp(symname
, sdt_prefix
, strlen(sdt_prefix
)) != 0)
110 symname
+= strlen(sdt_prefix
);
112 sdp
= kobj_alloc(sizeof (sdt_probedesc_t
), KM_WAIT
);
113 sdp
->sdpd_name
= kobj_alloc(strlen(symname
) + 1, KM_WAIT
);
114 bcopy(symname
, sdp
->sdpd_name
, strlen(symname
) + 1);
116 if ((uint32_t *)roff
== instr
) {
118 * This isn't an offset -- it's an absolute value. (This is
119 * typically only true for "unix".) We need to convert the
120 * value into an offset from mp->text.
122 roff
-= (uintptr_t)mp
->text
;
125 sdp
->sdpd_offset
= roff
;
127 sdp
->sdpd_next
= mp
->sdt_probes
;
128 mp
->sdt_probes
= sdp
;
131 * If the next instruction is a restore (any variant), then the probe
132 * point is being tail-called. Instead of patching the call to be a
133 * NOP, we must patch it to be a ret. If the next instruction is
134 * writing to %o7, it must be a tail call from a leaf; we must patch
135 * the instruction to be a retl.
137 if ((*(instr
+ 1) & SDT_RESTORE_MASK
) == SDT_RESTORE
) {
139 } else if ((*(instr
+ 1) & SDT_RDO7_MASK
) == SDT_RDO7
) {
160 uintptr_t reladdr
, rend
;
163 Addr value
, destination
;
167 tnf_probe_control_t
*probelist
= NULL
;
168 tnf_tag_data_t
*taglist
= NULL
;
170 reladdr
= (uintptr_t)reltbl
;
171 rend
= reladdr
+ nreloc
* relocsize
;
174 if (kobj_debug
& D_RELOCATIONS
) {
175 _kobj_printf(ops
, "krtld:\ttype\t\t\toffset\t addend"
177 _kobj_printf(ops
, "krtld:\t\t\t\t\t value\n");
180 destination
= baseaddr
;
183 * If this machine is loading a module through an alternate address
184 * we need to compute the spot where the actual relocation will
187 if (mp
->destination
) {
190 shp
= (Shdr
*)mp
->shdrs
;
191 for (i
= 0; i
< mp
->hdr
.e_shnum
; i
++, shp
++) {
192 if (shp
->sh_addr
== baseaddr
) {
193 if ((shp
->sh_flags
& SHF_ALLOC
) &&
194 !(shp
->sh_flags
& SHF_WRITE
))
195 destination
= (Addr
)mp
->destination
+
196 (baseaddr
- (Addr
)mp
->text
);
203 /* loop through relocations */
204 while (reladdr
< rend
) {
207 rtype
= ELF_R_TYPE(((Rela
*)reladdr
)->r_info
);
208 roff
= off
= ((Rela
*)reladdr
)->r_offset
;
209 stndx
= ELF_R_SYM(((Rela
*)reladdr
)->r_info
);
210 if (stndx
>= mp
->nsyms
) {
212 "do_relocate: bad strndx %d\n", symnum
);
215 if ((rtype
> R_SPARC_NUM
) || IS_TLS_INS(rtype
)) {
216 _kobj_printf(ops
, "krtld: invalid relocation type %d",
218 _kobj_printf(ops
, " at 0x%llx:", off
);
219 _kobj_printf(ops
, " file=%s\n", mp
->filename
);
223 addend
= (long)(((Rela
*)reladdr
)->r_addend
);
224 reladdr
+= relocsize
;
228 if (kobj_debug
& D_RELOCATIONS
) {
231 (mp
->symtbl
+(stndx
* mp
->symhdr
->sh_entsize
));
232 _kobj_printf(ops
, "krtld:\t%s",
233 conv_reloc_SPARC_type(rtype
));
234 _kobj_printf(ops
, "\t0x%8llx", off
);
235 _kobj_printf(ops
, " 0x%8llx", addend
);
236 _kobj_printf(ops
, " %s\n",
237 (const char *)mp
->strings
+ symp
->st_name
);
241 if (rtype
== R_SPARC_NONE
)
244 if (!(mp
->flags
& KOBJ_EXEC
))
248 * if R_SPARC_RELATIVE, simply add base addr
251 if (rtype
== R_SPARC_RELATIVE
) {
255 * get symbol table entry - if symbol is local
256 * value is base address of this object
259 (mp
->symtbl
+(stndx
* mp
->symhdr
->sh_entsize
));
260 if (ELF_ST_BIND(symref
->st_info
) == STB_LOCAL
) {
261 /* *** this is different for .o and .so */
262 value
= symref
->st_value
;
265 * It's global. Allow weak references. If
266 * the symbol is undefined, give TNF (the
267 * kernel probes facility) a chance to see
268 * if it's a probe site, and fix it up if so.
270 if (symref
->st_shndx
== SHN_UNDEF
&&
271 sdt_reloc_resolve(mp
, mp
->strings
+
272 symref
->st_name
, (uint32_t *)off
,
273 roff
+ ((uintptr_t)baseaddr
-
274 (uintptr_t)mp
->text
)) == 0)
277 if (symref
->st_shndx
== SHN_UNDEF
&&
278 tnf_reloc_resolve(mp
->strings
+
279 symref
->st_name
, &symref
->st_value
,
280 &addend
, off
, &probelist
, &taglist
) != 0) {
281 if (ELF_ST_BIND(symref
->st_info
)
290 } else { /* symbol found - relocate */
292 * calculate location of definition
293 * - symbol value plus base address of
294 * containing shared object
296 value
= symref
->st_value
;
297 } /* end else symbol found */
299 } /* end not R_SPARC_RELATIVE */
302 if (IS_EXTOFFSET(rtype
)) {
304 (Word
) ELF_R_TYPE_DATA(((Rela
*)reladdr
)->r_info
);
308 * calculate final value -
309 * if PC-relative, subtract ref addr
311 if (IS_PC_RELATIVE(rtype
)) {
313 value
-= (baseaddr
+ roff
);
319 if (kobj_debug
& D_RELOCATIONS
) {
320 _kobj_printf(ops
, "krtld:\t\t\t\t0x%8llx", off
);
321 _kobj_printf(ops
, " 0x%8llx\n", value
);
324 if (do_reloc_krtld(rtype
, (unsigned char *)off
, (Xword
*)&value
,
325 (const char *)mp
->strings
+ symref
->st_name
,
328 } /* end of while loop */
333 if (tnf_splice_probes(mp
->flags
& KOBJ_PRIM
, probelist
, taglist
))
334 mp
->flags
|= KOBJ_TNF_PROBE
;
340 do_relocations(struct module
*mp
)
346 /* do the relocations */
347 for (shn
= 1; shn
< mp
->hdr
.e_shnum
; shn
++) {
349 (mp
->shdrs
+ shn
* mp
->hdr
.e_shentsize
);
350 if (rshp
->sh_type
== SHT_REL
) {
351 _kobj_printf(ops
, "%s can't process type SHT_REL\n",
355 if (rshp
->sh_type
!= SHT_RELA
)
357 if (rshp
->sh_link
!= mp
->symtbl_section
) {
358 _kobj_printf(ops
, "%s reloc for non-default symtab\n",
362 if (rshp
->sh_info
>= mp
->hdr
.e_shnum
) {
363 _kobj_printf(ops
, "do_relocations: %s ", mp
->filename
);
364 _kobj_printf(ops
, " sh_info out of range %lld\n", shn
);
367 nreloc
= rshp
->sh_size
/ rshp
->sh_entsize
;
369 /* get the section header that this reloc table refers to */
371 (mp
->shdrs
+ rshp
->sh_info
* mp
->hdr
.e_shentsize
);
373 * Do not relocate any section that isn't loaded into memory.
374 * Most commonly this will skip over the .rela.stab* sections
376 if (!(shp
->sh_flags
& SHF_ALLOC
))
379 if (kobj_debug
& D_RELOCATIONS
) {
380 _kobj_printf(ops
, "krtld: relocating: file=%s ",
382 _kobj_printf(ops
, " section=%d\n", shn
);
385 if (do_relocate(mp
, (char *)rshp
->sh_addr
, rshp
->sh_type
,
386 nreloc
, rshp
->sh_entsize
, shp
->sh_addr
) < 0) {
388 "do_relocations: %s do_relocate failed\n",
392 kobj_free((void *)rshp
->sh_addr
, rshp
->sh_size
);
395 mp
->flags
|= KOBJ_RELOCATED
;
398 kobj_free((void *)rshp
->sh_addr
, rshp
->sh_size
);