dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / common / _inline_reloc.h
blob23ee41e288b9cda17b2ca0b86c493d9adf3f69f1
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) 2010, Oracle and/or its affiliates. All rights reserved.
25 #ifndef _INLINE_RELOC_H
26 #define _INLINE_RELOC_H
28 #include <sys/types.h>
29 #include <rtld.h>
30 #include <debug.h>
33 * Generic relative relocation function.
35 inline static ulong_t
36 /* LINTED */
37 /* ARGSUSED4 */
38 _elf_reloc_relative(ulong_t rbgn, ulong_t base, Rt_map *lmp, APlist **textrel,
39 int add)
41 mmapobj_result_t *mpp;
42 ulong_t roffset;
44 roffset = ((M_RELOC *)rbgn)->r_offset;
45 roffset += base;
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)
53 return (0);
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)))
62 return (0);
65 * Perform a base address update. This simple operation is required
66 * for updating .plt relocations in preparation for lazy binding.
68 #if defined(__x86)
69 if (add) {
70 *((ulong_t *)roffset) += base;
71 return (1);
73 #endif
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
78 * the addend itself).
80 #if defined(__sparc)
81 *((ulong_t *)roffset) += base + ((M_RELOC *)rbgn)->r_addend;
82 #elif defined(__amd64)
83 *((ulong_t *)roffset) = base + ((M_RELOC *)rbgn)->r_addend;
84 #else
85 *((ulong_t *)roffset) += base;
86 #endif
87 return (1);
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.
95 inline static ulong_t
96 /* LINTED */
97 elf_reloc_relative(ulong_t rbgn, ulong_t rend, ulong_t rsize, ulong_t base,
98 Rt_map *lmp, APlist **textrel, int add)
100 uchar_t rtype;
102 do {
103 if (_elf_reloc_relative(rbgn, base, lmp, textrel, add) == 0)
104 break;
106 rbgn += rsize;
107 if (rbgn >= rend)
108 break;
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);
117 return (rbgn);
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
125 /* LINTED */
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)
131 break;
133 rbgn += rsize;
135 return (rbgn);
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.
143 inline static int
144 /* LINTED */
145 is_sym_deferred(ulong_t rbgn, ulong_t base, Rt_map *lmp, APlist **textrel,
146 Syminfo *sip, ulong_t sndx)
148 Syminfo *sipe;
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)
156 return (0);
158 /* LINTED */
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.
173 #if defined(__x86)
174 if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0)
175 (void) _elf_reloc_relative(rbgn, base, lmp, textrel, 1);
176 #endif
177 return (1);
179 return (0);
182 #endif /* _INLINE_RELOC_H */