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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 #ifndef _INLINE_RELOC_H
26 #define _INLINE_RELOC_H
28 #include <sys/types.h>
33 * Generic relative relocation function.
38 _elf_reloc_relative(ulong_t rbgn
, ulong_t base
, Rt_map
*lmp
, APlist
**textrel
,
41 mmapobj_result_t
*mpp
;
44 roffset
= ((M_RELOC
*)rbgn
)->r_offset
;
48 * If this relocation is against an address that is not associated with
49 * a mapped segment, fall back to the generic relocation loop to
50 * collect the associated error.
52 if ((mpp
= find_segment((caddr_t
)roffset
, lmp
)) == NULL
)
56 * If this relocation is against a segment that does not provide write
57 * access, set the write permission for all non-writable mappings.
59 if (((mpp
->mr_prot
& PROT_WRITE
) == 0) && textrel
&&
60 ((set_prot(lmp
, mpp
, 1) == 0) ||
61 (aplist_append(textrel
, mpp
, AL_CNT_TEXTREL
) == NULL
)))
65 * Perform a base address update. This simple operation is required
66 * for updating .plt relocations in preparation for lazy binding.
70 *((ulong_t
*)roffset
) += base
;
75 * Perform the actual relocation. Note, for backward compatibility,
76 * SPARC relocations are added to the offset contents (there was a time
77 * when the offset was used to contain the addend, rather than using
81 *((ulong_t
*)roffset
) += base
+ ((M_RELOC
*)rbgn
)->r_addend
;
82 #elif defined(__amd64)
83 *((ulong_t
*)roffset
) = base
+ ((M_RELOC
*)rbgn
)->r_addend
;
85 *((ulong_t
*)roffset
) += base
;
91 * When a generic relocation loop realizes that it's dealing with relative
92 * relocations, but no DT_RELCOUNT .dynamic tag is present, this tighter loop
93 * is entered as an optimization.
97 elf_reloc_relative(ulong_t rbgn
, ulong_t rend
, ulong_t rsize
, ulong_t base
,
98 Rt_map
*lmp
, APlist
**textrel
, int add
)
103 if (_elf_reloc_relative(rbgn
, base
, lmp
, textrel
, add
) == 0)
111 * Make sure the next type is a relative relocation.
113 rtype
= ELF_R_TYPE(((M_RELOC
*)rbgn
)->r_info
, M_MACH
);
115 } while (rtype
== M_R_RELATIVE
);
121 * This is the tightest loop for RELATIVE relocations for those objects built
122 * with the DT_RELACOUNT .dynamic entry.
124 inline static ulong_t
126 elf_reloc_relative_count(ulong_t rbgn
, ulong_t rcount
, ulong_t rsize
,
127 ulong_t base
, Rt_map
*lmp
, APlist
**textrel
, int add
)
129 for (; rcount
; rcount
--) {
130 if (_elf_reloc_relative(rbgn
, base
, lmp
, textrel
, add
) == 0)
139 * Determine, from a symbols Syminfo information, whether a symbol reference
140 * is deferred. This routine is called from elf_reloc() as part of processing
141 * an objects relocations.
145 is_sym_deferred(ulong_t rbgn
, ulong_t base
, Rt_map
*lmp
, APlist
**textrel
,
146 Syminfo
*sip
, ulong_t sndx
)
151 * ldd(1) by default, sets LD_DEFERRED to force deferred dependency
152 * processing. ldd -D disables LD_DEFERRED, which allows ld.so.1's
153 * default action of skipping deferred dependencies.
155 if (rtld_flags
& RT_FL_DEFERRED
)
159 sipe
= (Syminfo
*)((char *)sip
+ (sndx
* SYMINENT(lmp
)));
160 if (sipe
->si_flags
& SYMINFO_FLG_DEFERRED
) {
162 * This .plt relocation should be skipped at this time, as
163 * deferred references are only processed when the associated
164 * function is explicitly called.
166 * On i386 and amd64 platforms the relocation offset needs
167 * adjusting to add this objects base address. If the object
168 * has already been relocated without RTLD_NOW, then this
169 * update will have already been carried out. However, if this
170 * is an initial RTLD_NOW relocation pass, this relocation
171 * offset needs updating now.
174 if ((FLAGS(lmp
) & FLG_RT_RELOCED
) == 0)
175 (void) _elf_reloc_relative(rbgn
, base
, lmp
, textrel
, 1);
182 #endif /* _INLINE_RELOC_H */