mdreloc.c revision 1.3 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
27 where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
28
29 switch (ELF_R_TYPE(rela->r_info)) {
30 case R_TYPE(NONE):
31 break;
32
33 #if 1 /* XXX should not occur */
34 case R_TYPE(GOT32):
35 def = _rtld_find_symdef(rela->r_info, obj, &defobj,
36 false);
37 if (def == NULL)
38 return -1;
39
40 tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
41 rela->r_addend);
42 if (*where != tmp)
43 *where = tmp;
44 rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
45 defobj->strtab + def->st_name, obj->path,
46 (void *)*where, defobj->path));
47 break;
48
49 case R_TYPE(REL32):
50 def = _rtld_find_symdef(rela->r_info, obj, &defobj,
51 false);
52 if (def == NULL)
53 return -1;
54
55 *where += (Elf_Addr)(defobj->relocbase + def->st_value +
56 rela->r_addend) - (Elf_Addr)where;
57 rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
58 defobj->strtab + def->st_name, obj->path,
59 (void *)*where, defobj->path));
60 break;
61 #endif
62
63 case R_TYPE(DIR32):
64 def = _rtld_find_symdef(rela->r_info, obj, &defobj,
65 false);
66 if (def == NULL)
67 return -1;
68
69 *where += (Elf_Addr)(defobj->relocbase + def->st_value +
70 rela->r_addend);
71 rdbg(dodebug, ("32 %s in %s --> %p in %s",
72 defobj->strtab + def->st_name, obj->path,
73 (void *)*where, defobj->path));
74 break;
75
76 case R_TYPE(GLOB_DAT):
77 def = _rtld_find_symdef(rela->r_info, obj, &defobj,
78 false);
79 if (def == NULL)
80 return -1;
81
82 tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
83 rela->r_addend;
84 if (*where != tmp)
85 *where = tmp;
86 rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
87 defobj->strtab + def->st_name, obj->path,
88 (void *)*where, defobj->path));
89 break;
90
91 case R_TYPE(RELATIVE):
92 if (rela->r_addend)
93 *where = (Elf_Addr)obj->relocbase + rela->r_addend;
94 else
95 *where += (Elf_Addr)obj->relocbase;
96 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
97 (void *)*where));
98 break;
99
100 case R_TYPE(COPY):
101 /*
102 * These are deferred until all other relocations have
103 * been done. All we do here is make sure that the
104 * COPY relocation is not in a shared library. They
105 * are allowed only in executable files.
106 */
107 if (!obj->mainprog) {
108 _rtld_error(
109 "%s: Unexpected R_COPY relocation in shared library",
110 obj->path);
111 return -1;
112 }
113 rdbg(dodebug, ("COPY (avoid in main)"));
114 break;
115
116 default:
117 def = _rtld_find_symdef(rela->r_info, obj, &defobj,
118 true);
119 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
120 "addend = %p, contents = %p, symbol = %s",
121 (u_long)ELF_R_SYM(rela->r_info),
122 (u_long)ELF_R_TYPE(rela->r_info),
123 (void *)rela->r_offset, (void *)rela->r_addend,
124 (void *)*where,
125 def ? defobj->strtab + def->st_name : "??"));
126 _rtld_error("%s: Unsupported relocation type %ld "
127 "in non-PLT relocations\n",
128 obj->path, (u_long) ELF_R_TYPE(rela->r_info));
129 return -1;
130 }
131 }
132 return 0;
133 }
134