1 /* $NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $ */
4 * Copyright (c) 2001 Wasabi Systems, Inc.
7 * Written by Frank van der Linden for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright 1996 John D. Polstra.
40 * Copyright 1996 Matt Thomas <matt@3am-software.com>
41 * All rights reserved.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by John Polstra.
54 * 4. The name of the author may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 #include <sys/cdefs.h>
71 __RCSID("$NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $");
74 #include <sys/types.h>
88 void _rtld_bind_start(void);
89 void _rtld_relocate_nonplt_self(Elf_Dyn
*, Elf_Addr
);
90 caddr_t
_rtld_bind(const Obj_Entry
*, Elf_Word
);
91 static inline int _rtld_relocate_plt_object(const Obj_Entry
*,
92 const Elf_Rela
*, Elf_Addr
*);
95 _rtld_setup_pltgot(const Obj_Entry
*obj
)
97 obj
->pltgot
[1] = (Elf_Addr
) obj
;
98 obj
->pltgot
[2] = (Elf_Addr
) &_rtld_bind_start
;
102 _rtld_relocate_nonplt_self(Elf_Dyn
*dynp
, Elf_Addr relocbase
)
104 const Elf_Rela
*rela
= 0, *relalim
;
108 for (; dynp
->d_tag
!= DT_NULL
; dynp
++) {
109 switch (dynp
->d_tag
) {
111 rela
= (const Elf_Rela
*)(relocbase
+ dynp
->d_un
.d_ptr
);
114 relasz
= dynp
->d_un
.d_val
;
119 * Assume only 64-bit relocations here, which should always
120 * be true for the dynamic linker.
122 relalim
= (const Elf_Rela
*)((const uint8_t *)rela
+ relasz
);
123 for (; rela
< relalim
; rela
++) {
124 where
= (Elf_Addr
*)(relocbase
+ rela
->r_offset
);
125 *where
= (Elf_Addr
)(relocbase
+ rela
->r_addend
);
130 _rtld_relocate_nonplt_objects(Obj_Entry
*obj
)
132 const Elf_Rela
*rela
;
133 const Elf_Sym
*def
= NULL
;
134 const Obj_Entry
*defobj
=NULL
;
136 for (rela
= obj
->rela
; rela
< obj
->relalim
; rela
++) {
141 unsigned long symnum
;
143 where64
= (Elf64_Addr
*)(obj
->relocbase
+ rela
->r_offset
);
144 where32
= (Elf32_Addr
*)where64
;
145 symnum
= ELF_R_SYM(rela
->r_info
);
147 switch (ELF_R_TYPE(rela
->r_info
)) {
151 case R_TYPE(32): /* word32 S + A, truncate */
152 case R_TYPE(32S
): /* word32 S + A, signed truncate */
153 case R_TYPE(GOT32
): /* word32 G + A (XXX can we see these?) */
154 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
157 tmp32
= (Elf32_Addr
)(u_long
)(defobj
->relocbase
+
158 def
->st_value
+ rela
->r_addend
);
160 if (*where32
!= tmp32
)
162 rdbg(("32/32S %s in %s --> %p in %s",
163 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
164 obj
->path
, (void *)(uintptr_t)*where32
,
167 case R_TYPE(64): /* word64 S + A */
168 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
171 tmp64
= (Elf64_Addr
)(defobj
->relocbase
+ def
->st_value
+
174 if (*where64
!= tmp64
)
176 rdbg(("64 %s in %s --> %p in %s",
177 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
178 obj
->path
, (void *)*where64
, defobj
->path
));
180 case R_TYPE(PC32
): /* word32 S + A - P */
181 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
184 tmp32
= (Elf32_Addr
)(u_long
)(defobj
->relocbase
+
185 def
->st_value
+ rela
->r_addend
-
186 (Elf64_Addr
)where64
);
187 if (*where32
!= tmp32
)
189 rdbg(("PC32 %s in %s --> %p in %s",
190 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
191 obj
->path
, (void *)(unsigned long)*where32
,
194 case R_TYPE(GLOB_DAT
): /* word64 S */
195 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
198 tmp64
= (Elf64_Addr
)(defobj
->relocbase
+ def
->st_value
);
200 if (*where64
!= tmp64
)
202 rdbg(("64 %s in %s --> %p in %s",
203 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
204 obj
->path
, (void *)*where64
, defobj
->path
));
206 case R_TYPE(RELATIVE
): /* word64 B + A */
207 tmp64
= (Elf64_Addr
)(obj
->relocbase
+ rela
->r_addend
);
208 if (*where64
!= tmp64
)
210 rdbg(("RELATIVE in %s --> %p", obj
->path
,
214 case R_TYPE(TPOFF64
):
215 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
219 if (!defobj
->tls_done
&&
220 _rtld_tls_offset_allocate(obj
))
223 *where64
= (Elf64_Addr
)(def
->st_value
-
224 defobj
->tlsoffset
+ rela
->r_addend
);
226 rdbg(("TPOFF64 %s in %s --> %p",
227 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
228 obj
->path
, (void *)*where64
));
232 case R_TYPE(DTPMOD64
):
233 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
237 *where64
= (Elf64_Addr
)defobj
->tlsindex
;
239 rdbg(("DTPMOD64 %s in %s --> %p",
240 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
241 obj
->path
, (void *)*where64
));
245 case R_TYPE(DTPOFF64
):
246 def
= _rtld_find_symdef(symnum
, obj
, &defobj
, false);
250 *where64
= (Elf64_Addr
)(def
->st_value
+ rela
->r_addend
);
252 rdbg(("DTPOFF64 %s in %s --> %p",
253 obj
->strtab
+ obj
->symtab
[symnum
].st_name
,
254 obj
->path
, (void *)*where64
));
263 rdbg(("sym = %lu, type = %lu, offset = %p, "
264 "addend = %p, contents = %p, symbol = %s",
265 symnum
, (u_long
)ELF_R_TYPE(rela
->r_info
),
266 (void *)rela
->r_offset
, (void *)rela
->r_addend
,
268 obj
->strtab
+ obj
->symtab
[symnum
].st_name
));
269 _rtld_error("%s: Unsupported relocation type %ld "
270 "in non-PLT relocations",
271 obj
->path
, (u_long
) ELF_R_TYPE(rela
->r_info
));
279 _rtld_relocate_plt_lazy(const Obj_Entry
*obj
)
281 const Elf_Rela
*rela
;
286 for (rela
= obj
->pltrela
; rela
< obj
->pltrelalim
; rela
++) {
287 Elf_Addr
*where
= (Elf_Addr
*)(obj
->relocbase
+ rela
->r_offset
);
289 assert(ELF_R_TYPE(rela
->r_info
) == R_TYPE(JUMP_SLOT
));
291 /* Just relocate the GOT slots pointing into the PLT */
292 *where
+= (Elf_Addr
)obj
->relocbase
;
293 rdbg(("fixup !main in %s --> %p", obj
->path
, (void *)*where
));
300 _rtld_relocate_plt_object(const Obj_Entry
*obj
, const Elf_Rela
*rela
, Elf_Addr
*tp
)
302 Elf_Addr
*where
= (Elf_Addr
*)(obj
->relocbase
+ rela
->r_offset
);
305 const Obj_Entry
*defobj
;
306 unsigned long info
= rela
->r_info
;
308 assert(ELF_R_TYPE(info
) == R_TYPE(JUMP_SLOT
));
310 def
= _rtld_find_plt_symdef(ELF_R_SYM(info
), obj
, &defobj
, tp
!= NULL
);
311 if (__predict_false(def
== NULL
))
313 if (__predict_false(def
== &_rtld_sym_zero
))
316 if (ELF_ST_TYPE(def
->st_info
) == STT_GNU_IFUNC
) {
319 new_value
= _rtld_resolve_ifunc(defobj
, def
);
321 new_value
= (Elf_Addr
)(defobj
->relocbase
+ def
->st_value
+
325 rdbg(("bind now/fixup in %s --> old=%p new=%p",
326 defobj
->strtab
+ def
->st_name
, (void *)*where
, (void *)new_value
));
327 if (*where
!= new_value
)
331 *tp
= new_value
- rela
->r_addend
;
337 _rtld_bind(const Obj_Entry
*obj
, Elf_Word reloff
)
339 const Elf_Rela
*rela
= obj
->pltrela
+ reloff
;
343 new_value
= 0; /* XXX GCC4 */
345 _rtld_shared_enter();
346 error
= _rtld_relocate_plt_object(obj
, rela
, &new_value
);
351 return (caddr_t
)new_value
;
355 _rtld_relocate_plt_objects(const Obj_Entry
*obj
)
357 const Elf_Rela
*rela
;
359 for (rela
= obj
->pltrela
; rela
< obj
->pltrelalim
; rela
++)
360 if (_rtld_relocate_plt_object(obj
, rela
, NULL
) < 0)