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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
30 #include <krtld/reloc.h>
35 static const char *unknown
= 0; /* Stash MSG_INTL(MSG_STR_UNKNOWN) */
38 * Process all relocation records. A new `Reloc' structure is allocated to
39 * cache the processing decisions deduced, and these will be applied during
41 * A count of the number of null relocations (i.e., relocations that will be
42 * fixed and whoes records will be nulled out), data and function relocations
43 * is maintained. This allows the relocation records themselves to be
44 * rearranged (localized) later if necessary. Note that the number of function
45 * relocations, although coounted, shouldn't differ from the original file,
46 * the index of a .plt must be maintained to the index of its relocation record
47 * within the associated relocation section.
49 * The intention behind this file is to maintain as much relocation logic as
50 * possible in a generic form.
53 count_reloc(Cache
*cache
, Cache
*_cache
, Rt_map
*lmp
, int flags
, Addr addr
,
54 Xword
*null
, Xword
*data
, Xword
*func
, Alist
*nodirect
)
66 * Determine the number of relocation entries we'll be dealing with.
68 shdr
= _cache
->c_shdr
;
69 rel
= (Rel
*)_cache
->c_data
->d_buf
;
70 ent
= shdr
->sh_entsize
;
71 cnt
= shdr
->sh_size
/ ent
;
74 * Allocate a relocation structure for this relocation section.
76 if ((reloc
= calloc(cnt
, sizeof (Reloc
))) == 0)
78 _cache
->c_info
= (void *)reloc
;
81 * Determine the relocations associated symbol and string table.
83 __cache
= &cache
[shdr
->sh_link
];
84 syms
= (Sym
*)__cache
->c_data
->d_buf
;
85 shdr
= __cache
->c_shdr
;
86 __cache
= &cache
[shdr
->sh_link
];
87 strs
= (const char *)__cache
->c_data
->d_buf
;
90 * Loop through the relocation table.
92 for (_cnt
= 0; _cnt
< cnt
; _cnt
++, reloc
++,
93 rel
= (Rel
*)((uintptr_t)rel
+ ent
)) {
96 uchar_t type
= (uchar_t
)ELF_R_TYPE(rel
->r_info
, M_MACH
);
98 ulong_t offset
= rel
->r_offset
+ addr
;
101 ulong_t rsymndx
= ELF_R_SYM(rel
->r_info
);
105 Sym
*_sym
, *sym
= (syms
+ rsymndx
);
107 if (type
== M_R_JMP_SLOT
)
108 reloc
->r_pltndx
= ++pltndx
;
111 * Analyze the case where no relocations are to be applied.
113 if ((flags
& RTLD_REL_ALL
) == 0) {
115 * Don't apply any relocations to the new image but
116 * insure their offsets are incremented to reflect any
119 reloc
->r_flags
= FLG_R_INC
;
122 * Undo any relocations that might have already been
123 * applied to the memory image.
125 if (flags
& RTLD_MEMORY
) {
126 reloc
->r_flags
|= FLG_R_UNDO
;
129 * If a copy relocation is involved we'll need
130 * to know the size of the copy.
132 if (type
== M_R_COPY
)
133 reloc
->r_size
= sym
->st_size
;
139 * Save the objects new address.
141 reloc
->r_value
= addr
;
143 if (type
== M_R_JMP_SLOT
)
151 * Determine the symbol binding of the relocation. Don't assume
152 * that relative relocations are simply M_R_RELATIVE. Although
153 * a pic generated shared object can normally be viewed as
154 * having relative and non-relative relocations, a non-pic
155 * shared object will contain a number of relocations against
156 * local symbols (normally sections). If a relocation is
157 * against a local symbol it qualifies as a relative relocation.
159 if ((type
== M_R_RELATIVE
) || (type
== M_R_NONE
) ||
160 (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
))
166 * Analyze the case where only relative relocations are to be
169 if ((flags
& RTLD_REL_ALL
) == RTLD_REL_RELATIVE
) {
170 if (flags
& RTLD_MEMORY
) {
171 if (bind
== STB_LOCAL
) {
173 * Save the relative relocations from
174 * the memory image. The data itself
175 * might already have been relocated,
176 * thus clear the relocation record so
177 * that it will not be performed again.
179 reloc
->r_flags
= FLG_R_CLR
;
183 * Any non-relative relocation must be
184 * undone, and the relocation records
185 * offset updated to any new fixed
189 (FLG_R_UNDO
| FLG_R_INC
);
190 reloc
->r_value
= addr
;
191 if (type
== M_R_JMP_SLOT
)
197 if (bind
== STB_LOCAL
) {
199 * Apply relative relocation to the
200 * file image. Clear the relocation
201 * record so that it will not be
205 (FLG_R_APPLY
| FLG_R_CLR
);
206 reloc
->r_value
= addr
;
207 if (IS_PC_RELATIVE(type
))
208 reloc
->r_value
-= offset
;
212 MSG_INTL(MSG_STR_UNKNOWN
);
213 reloc
->r_name
= unknown
;
217 * Any non-relative relocation should be
218 * left alone, but its offset should be
219 * updated to any new fixed address.
221 reloc
->r_flags
= FLG_R_INC
;
222 reloc
->r_value
= addr
;
223 if (type
== M_R_JMP_SLOT
)
233 * Analyze the case where more than just relative relocations
236 if (bind
== STB_LOCAL
) {
237 if (flags
& RTLD_MEMORY
) {
239 * Save the relative relocations from the memory
240 * image. The data itself has already been
241 * relocated, thus clear the relocation record
242 * so that it will not be performed again.
244 reloc
->r_flags
= FLG_R_CLR
;
247 * Apply relative relocation to the file image.
248 * Clear the relocation record so that it will
249 * not be performed again.
251 reloc
->r_flags
= (FLG_R_APPLY
| FLG_R_CLR
);
252 reloc
->r_value
= addr
;
253 if (IS_PC_RELATIVE(type
))
254 reloc
->r_value
-= offset
;
257 unknown
= MSG_INTL(MSG_STR_UNKNOWN
);
258 reloc
->r_name
= unknown
;
265 * At this point we're dealing with a non-relative relocation
266 * that requires the symbol definition.
268 name
= strs
+ sym
->st_name
;
271 * Find the symbol. As the object being investigated is already
272 * a part of this process, the symbol lookup will likely
273 * succeed. However, because of lazy binding, there is still
274 * the possibility of a dangling .plt relocation. dldump()
275 * users might be encouraged to set LD_FLAGS=loadavail (crle(1)
276 * does this for them).
278 * Initialize the symbol lookup, and symbol result, data
281 SLOOKUP_INIT(sl
, name
, lmp
, LIST(lmp
)->lm_head
, ld_entry_cnt
,
282 0, rsymndx
, sym
, type
, LKUP_STDRELOC
);
283 SRESULT_INIT(sr
, name
);
287 if (lookup_sym(&sl
, &sr
, &binfo
, NULL
)) {
292 * Determine from the various relocation requirements
293 * whether this binding is appropriate. If we're called
294 * from crle(1), RTLD_CONFSET is set, then only inspect
295 * objects selected from the configuration file
296 * (FL1_RT_CONFSET was set during load()).
298 if (!(flags
& RTLD_CONFSET
) ||
299 (FLAGS1(_lmp
) & FL1_RT_CONFSET
)) {
300 if (((flags
& RTLD_REL_ALL
) == RTLD_REL_ALL
) ||
301 ((flags
& RTLD_REL_EXEC
) &&
302 (FLAGS(_lmp
) & FLG_RT_ISMAIN
)) ||
303 ((flags
& RTLD_REL_DEPENDS
) &&
304 (!(FLAGS(_lmp
) & FLG_RT_ISMAIN
))) ||
305 ((flags
& RTLD_REL_PRELOAD
) &&
306 (FLAGS(_lmp
) & FLG_RT_PRELOAD
)) ||
307 ((flags
& RTLD_REL_SELF
) &&
315 * If this symbol is explicitly defined
316 * as nodirect, don't allow any local
319 for (ALIST_TRAVERSE(nodirect
, idx
,
321 if (*ndx
== rsymndx
) {
330 * If this is a weak reference and we've been asked to
331 * bind unresolved weak references consider ourself
332 * bound. This category is typically set by clre(1) for
333 * an application cache.
335 if ((ELF_ST_BIND(_sym
->st_info
) == STB_WEAK
) &&
336 (_sym
->st_shndx
== SHN_UNDEF
) &&
337 (flags
& RTLD_REL_WEAK
))
341 if (flags
& RTLD_MEMORY
) {
344 * We know that all data relocations will have
345 * been performed at process startup thus clear
346 * the relocation record so that it will not be
347 * performed again. However, we don't know what
348 * function relocations have been performed
349 * because of lazy binding - regardless, we can
350 * leave all the function relocation records in
351 * place, because if the function has already
352 * been bound the record won't be referenced
353 * anyway. In the case of using LD_BIND_NOW,
354 * a function may be bound twice - so what.
356 if (type
== M_R_JMP_SLOT
) {
357 reloc
->r_flags
= FLG_R_INC
;
360 if (type
!= M_R_COPY
)
361 reloc
->r_flags
= FLG_R_CLR
;
366 * Clear any unrequired relocation.
368 reloc
->r_flags
= FLG_R_UNDO
| FLG_R_INC
;
369 reloc
->r_value
= addr
;
370 if (type
== M_R_JMP_SLOT
)
378 * Apply the global relocation to the file
379 * image. Clear the relocation record so that
380 * it will not be performed again.
386 reloc
->r_value
= sym
->st_value
;
387 if (IS_PC_RELATIVE(type
))
388 reloc
->r_value
-= offset
;
389 if ((!(FLAGS(_lmp
) & FLG_RT_FIXED
)) &&
390 (sym
->st_shndx
!= SHN_ABS
))
391 reloc
->r_value
+= ADDR(_lmp
);
392 reloc
->r_size
= sym
->st_size
;
395 reloc
->r_flags
= FLG_R_APPLY
| FLG_R_CLR
;
396 reloc
->r_name
= name
;
397 if (type
== M_R_JMP_SLOT
)
403 * Do not apply any unrequired relocations.
405 reloc
->r_flags
= FLG_R_INC
;
406 reloc
->r_value
= addr
;
407 if (type
== M_R_JMP_SLOT
)
419 * Perform any relocation updates to the new image using the information from
420 * the `Reloc' structure constructed during count_reloc().
423 update_reloc(Cache
*ocache
, Cache
*icache
, Cache
*_icache
, const char *name
,
424 Rt_map
*lmp
, Rel
**null
, Rel
**data
, Rel
**func
)
429 Xword ent
, cnt
, _cnt
;
430 Cache
*orcache
, *ircache
= 0;
434 * Set up to read the output relocation table.
436 shdr
= _icache
->c_shdr
;
437 rel
= (Rel
*)_icache
->c_data
->d_buf
;
438 reloc
= (Reloc
*)_icache
->c_info
;
439 ent
= shdr
->sh_entsize
;
440 cnt
= shdr
->sh_size
/ ent
;
443 * Loop through the relocation table.
445 for (_cnt
= 0; _cnt
< cnt
; _cnt
++, reloc
++,
446 rel
= (Rel
*)((uintptr_t)rel
+ ent
)) {
447 uchar_t
*iaddr
, *oaddr
;
449 uchar_t type
= (uchar_t
)ELF_R_TYPE(rel
->r_info
, M_MACH
);
453 * Ignore null relocations (these may have been created from a
454 * previous dldump() of this image).
456 if (type
== M_R_NONE
) {
462 * Determine the section being relocated if we haven't already
463 * done so (we may have had to skip over some null relocation to
464 * get to the first valid offset). The System V ABI states that
465 * a relocation sections sh_info field indicates the section
466 * that must be relocated. However, on Intel it seems that the
467 * .rel.plt sh_info records the section index of the .plt, when
468 * in fact it's the .got that gets relocated. In addition we
469 * now create combined relocation sections with -zcomreloc. To
470 * generically be able to cope with these anomalies, search for
471 * the appropriate section to be relocated by comparing the
472 * offset of the first relocation record against each sections
476 if ((ircache
== (Cache
*)0) || (rel
->r_offset
< bgn
) ||
477 (rel
->r_offset
> end
)) {
481 for (ndx
= 1; _icache
->c_flags
!= FLG_C_END
; ndx
++,
484 shdr
= _icache
->c_shdr
;
486 end
= bgn
+ shdr
->sh_size
;
488 if ((rel
->r_offset
>= bgn
) &&
489 (rel
->r_offset
<= end
))
492 ircache
= &icache
[ndx
];
493 orcache
= &ocache
[ndx
];
498 * Determine the relocation location of both the input and
499 * output data. Take into account that an input section may be
500 * NOBITS (ppc .plt for example).
502 off
= rel
->r_offset
- ircache
->c_shdr
->sh_addr
;
503 if (ircache
->c_data
->d_buf
)
504 iaddr
= (uchar_t
*)ircache
->c_data
->d_buf
+ off
;
507 oaddr
= (uchar_t
*)orcache
->c_data
->d_buf
+ off
;
510 * Apply the relocation to the new output image. Any base
511 * address, or symbol value, will have been saved in the reloc
512 * structure during count_reloc().
514 if (reloc
->r_flags
& FLG_R_APPLY
)
515 apply_reloc(rel
, reloc
, name
, oaddr
, lmp
);
518 * Undo any relocation that might already been applied to the
519 * memory image by the runtime linker. Using the original
520 * file, determine the relocation offset original value and
521 * restore the new image to that value.
523 if ((reloc
->r_flags
& FLG_R_UNDO
) &&
524 (FLAGS(lmp
) & FLG_RT_RELOCED
))
525 undo_reloc(rel
, oaddr
, iaddr
, reloc
);
528 * If a relocation has been applied then the relocation record
529 * should be cleared so that the relocation isn't applied again
530 * when the new image is used.
532 if (reloc
->r_flags
& FLG_R_CLR
) {
533 if (type
== M_R_JMP_SLOT
) {
535 *func
= (Rel
*)((uintptr_t)*func
+ ent
);
538 *null
= (Rel
*)((uintptr_t)*null
+ ent
);
543 * If a relocation isn't applied, update the relocation record
544 * to take into account the new address of the image.
546 if (reloc
->r_flags
& FLG_R_INC
) {
547 if (type
== M_R_JMP_SLOT
) {
548 inc_reloc(*func
, rel
, reloc
, oaddr
, iaddr
);
549 *func
= (Rel
*)((uintptr_t)*func
+ ent
);
551 inc_reloc(*data
, rel
, reloc
, oaddr
, iaddr
);
552 *data
= (Rel
*)((uintptr_t)*data
+ ent
);