mdreloc.c revision 1.10 1 /* $NetBSD: mdreloc.c,v 1.10 2002/09/11 14:19:31 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 case R_TYPE(32): /* word32 S + A */
39 case R_TYPE(GLOB_DAT): /* word32 S + A */
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);
46
47 if (*where != tmp)
48 *where = tmp;
49 rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
50 obj->strtab + obj->symtab[symnum].st_name,
51 obj->path, (void *)*where, defobj->path));
52 break;
53
54 case R_TYPE(RELATIVE): /* word32 B + A */
55 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
56 if (*where != tmp)
57 *where = tmp;
58 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
59 (void *)*where));
60 break;
61
62 case R_TYPE(COPY):
63 /*
64 * These are deferred until all other relocations have
65 * been done. All we do here is make sure that the
66 * COPY relocation is not in a shared library. They
67 * are allowed only in executable files.
68 */
69 if (obj->isdynamic) {
70 _rtld_error(
71 "%s: Unexpected R_COPY relocation in shared library",
72 obj->path);
73 return -1;
74 }
75 rdbg(dodebug, ("COPY (avoid in main)"));
76 break;
77
78 default:
79 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
80 "addend = %p, contents = %p, symbol = %s",
81 symnum, (u_long)ELF_R_TYPE(rela->r_info),
82 (void *)rela->r_offset, (void *)rela->r_addend,
83 (void *)*where,
84 obj->strtab + obj->symtab[symnum].st_name));
85 _rtld_error("%s: Unsupported relocation type %ld "
86 "in non-PLT relocations\n",
87 obj->path, (u_long) ELF_R_TYPE(rela->r_info));
88 return -1;
89 }
90 }
91 return 0;
92 }
93
94 int
95 _rtld_relocate_plt_lazy(obj, dodebug)
96 const Obj_Entry *obj;
97 bool dodebug;
98 {
99 const Elf_Rela *rela;
100
101 if (!obj->isdynamic)
102 return 0;
103
104 for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) {
105 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
106
107 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
108
109 /* Just relocate the GOT slots pointing into the PLT */
110 *where += (Elf_Addr)obj->relocbase;
111 rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
112 (void *)*where));
113 }
114
115 return 0;
116 }
117
118 int
119 _rtld_relocate_plt_object(obj, rela, addrp, dodebug)
120 const Obj_Entry *obj;
121 const Elf_Rela *rela;
122 caddr_t *addrp;
123 bool dodebug;
124 {
125 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
126 Elf_Addr new_value;
127 const Elf_Sym *def;
128 const Obj_Entry *defobj;
129
130 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
131
132 def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
133 if (def == NULL)
134 return -1;
135
136 new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
137 rela->r_addend);
138 rdbg(dodebug, ("bind now/fixup in %s --> old=%p new=%p",
139 defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
140 if (*where != new_value)
141 *where = new_value;
142
143 *addrp = (caddr_t)(new_value - rela->r_addend);
144 return 0;
145 }
146