Annotation of src/libexec/ld.elf_so/reloc.c, Revision 1.97
1.97 ! pooka 1: /* $NetBSD: reloc.c,v 1.96 2008/07/29 16:27:01 matt Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright 1996 John D. Polstra.
5: * Copyright 1996 Matt Thomas <matt@3am-software.com>
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by John Polstra.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Dynamic linker for ELF.
36: *
37: * John Polstra <jdp@polstra.com>.
38: */
39:
1.85 skrll 40: #include <sys/cdefs.h>
41: #ifndef lint
1.97 ! pooka 42: __RCSID("$NetBSD: reloc.c,v 1.96 2008/07/29 16:27:01 matt Exp $");
1.85 skrll 43: #endif /* not lint */
44:
1.1 cgd 45: #include <err.h>
46: #include <errno.h>
47: #include <fcntl.h>
48: #include <stdarg.h>
49: #include <stdio.h>
50: #include <stdlib.h>
51: #include <string.h>
52: #include <unistd.h>
53: #include <sys/types.h>
54: #include <sys/mman.h>
55: #include <dirent.h>
56:
57: #include "debug.h"
58: #include "rtld.h"
59:
1.14 pk 60: #ifndef RTLD_INHIBIT_COPY_RELOCS
1.80 skrll 61: static int _rtld_do_copy_relocation(const Obj_Entry *, const Elf_Rela *);
1.16 christos 62:
1.1 cgd 63: static int
1.80 skrll 64: _rtld_do_copy_relocation(const Obj_Entry *dstobj, const Elf_Rela *rela)
1.1 cgd 65: {
1.11 christos 66: void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
67: const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
68: const char *name = dstobj->strtab + dstsym->st_name;
69: unsigned long hash = _rtld_elf_hash(name);
70: size_t size = dstsym->st_size;
71: const void *srcaddr;
1.37 matt 72: const Elf_Sym *srcsym = NULL;
1.11 christos 73: Obj_Entry *srcobj;
74:
75: for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
1.72 mycroft 76: if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL)
1.11 christos 77: break;
78:
79: if (srcobj == NULL) {
80: _rtld_error("Undefined symbol \"%s\" referenced from COPY"
81: " relocation in %s", name, dstobj->path);
1.14 pk 82: return (-1);
1.11 christos 83: }
84: srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value);
85: (void)memcpy(dstaddr, srcaddr, size);
1.84 petrov 86: rdbg(("COPY %s %s %s --> src=%p dst=%p size %ld",
1.11 christos 87: dstobj->path, srcobj->path, name, (void *)srcaddr,
1.84 petrov 88: (void *)dstaddr, (long)size));
1.14 pk 89: return (0);
1.1 cgd 90: }
1.14 pk 91: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.11 christos 92:
93:
1.1 cgd 94: /*
95: * Process the special R_xxx_COPY relocations in the main program. These
96: * copy data from a shared object into a region in the main program's BSS
97: * segment.
98: *
99: * Returns 0 on success, -1 on failure.
100: */
101: int
1.80 skrll 102: _rtld_do_copy_relocations(const Obj_Entry *dstobj)
1.1 cgd 103: {
1.14 pk 104: #ifndef RTLD_INHIBIT_COPY_RELOCS
105:
106: /* COPY relocations are invalid elsewhere */
1.64 mycroft 107: assert(!dstobj->isdynamic);
1.1 cgd 108:
1.11 christos 109: if (dstobj->rel != NULL) {
110: const Elf_Rel *rel;
111: for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) {
112: if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) {
1.35 kleink 113: Elf_Rela ourrela;
1.11 christos 114: ourrela.r_info = rel->r_info;
115: ourrela.r_offset = rel->r_offset;
116: ourrela.r_addend = 0;
117: if (_rtld_do_copy_relocation(dstobj,
1.66 mycroft 118: &ourrela) < 0)
1.14 pk 119: return (-1);
1.11 christos 120: }
121: }
122: }
123: if (dstobj->rela != NULL) {
1.35 kleink 124: const Elf_Rela *rela;
1.11 christos 125: for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) {
126: if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) {
1.66 mycroft 127: if (_rtld_do_copy_relocation(dstobj, rela) < 0)
1.14 pk 128: return (-1);
1.11 christos 129: }
130: }
1.1 cgd 131: }
1.14 pk 132: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.1 cgd 133:
1.14 pk 134: return (0);
1.1 cgd 135: }
1.9 pk 136:
1.1 cgd 137: /*
138: * Relocate newly-loaded shared objects. The argument is a pointer to
139: * the Obj_Entry for the first such object. All objects from the first
140: * to the end of the list of objects are relocated. Returns 0 on success,
141: * or -1 on failure.
142: */
143: int
1.80 skrll 144: _rtld_relocate_objects(Obj_Entry *first, bool bind_now)
1.1 cgd 145: {
1.16 christos 146: Obj_Entry *obj;
1.77 mycroft 147: int ok = 1;
1.1 cgd 148:
1.11 christos 149: for (obj = first; obj != NULL; obj = obj->next) {
1.16 christos 150: if (obj->nbuckets == 0 || obj->nchains == 0 ||
151: obj->buckets == NULL || obj->symtab == NULL ||
152: obj->strtab == NULL) {
1.11 christos 153: _rtld_error("%s: Shared object has no run-time"
154: " symbol table", obj->path);
155: return -1;
156: }
1.66 mycroft 157: rdbg((" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)",
1.11 christos 158: obj->path,
159: (long)(obj->rellim - obj->rel),
160: (long)(obj->relalim - obj->rela),
161: (long)(obj->pltrellim - obj->pltrel),
1.16 christos 162: (long)(obj->pltrelalim - obj->pltrela)));
1.11 christos 163:
164: if (obj->textrel) {
165: /*
166: * There are relocations to the write-protected text
167: * segment.
168: */
169: if (mprotect(obj->mapbase, obj->textsize,
170: PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
171: _rtld_error("%s: Cannot write-enable text "
172: "segment: %s", obj->path, xstrerror(errno));
173: return -1;
174: }
175: }
1.71 mycroft 176: dbg(("doing non-PLT relocations"));
1.76 junyoung 177: if (_rtld_relocate_nonplt_objects(obj) < 0)
1.77 mycroft 178: ok = 0;
1.11 christos 179: if (obj->textrel) { /* Re-protected the text segment. */
180: if (mprotect(obj->mapbase, obj->textsize,
181: PROT_READ | PROT_EXEC) == -1) {
182: _rtld_error("%s: Cannot write-protect text "
183: "segment: %s", obj->path, xstrerror(errno));
184: return -1;
185: }
186: }
1.71 mycroft 187: dbg(("doing lazy PLT binding"));
1.76 junyoung 188: if (_rtld_relocate_plt_lazy(obj) < 0)
1.77 mycroft 189: ok = 0;
1.83 skrll 190: #if defined(__hppa__)
191: bind_now = 1;
192: #endif
1.82 skrll 193: if (bind_now) {
194: dbg(("doing immediate PLT binding"));
1.76 junyoung 195: if (_rtld_relocate_plt_objects(obj) < 0)
1.77 mycroft 196: ok = 0;
1.82 skrll 197: }
1.77 mycroft 198: if (!ok)
199: return -1;
200:
1.96 matt 201: (void)dlerror(); /* clear any errors since all is good */
1.11 christos 202:
203: /* Set some sanity-checking numbers in the Obj_Entry. */
204: obj->magic = RTLD_MAGIC;
205: obj->version = RTLD_VERSION;
206:
207: /* Fill in the dynamic linker entry points. */
1.81 skrll 208: obj->dlopen = dlopen;
209: obj->dlsym = dlsym;
210: obj->dlerror = dlerror;
211: obj->dlclose = dlclose;
212: obj->dladdr = dladdr;
1.97 ! pooka 213: obj->dlinfo = dlinfo;
1.1 cgd 214:
1.71 mycroft 215: dbg(("fixing up PLTGOT"));
1.11 christos 216: /* Set the special PLTGOT entries. */
1.53 mycroft 217: if (obj->pltgot != NULL)
218: _rtld_setup_pltgot(obj);
1.1 cgd 219: }
220:
1.11 christos 221: return 0;
1.1 cgd 222: }
CVSweb <webmaster@jp.NetBSD.org>