mdreloc.c revision 1.1 1 1.1 fvdl #include <sys/types.h>
2 1.1 fvdl #include <sys/mman.h>
3 1.1 fvdl #include <err.h>
4 1.1 fvdl #include <errno.h>
5 1.1 fvdl #include <fcntl.h>
6 1.1 fvdl #include <stdarg.h>
7 1.1 fvdl #include <stdio.h>
8 1.1 fvdl #include <stdlib.h>
9 1.1 fvdl #include <string.h>
10 1.1 fvdl #include <unistd.h>
11 1.1 fvdl #include <elf.h>
12 1.1 fvdl
13 1.1 fvdl #include "debug.h"
14 1.1 fvdl #include "rtld.h"
15 1.1 fvdl
16 1.1 fvdl extern Elf64_Addr _GLOBAL_OFFSET_TABLE_[];
17 1.1 fvdl
18 1.1 fvdl int
19 1.1 fvdl _rtld_relocate_nonplt_object(Obj_Entry *obj, const Elf_RelA *rela, bool dodebug)
20 1.1 fvdl {
21 1.1 fvdl Elf64_Addr *where64;
22 1.1 fvdl Elf32_Addr *where32;
23 1.1 fvdl const Elf_Sym *def;
24 1.1 fvdl const Obj_Entry *defobj;
25 1.1 fvdl Elf64_Addr tmp64;
26 1.1 fvdl Elf32_Addr tmp32;
27 1.1 fvdl
28 1.1 fvdl where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset);
29 1.1 fvdl where32 = (Elf32_Addr *)where64;
30 1.1 fvdl
31 1.1 fvdl switch (ELF_R_TYPE(rela->r_info)) {
32 1.1 fvdl
33 1.1 fvdl case R_TYPE(NONE):
34 1.1 fvdl break;
35 1.1 fvdl
36 1.1 fvdl case R_TYPE(32): /* word32 S + A, truncate */
37 1.1 fvdl case R_TYPE(32S): /* word32 S + A, signed truncate */
38 1.1 fvdl case R_TYPE(GOT32): /* word32 G + A (XXX can we see these?) */
39 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
40 1.1 fvdl &defobj, false);
41 1.1 fvdl if (def == NULL)
42 1.1 fvdl return -1;
43 1.1 fvdl tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + def->st_value +
44 1.1 fvdl rela->r_addend);
45 1.1 fvdl
46 1.1 fvdl if (*where32 != tmp32)
47 1.1 fvdl *where32 = tmp32;
48 1.1 fvdl rdbg(dodebug, ("32/32S %s in %s --> %p in %s",
49 1.1 fvdl defobj->strtab + def->st_name, obj->path,
50 1.1 fvdl (void *)(unsigned long)*where32, defobj->path));
51 1.1 fvdl break;
52 1.1 fvdl case R_TYPE(64): /* word64 S + A */
53 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
54 1.1 fvdl &defobj, false);
55 1.1 fvdl if (def == NULL)
56 1.1 fvdl return -1;
57 1.1 fvdl
58 1.1 fvdl tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value +
59 1.1 fvdl rela->r_addend);
60 1.1 fvdl
61 1.1 fvdl if (*where64 != tmp64)
62 1.1 fvdl *where64 = tmp64;
63 1.1 fvdl rdbg(dodebug, ("64 %s in %s --> %p in %s",
64 1.1 fvdl defobj->strtab + def->st_name, obj->path,
65 1.1 fvdl (void *)*where64, defobj->path));
66 1.1 fvdl break;
67 1.1 fvdl case R_TYPE(PC32): /* word32 S + A - P */
68 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
69 1.1 fvdl &defobj, false);
70 1.1 fvdl if (def == NULL)
71 1.1 fvdl return -1;
72 1.1 fvdl tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + def->st_value +
73 1.1 fvdl rela->r_addend - (Elf64_Addr)where64);
74 1.1 fvdl if (*where32 != tmp32)
75 1.1 fvdl *where32 = tmp32;
76 1.1 fvdl rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
77 1.1 fvdl defobj->strtab + def->st_name, obj->path,
78 1.1 fvdl (void *)(unsigned long)*where32, defobj->path));
79 1.1 fvdl break;
80 1.1 fvdl case R_TYPE(GLOB_DAT): /* word64 S */
81 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
82 1.1 fvdl &defobj, false);
83 1.1 fvdl if (def == NULL)
84 1.1 fvdl return -1;
85 1.1 fvdl
86 1.1 fvdl tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value);
87 1.1 fvdl
88 1.1 fvdl if (*where64 != tmp64)
89 1.1 fvdl *where64 = tmp64;
90 1.1 fvdl rdbg(dodebug, ("64 %s in %s --> %p in %s",
91 1.1 fvdl defobj->strtab + def->st_name, obj->path,
92 1.1 fvdl (void *)*where64, defobj->path));
93 1.1 fvdl break;
94 1.1 fvdl case R_TYPE(RELATIVE): /* word64 B + A */
95 1.1 fvdl tmp64 = (Elf64_Addr)(obj->relocbase + rela->r_addend);
96 1.1 fvdl if (*where64 != tmp64)
97 1.1 fvdl *where64 = tmp64;
98 1.1 fvdl rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
99 1.1 fvdl (void *)*where64));
100 1.1 fvdl break;
101 1.1 fvdl
102 1.1 fvdl case R_TYPE(COPY):
103 1.1 fvdl rdbg(dodebug, ("COPY"));
104 1.1 fvdl break;
105 1.1 fvdl
106 1.1 fvdl default:
107 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
108 1.1 fvdl &defobj, true);
109 1.1 fvdl rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
110 1.1 fvdl "addend = %p, contents = %p, symbol = %s",
111 1.1 fvdl (u_long)ELF_R_SYM(rela->r_info),
112 1.1 fvdl (u_long)ELF_R_TYPE(rela->r_info),
113 1.1 fvdl (void *)rela->r_offset, (void *)rela->r_addend,
114 1.1 fvdl (void *)*where64,
115 1.1 fvdl def ? defobj->strtab + def->st_name : "??"));
116 1.1 fvdl _rtld_error("%s: Unsupported relocation type %ld "
117 1.1 fvdl "in non-PLT relocations\n",
118 1.1 fvdl obj->path, (u_long) ELF_R_TYPE(rela->r_info));
119 1.1 fvdl return -1;
120 1.1 fvdl }
121 1.1 fvdl return 0;
122 1.1 fvdl }
123 1.1 fvdl
124 1.1 fvdl
125 1.1 fvdl
126 1.1 fvdl int
127 1.1 fvdl _rtld_relocate_plt_object(Obj_Entry *obj, const Elf_RelA *rela, caddr_t *addrp,
128 1.1 fvdl bool bind_now, bool dodebug)
129 1.1 fvdl {
130 1.1 fvdl Elf32_Addr *where = (Elf32_Addr *)(obj->relocbase + rela->r_offset);
131 1.1 fvdl Elf32_Addr new_value;
132 1.1 fvdl
133 1.1 fvdl /* Fully resolve procedure addresses now */
134 1.1 fvdl
135 1.1 fvdl if (bind_now || obj->pltgot == NULL) {
136 1.1 fvdl const Elf_Sym *def;
137 1.1 fvdl const Obj_Entry *defobj;
138 1.1 fvdl
139 1.1 fvdl assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT));
140 1.1 fvdl
141 1.1 fvdl def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
142 1.1 fvdl &defobj, true);
143 1.1 fvdl if (def == NULL)
144 1.1 fvdl return -1;
145 1.1 fvdl
146 1.1 fvdl new_value = (Elf32_Addr)(u_long)
147 1.1 fvdl (defobj->relocbase + def->st_value + rela->r_addend);
148 1.1 fvdl rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
149 1.1 fvdl (int)bind_now,
150 1.1 fvdl defobj->strtab + def->st_name,
151 1.1 fvdl (void *)(u_long)*where, (void *)(u_long)new_value));
152 1.1 fvdl } else {
153 1.1 fvdl if (!obj->mainprog) {
154 1.1 fvdl /* Just relocate the GOT slots pointing into the PLT */
155 1.1 fvdl new_value = *where + (Elf32_Addr)(u_long)
156 1.1 fvdl obj->relocbase;
157 1.1 fvdl rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
158 1.1 fvdl (void *)(unsigned long)*where));
159 1.1 fvdl } else {
160 1.1 fvdl return 0;
161 1.1 fvdl }
162 1.1 fvdl }
163 1.1 fvdl /*
164 1.1 fvdl * Since this page is probably copy-on-write, let's not write
165 1.1 fvdl * it unless we really really have to.
166 1.1 fvdl */
167 1.1 fvdl if (*where != new_value)
168 1.1 fvdl *where = new_value;
169 1.1 fvdl if (addrp != NULL)
170 1.1 fvdl *addrp = *(caddr_t *)(obj->relocbase + rela->r_offset) -
171 1.1 fvdl rela->r_addend;
172 1.1 fvdl return 0;
173 1.1 fvdl }
174