mdreloc.c revision 1.11 1 /* $NetBSD: mdreloc.c,v 1.11 2002/09/12 20:21:02 mycroft Exp $ */
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5
6 #include "debug.h"
7 #include "rtld.h"
8
9 void _rtld_bind_start(void);
10
11 void
12 _rtld_setup_pltgot(const Obj_Entry *obj)
13 {
14 obj->pltgot[1] = (Elf_Addr) obj;
15 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
16 }
17
18 int
19 _rtld_relocate_nonplt_objects(obj, self, dodebug)
20 const Obj_Entry *obj;
21 bool self;
22 bool dodebug;
23 {
24 const Elf_Rela *rela;
25
26 for (rela = obj->rela; rela < obj->relalim; rela++) {
27 Elf_Addr *where;
28 const Elf_Sym *def;
29 const Obj_Entry *defobj;
30 Elf_Addr tmp;
31 unsigned long symnum;
32
33 where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
34 symnum = ELF_R_SYM(rela->r_info);
35
36 switch (ELF_R_TYPE(rela->r_info)) {
37 case R_TYPE(NONE):
38 break;
39
40 case R_TYPE(32): /* word32 S + A */
41 case R_TYPE(GLOB_DAT): /* word32 S + A */
42 def = _rtld_find_symdef(symnum, obj, &defobj, false);
43 if (def == NULL)
44 return -1;
45
46 tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
47 rela->r_addend);
48
49 if (*where != tmp)
50 *where = tmp;
51 rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
52 obj->strtab + obj->symtab[symnum].st_name,
53 obj->path, (void *)*where, defobj->path));
54 break;
55
56 case R_TYPE(RELATIVE): /* word32 B + A */
57 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
58 if (*where != tmp)
59 *where = tmp;
60 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
61 (void *)*where));
62 break;
63
64 case R_TYPE(COPY):
65 /*
66 * These are deferred until all other relocations have
67 * been done. All we do here is make sure that the
68 * COPY relocation is not in a shared library. They
69 * are allowed only in executable files.
70 */
71 if (obj->isdynamic) {
72 _rtld_error(
73 "%s: Unexpected R_COPY relocation in shared library",
74 obj->path);
75 return -1;
76 }
77 rdbg(dodebug, ("COPY (avoid in main)"));
78 break;
79
80 default:
81 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
82 "addend = %p, contents = %p, symbol = %s",
83 symnum, (u_long)ELF_R_TYPE(rela->r_info),
84 (void *)rela->r_offset, (void *)rela->r_addend,
85 (void *)*where,
86 obj->strtab + obj->symtab[symnum].st_name));
87 _rtld_error("%s: Unsupported relocation type %ld "
88 "in non-PLT relocations\n",
89 obj->path, (u_long) ELF_R_TYPE(rela->r_info));
90 return -1;
91 }
92 }
93 return 0;
94 }
95
96 int
97 _rtld_relocate_plt_lazy(obj, dodebug)
98 const Obj_Entry *obj;
99 bool dodebug;
100 {
101 const Elf_Rela *rela;
102
103 if (!obj->isdynamic)
104 return 0;
105
106 for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
107 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
108
109 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
110
111 /* Just relocate the GOT slots pointing into the PLT */
112 *where += (Elf_Addr)obj->relocbase;
113 rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
114 (void *)*where));
115 }
116
117 return 0;
118 }
119
120 int
121 _rtld_relocate_plt_object(obj, rela, addrp, dodebug)
122 const Obj_Entry *obj;
123 const Elf_Rela *rela;
124 caddr_t *addrp;
125 bool dodebug;
126 {
127 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
128 Elf_Addr new_value;
129 const Elf_Sym *def;
130 const Obj_Entry *defobj;
131
132 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
133
134 def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
135 if (def == NULL)
136 return -1;
137
138 new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
139 rela->r_addend);
140 rdbg(dodebug, ("bind now/fixup in %s --> old=%p new=%p",
141 defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
142 if (*where != new_value)
143 *where = new_value;
144
145 *addrp = (caddr_t)(new_value - rela->r_addend);
146 return 0;
147 }
148