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