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