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(PC24): { /* word32 S - P + A */
32 Elf32_Sword addend;
33
34 /*
35 * Extract addend and sign-extend if needed.
36 */
37 addend = *where;
38 if (addend & 0x00800000)
39 addend |= 0xff000000;
40
41 def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
42 if (def == NULL)
43 return -1;
44 tmp = (Elf_Addr)obj->relocbase + def->st_value
45 - (Elf_Addr)where + (addend << 2);
46 if ((tmp & 0xfe000000) != 0xfe000000 &&
47 (tmp & 0xfe000000) != 0) {
48 _rtld_error(
49 "%s: R_ARM_PC24 relocation @ %p to %s failed "
50 "(displacement %ld (%#lx) out of range)",
51 obj->path, where, defobj->strtab + def->st_name,
52 (long) tmp, (long) tmp);
53 return -1;
54 }
55 tmp >>= 2;
56 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
57 rdbg(dodebug, ("PC24 %s in %s --> %p @ %p in %s",
58 defobj->strtab + def->st_name, obj->path,
59 (void *)*where, where, defobj->path));
60 break;
61 }
62 #endif
63
64 case R_TYPE(ABS32): /* word32 B + S + A */
65 def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
66 if (def == NULL)
67 return -1;
68 *where += (Elf_Addr)defobj->relocbase + def->st_value;
69 rdbg(dodebug, ("ABS32 %s in %s --> %p @ %p in %s",
70 defobj->strtab + def->st_name, obj->path,
71 (void *)*where, where, defobj->path));
72 break;
73
74 case R_TYPE(GLOB_DAT): /* word32 B + S */
75 def = _rtld_find_symdef(rela->r_info, obj, &defobj, false);
76 if (def == NULL)
77 return -1;
78 *where = (Elf_Addr)(defobj->relocbase + def->st_value);
79 rdbg(dodebug, ("GLOB_DAT %s in %s --> %p @ %p in %s",
80 defobj->strtab + def->st_name, obj->path,
81 (void *)*where, where, defobj->path));
82 break;
83
84 case R_TYPE(RELATIVE): /* word32 B + A */
85 *where += (Elf_Addr)obj->relocbase;
86 rdbg(dodebug, ("RELATIVE in %s --> %p @ %p", obj->path,
87 (void *)*where, where));
88 break;
89
90 case R_TYPE(COPY):
91 /*
92 * These are deferred until all other relocations have
93 * been done. All we do here is make sure that the COPY
94 * relocation is not in a shared library. They are allowed
95 * only in executable files.
96 */
97 if (!obj->mainprog) {
98 _rtld_error(
99 "%s: Unexpected R_COPY relocation in shared library",
100 obj->path);
101 return -1;
102 }
103 rdbg(dodebug, ("COPY (avoid in main)"));
104 break;
105
106 default:
107 def = _rtld_find_symdef(rela->r_info, obj, &defobj, true);
108 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
109 "addend = %p, contents = %p, symbol = %s",
110 (u_long)ELF_R_SYM(rela->r_info),
111 (u_long)ELF_R_TYPE(rela->r_info),
112 (void *)rela->r_offset, (void *)rela->r_addend,
113 (void *)*where,
114 def ? defobj->strtab + def->st_name : "??"));
115 _rtld_error("%s: Unsupported relocation type %ld "
116 "in non-PLT relocations\n",
117 obj->path, (u_long) ELF_R_TYPE(rela->r_info));
118 return -1;
119 }
120 return 0;
121 }
122