1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <elf.h>
21: #include <assert.h>
22:
23: #ifdef RESOLVE_MAP
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34: # if ! ELF_MACHINE_NO_REL
35: auto inline void __attribute__((always_inline))
36: elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
37: const ElfW(Sym) *sym, const struct r_found_version *version,
38: void *const reloc_addr);
39: auto inline void __attribute__((always_inline))
40: elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
41: void *const reloc_addr);
42: # endif
43: # if ! ELF_MACHINE_NO_RELA
44: auto inline void __attribute__((always_inline))
45: elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
46: const ElfW(Sym) *sym, const struct r_found_version *version,
47: void *const reloc_addr);
48: auto inline void __attribute__((always_inline))
49: elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
50: void *const reloc_addr);
51: # endif
52: # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
53: auto inline void __attribute__((always_inline))
54: elf_machine_lazy_rel (struct link_map *map,
55: ElfW(Addr) l_addr, const ElfW(Rel) *reloc);
56: # else
57: auto inline void __attribute__((always_inline))
58: elf_machine_lazy_rel (struct link_map *map,
59: ElfW(Addr) l_addr, const ElfW(Rela) *reloc);
60: # endif
61: #endif
62:
63: #include <dl-machine.h>
64:
65: #ifndef VERSYMIDX
66: # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
67: #endif
68:
69:
70:
71: #ifndef RESOLVE_MAP
72: static
73: #else
74: auto
75: #endif
76: inline void __attribute__ ((unused, always_inline))
77: elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
78: {
79: ElfW(Dyn) *dyn = l->l_ld;
80: ElfW(Dyn) **info;
81:
82: #ifndef RTLD_BOOTSTRAP
83: if (dyn == NULL)
84: return;
85: #endif
86:
87: info = l->l_info;
88:
89: while (dyn->d_tag != DT_NULL)
90: {
91: if (dyn->d_tag < DT_NUM)
92: info[dyn->d_tag] = dyn;
93: else if (dyn->d_tag >= DT_LOPROC &&
94: dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
95: info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
96: else if ((Elf32_Word) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
97: info[VERSYMIDX (dyn->d_tag)] = dyn;
98: else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
99: info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
100: + DT_VERSIONTAGNUM] = dyn;
101: else if ((Elf32_Word) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
102: info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
103: + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
104: else if ((Elf32_Word) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
105: info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
106: + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
107: ++dyn;
108: }
109:
110: #define DL_RO_DYN_TEMP_CNT 8
111:
112: #ifndef DL_RO_DYN_SECTION
113:
114: if (l->l_addr != 0)
115: {
116: ElfW(Addr) l_addr = l->l_addr;
117: int cnt = 0;
118:
119: # define ADJUST_DYN_INFO(tag) \
120: do \
121: if (info[tag] != NULL) \
122: { \
123: if (temp) \
124: { \
125: temp[cnt].d_tag = info[tag]->d_tag; \
126: temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \
127: info[tag] = temp + cnt++; \
128: } \
129: else \
130: info[tag]->d_un.d_ptr += l_addr; \
131: } \
132: while (0)
133:
134: ADJUST_DYN_INFO (DT_HASH);
135: ADJUST_DYN_INFO (DT_PLTGOT);
136: ADJUST_DYN_INFO (DT_STRTAB);
137: ADJUST_DYN_INFO (DT_SYMTAB);
138: # if ! ELF_MACHINE_NO_RELA
139: ADJUST_DYN_INFO (DT_RELA);
140: # endif
141: # if ! ELF_MACHINE_NO_REL
142: ADJUST_DYN_INFO (DT_REL);
143: # endif
144: ADJUST_DYN_INFO (DT_JMPREL);
145: ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
146: ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
147: + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM);
148: # undef ADJUST_DYN_INFO
149: assert (cnt <= DL_RO_DYN_TEMP_CNT);
150: }
151: #endif
152: if (info[DT_PLTREL] != NULL)
153: {
154: #if ELF_MACHINE_NO_RELA
155: assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
156: #elif ELF_MACHINE_NO_REL
157: assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
158: #else
159: assert (info[DT_PLTREL]->d_un.d_val == DT_REL
160: || info[DT_PLTREL]->d_un.d_val == DT_RELA);
161: #endif
162: }
163: #if ! ELF_MACHINE_NO_RELA
164: if (info[DT_RELA] != NULL)
165: assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
166: # endif
167: # if ! ELF_MACHINE_NO_REL
168: if (info[DT_REL] != NULL)
169: assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
170: #endif
171: #ifdef RTLD_BOOTSTRAP
172:
173: assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
174: || info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val == DF_1_NOW);
175: assert (info[DT_FLAGS] == NULL
176: || info[DT_FLAGS]->d_un.d_val == DF_BIND_NOW);
177:
178: assert (info[DT_RUNPATH] == NULL);
179: assert (info[DT_RPATH] == NULL);
180: #else
181: if (info[DT_FLAGS] != NULL)
182: {
183:
184:
185:
186: l->l_flags = info[DT_FLAGS]->d_un.d_val;
187:
188: if (l->l_flags & DF_SYMBOLIC)
189: info[DT_SYMBOLIC] = info[DT_FLAGS];
190: if (l->l_flags & DF_TEXTREL)
191: info[DT_TEXTREL] = info[DT_FLAGS];
192: if (l->l_flags & DF_BIND_NOW)
193: info[DT_BIND_NOW] = info[DT_FLAGS];
194: }
195: if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
196: {
197: l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
198:
199: if (l->l_flags_1 & DF_1_NOW)
200: info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)];
201: }
202: if (info[DT_RUNPATH] != NULL)
203:
204: info[DT_RPATH] = NULL;
205: #endif
206: }
207:
208: #ifdef RESOLVE_MAP
209:
210: # ifdef RTLD_BOOTSTRAP
211: # define ELF_DURING_STARTUP (1)
212: # else
213: # define ELF_DURING_STARTUP (0)
214: # endif
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226: # ifdef ELF_MACHINE_PLTREL_OVERLAP
227: # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
228: do { \
229: struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \
230: int ranges_index; \
231: \
232: ranges[0].lazy = ranges[2].lazy = 0; \
233: ranges[1].lazy = 1; \
234: ranges[0].size = ranges[1].size = ranges[2].size = 0; \
235: \
236: if ((map)->l_info[DT_##RELOC]) \
237: { \
238: ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
239: ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
240: } \
241: \
242: if ((do_lazy) \
243: && (map)->l_info[DT_PLTREL] \
244: && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
245: { \
246: ranges[1].start = D_PTR ((map), l_info[DT_JMPREL]); \
247: ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
248: ranges[2].start = ranges[1].start + ranges[1].size; \
249: ranges[2].size = ranges[0].start + ranges[0].size - ranges[2].start; \
250: ranges[0].size = ranges[1].start - ranges[0].start; \
251: } \
252: \
253: for (ranges_index = 0; ranges_index < 3; ++ranges_index) \
254: elf_dynamic_do_##reloc ((map), \
255: ranges[ranges_index].start, \
256: ranges[ranges_index].size, \
257: ranges[ranges_index].lazy); \
258: } while (0)
259: # else
260: # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
261: do { \
262: struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \
263: ranges[0].lazy = 0; \
264: ranges[0].size = ranges[1].size = 0; \
265: ranges[0].start = 0; \
266: \
267: if ((map)->l_info[DT_##RELOC]) \
268: { \
269: ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
270: ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
271: } \
272: if ((map)->l_info[DT_PLTREL] \
273: && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
274: { \
275: ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
276: \
277: if (! ELF_DURING_STARTUP \
278: && ((do_lazy) \
279:
280:
281: \
282: || ranges[0].start + ranges[0].size != start)) \
283: { \
284: ranges[1].start = start; \
285: ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
286: ranges[1].lazy = (do_lazy); \
287: } \
288: else \
289: { \
290: \
291: assert (ranges[0].start + ranges[0].size == start); \
292: ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
293: } \
294: } \
295: \
296: if (ELF_DURING_STARTUP) \
297: elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, 0); \
298: else \
299: { \
300: int ranges_index; \
301: for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
302: elf_dynamic_do_##reloc ((map), \
303: ranges[ranges_index].start, \
304: ranges[ranges_index].size, \
305: ranges[ranges_index].lazy); \
306: } \
307: } while (0)
308: # endif
309:
310: # if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
311: # define _ELF_CHECK_REL 0
312: # else
313: # define _ELF_CHECK_REL 1
314: # endif
315:
316: # if ! ELF_MACHINE_NO_REL
317: # include "do-rel.h"
318: # define ELF_DYNAMIC_DO_REL(map, lazy) \
319: _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
320: # else
321: # define ELF_DYNAMIC_DO_REL(map, lazy)
322: # endif
323:
324: # if ! ELF_MACHINE_NO_RELA
325: # define DO_RELA
326: # include "do-rel.h"
327: # define ELF_DYNAMIC_DO_RELA(map, lazy) \
328: _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
329: # else
330: # define ELF_DYNAMIC_DO_RELA(map, lazy)
331: # endif
332:
333:
334:
335: # define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
336: do { \
337: int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
338: (consider_profile)); \
339: ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
340: ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
341: } while (0)
342:
343: #endif