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