1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <libintl.h>
22: #include <stdlib.h>
23: #include <unistd.h>
24: #include <ldsodefs.h>
25: #include <sys/mman.h>
26: #include <sys/param.h>
27: #include <sys/types.h>
28: #include "dynamic-link.h"
29:
30:
31: #ifdef SHARED
32: # define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
33: #else
34: # define bump_num_cache_relocations() ((void) 0)
35: #endif
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46: void
47: internal_function __attribute_noinline__
48: _dl_allocate_static_tls (struct link_map *map)
49: {
50:
51: if (map->l_tls_align > GL(dl_tls_static_align))
52: {
53: fail:
54: _dl_signal_error (0, map->l_name, NULL, N_("\
55: cannot allocate memory in static TLS block"));
56: }
57:
58: #if TLS_TCB_AT_TP
59: size_t freebytes;
60: size_t n;
61: size_t blsize;
62:
63: freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used) - TLS_TCB_SIZE;
64:
65: blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
66: if (freebytes < blsize)
67: goto fail;
68:
69: n = (freebytes - blsize) / map->l_tls_align;
70:
71: size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
72: - map->l_tls_firstbyte_offset);
73:
74: map->l_tls_offset = GL(dl_tls_static_used) = offset;
75: #elif TLS_DTV_AT_TP
76: size_t used;
77: size_t check;
78:
79: size_t offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
80: used = offset + map->l_tls_blocksize;
81: check = used;
82:
83:
84: if (check > GL(dl_tls_static_size))
85: goto fail;
86:
87: map->l_tls_offset = offset;
88: GL(dl_tls_static_used) = used;
89: #else
90: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
91: #endif
92:
93:
94:
95: if (map->l_real->l_relocated)
96: {
97: #ifdef SHARED
98: if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
99: 0))
100:
101:
102: (void) _dl_update_slotinfo (map->l_tls_modid);
103: #endif
104:
105: GL(dl_init_static_tls) (map);
106: }
107: else
108: map->l_need_tls_init = 1;
109: }
110:
111:
112:
113:
114: void
115: _dl_nothread_init_static_tls (struct link_map *map)
116: {
117: #if TLS_TCB_AT_TP
118: void *dest = (char *) THREAD_SELF - map->l_tls_offset;
119: #elif TLS_DTV_AT_TP
120: void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
121: #else
122: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
123: #endif
124:
125:
126: dtv_t *dtv = THREAD_DTV ();
127: assert (map->l_tls_modid <= dtv[-1].counter);
128: dtv[map->l_tls_modid].pointer.val = dest;
129: dtv[map->l_tls_modid].pointer.is_static = true;
130:
131:
132: memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
133: '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
134: }
135:
136:
137: void
138: _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
139: int lazy, int consider_profiling)
140: {
141: struct textrels
142: {
143: caddr_t start;
144: size_t len;
145: int prot;
146: struct textrels *next;
147: } *textrels = NULL;
148:
149: const char *errstring = NULL;
150:
151: #ifdef SHARED
152:
153: consider_profiling |= GLRO(dl_audit) != NULL;
154: #elif defined PROF
155:
156: # define consider_profiling 0
157: #endif
158:
159: if (l->l_relocated)
160: return;
161:
162:
163:
164:
165: if (!consider_profiling
166: && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
167: lazy = 0;
168:
169: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
170: _dl_debug_printf ("\nrelocation processing: %s%s\n",
171: l->l_name[0] ? l->l_name : rtld_progname,
172: lazy ? " (lazy)" : "");
173:
174:
175:
176:
177: if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
178: {
179:
180:
181: const ElfW(Phdr) *ph;
182: for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
183: if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
184: {
185: struct textrels *newp;
186:
187: newp = (struct textrels *) alloca (sizeof (*newp));
188: newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
189: & ~(GLRO(dl_pagesize) - 1))
190: - (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
191: newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
192: + (caddr_t) l->l_addr);
193:
194: if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
195: {
196: errstring = N_("cannot make segment writable for relocation");
197: call_error:
198: _dl_signal_error (errno, l->l_name, NULL, errstring);
199: }
200:
201: #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
202: newp->prot = (PF_TO_PROT
203: >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
204: #else
205: newp->prot = 0;
206: if (ph->p_flags & PF_R)
207: newp->prot |= PROT_READ;
208: if (ph->p_flags & PF_W)
209: newp->prot |= PROT_WRITE;
210: if (ph->p_flags & PF_X)
211: newp->prot |= PROT_EXEC;
212: #endif
213: newp->next = textrels;
214: textrels = newp;
215: }
216: }
217:
218: {
219:
220:
221:
222: const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
223:
224:
225: #define RESOLVE_MAP(ref, version, r_type) \
226: (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
227: ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
228: && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
229: ? (bump_num_cache_relocations (), \
230: (*ref) = l->l_lookup_cache.ret, \
231: l->l_lookup_cache.value) \
232: : ({ lookup_t _lr; \
233: int _tc = elf_machine_type_class (r_type); \
234: l->l_lookup_cache.type_class = _tc; \
235: l->l_lookup_cache.sym = (*ref); \
236: const struct r_found_version *v = NULL; \
237: int flags = DL_LOOKUP_ADD_DEPENDENCY; \
238: if ((version) != NULL && (version)->hash != 0) \
239: { \
240: v = (version); \
241: flags = 0; \
242: } \
243: _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
244: scope, v, _tc, flags, NULL); \
245: l->l_lookup_cache.ret = (*ref); \
246: l->l_lookup_cache.value = _lr; })) \
247: : l)
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258: #define CHECK_STATIC_TLS(map, sym_map) \
259: do { \
260: if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \
261: _dl_allocate_static_tls (sym_map); \
262: } while (0)
263:
264: #include "dynamic-link.h"
265:
266: ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
267:
268: #ifndef PROF
269: if (__builtin_expect (consider_profiling, 0))
270: {
271:
272:
273:
274:
275: if (l->l_info[DT_PLTRELSZ] == NULL)
276: {
277: errstring = N_("%s: no PLTREL found in object %s\n");
278: fatal:
279: _dl_fatal_printf (errstring,
280: rtld_progname ?: "<program name unknown>",
281: l->l_name);
282: }
283:
284: l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
285: l->l_info[DT_PLTRELSZ]->d_un.d_val);
286: if (l->l_reloc_result == NULL)
287: {
288: errstring = N_("\
289: %s: out of memory to store relocation results for %s\n");
290: goto fatal;
291: }
292: }
293: #endif
294: }
295:
296:
297: l->l_relocated = 1;
298:
299:
300: while (__builtin_expect (textrels != NULL, 0))
301: {
302: if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
303: {
304: errstring = N_("cannot restore segment prot after reloc");
305: goto call_error;
306: }
307:
308: textrels = textrels->next;
309: }
310:
311:
312:
313: if (l->l_relro_size != 0)
314: _dl_protect_relro (l);
315: }
316:
317:
318: void internal_function
319: _dl_protect_relro (struct link_map *l)
320: {
321: ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
322: & ~(GLRO(dl_pagesize) - 1));
323: ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
324: & ~(GLRO(dl_pagesize) - 1));
325:
326: if (start != end
327: && __mprotect ((void *) start, end - start, PROT_READ) < 0)
328: {
329: static const char errstring[] = N_("\
330: cannot apply additional memory protection after relocation");
331: _dl_signal_error (errno, l->l_name, NULL, errstring);
332: }
333: }
334:
335: void
336: internal_function __attribute_noinline__
337: _dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
338: {
339: extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden;
340: #define DIGIT(b) INTUSE(_itoa_lower_digits)[(b) & 0xf];
341:
342:
343: static const char msg[2][32
344: #if __ELF_NATIVE_CLASS == 64
345: + 6
346: #endif
347: ] = { "unexpected reloc type 0x",
348: "unexpected PLT reloc type 0x" };
349: char msgbuf[sizeof (msg[0])];
350: char *cp;
351:
352: cp = __stpcpy (msgbuf, msg[plt]);
353: #if __ELF_NATIVE_CLASS == 64
354: if (__builtin_expect(type > 0xff, 0))
355: {
356: *cp++ = DIGIT (type >> 28);
357: *cp++ = DIGIT (type >> 24);
358: *cp++ = DIGIT (type >> 20);
359: *cp++ = DIGIT (type >> 16);
360: *cp++ = DIGIT (type >> 12);
361: *cp++ = DIGIT (type >> 8);
362: }
363: #endif
364: *cp++ = DIGIT (type >> 4);
365: *cp++ = DIGIT (type);
366: *cp = '\0';
367:
368: _dl_signal_error (0, map->l_name, NULL, msgbuf);
369: }