OLD | NEW |
1 #include <stddef.h> | 1 #include <stddef.h> |
2 #include "dynlink.h" | 2 #include "dynlink.h" |
3 | 3 |
4 #ifndef START | 4 #ifndef START |
5 #define START "_dlstart" | 5 #define START "_dlstart" |
6 #endif | 6 #endif |
7 | 7 |
8 #include "crt_arch.h" | 8 #include "crt_arch.h" |
9 | 9 |
10 #ifndef GETFUNCSYM | 10 #ifndef GETFUNCSYM |
11 #define GETFUNCSYM(fp, sym, got) do { \ | 11 #define GETFUNCSYM(fp, sym, got) \ |
12 » __attribute__((__visibility__("hidden"))) void sym(); \ | 12 do { \ |
13 » static void (*static_func_ptr)() = sym; \ | 13 __attribute__((__visibility__("hidden"))) void sym(); \ |
14 » __asm__ __volatile__ ( "" : "+m"(static_func_ptr) : : "memory"); \ | 14 static void (*static_func_ptr)() = sym; \ |
15 » *(fp) = static_func_ptr; } while(0) | 15 __asm__ __volatile__("" : "+m"(static_func_ptr) : : "memory"); \ |
| 16 *(fp) = static_func_ptr; \ |
| 17 } while (0) |
16 #endif | 18 #endif |
17 | 19 |
18 __attribute__((__visibility__("hidden"))) | 20 __attribute__((__visibility__("hidden"))) void _dlstart_c(size_t* sp, |
19 void _dlstart_c(size_t *sp, size_t *dynv) | 21 size_t* dynv) { |
20 { | 22 size_t i, aux[AUX_CNT], dyn[DYN_CNT]; |
21 » size_t i, aux[AUX_CNT], dyn[DYN_CNT]; | 23 size_t *rel, rel_size, base; |
22 » size_t *rel, rel_size, base; | |
23 | 24 |
24 » int argc = *sp; | 25 int argc = *sp; |
25 » char **argv = (void *)(sp+1); | 26 char** argv = (void*)(sp + 1); |
26 | 27 |
27 » for (i=argc+1; argv[i]; i++); | 28 for (i = argc + 1; argv[i]; i++) |
28 » size_t *auxv = (void *)(argv+i+1); | 29 ; |
| 30 size_t* auxv = (void*)(argv + i + 1); |
29 | 31 |
30 » for (i=0; i<AUX_CNT; i++) aux[i] = 0; | 32 for (i = 0; i < AUX_CNT; i++) |
31 » for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT) | 33 aux[i] = 0; |
32 » » aux[auxv[i]] = auxv[i+1]; | 34 for (i = 0; auxv[i]; i += 2) |
| 35 if (auxv[i] < AUX_CNT) |
| 36 aux[auxv[i]] = auxv[i + 1]; |
33 | 37 |
34 #if DL_FDPIC | 38 #if DL_FDPIC |
35 » struct fdpic_loadseg *segs, fakeseg; | 39 struct fdpic_loadseg *segs, fakeseg; |
36 » size_t j; | 40 size_t j; |
37 » if (dynv) { | 41 if (dynv) { |
38 » » /* crt_arch.h entry point asm is responsible for reserving | 42 /* crt_arch.h entry point asm is responsible for reserving |
39 » » * space and moving the extra fdpic arguments to the stack | 43 * space and moving the extra fdpic arguments to the stack |
40 » » * vector where they are easily accessible from C. */ | 44 * vector where they are easily accessible from C. */ |
41 » » segs = ((struct fdpic_loadmap *)(sp[-1] ? sp[-1] : sp[-2]))->seg
s; | 45 segs = ((struct fdpic_loadmap*)(sp[-1] ? sp[-1] : sp[-2]))->segs; |
42 » } else { | 46 } else { |
43 » » /* If dynv is null, the entry point was started from loader | 47 /* If dynv is null, the entry point was started from loader |
44 » » * that is not fdpic-aware. We can assume normal fixed- | 48 * that is not fdpic-aware. We can assume normal fixed- |
45 » » * displacement ELF loading was performed, but when ldso was | 49 * displacement ELF loading was performed, but when ldso was |
46 » » * run as a command, finding the Ehdr is a heursitic: we | 50 * run as a command, finding the Ehdr is a heursitic: we |
47 » » * have to assume Phdrs start in the first 4k of the file. */ | 51 * have to assume Phdrs start in the first 4k of the file. */ |
48 » » base = aux[AT_BASE]; | 52 base = aux[AT_BASE]; |
49 » » if (!base) base = aux[AT_PHDR] & -4096; | 53 if (!base) |
50 » » segs = &fakeseg; | 54 base = aux[AT_PHDR] & -4096; |
51 » » segs[0].addr = base; | 55 segs = &fakeseg; |
52 » » segs[0].p_vaddr = 0; | 56 segs[0].addr = base; |
53 » » segs[0].p_memsz = -1; | 57 segs[0].p_vaddr = 0; |
54 » » Ehdr *eh = (void *)base; | 58 segs[0].p_memsz = -1; |
55 » » Phdr *ph = (void *)(base + eh->e_phoff); | 59 Ehdr* eh = (void*)base; |
56 » » size_t phnum = eh->e_phnum; | 60 Phdr* ph = (void*)(base + eh->e_phoff); |
57 » » size_t phent = eh->e_phentsize; | 61 size_t phnum = eh->e_phnum; |
58 » » while (phnum-- && ph->p_type != PT_DYNAMIC) | 62 size_t phent = eh->e_phentsize; |
59 » » » ph = (void *)((size_t)ph + phent); | 63 while (phnum-- && ph->p_type != PT_DYNAMIC) |
60 » » dynv = (void *)(base + ph->p_vaddr); | 64 ph = (void*)((size_t)ph + phent); |
61 » } | 65 dynv = (void*)(base + ph->p_vaddr); |
| 66 } |
62 #endif | 67 #endif |
63 | 68 |
64 » for (i=0; i<DYN_CNT; i++) dyn[i] = 0; | 69 for (i = 0; i < DYN_CNT; i++) |
65 » for (i=0; dynv[i]; i+=2) if (dynv[i]<DYN_CNT) | 70 dyn[i] = 0; |
66 » » dyn[dynv[i]] = dynv[i+1]; | 71 for (i = 0; dynv[i]; i += 2) |
| 72 if (dynv[i] < DYN_CNT) |
| 73 dyn[dynv[i]] = dynv[i + 1]; |
67 | 74 |
68 #if DL_FDPIC | 75 #if DL_FDPIC |
69 » for (i=0; i<DYN_CNT; i++) { | 76 for (i = 0; i < DYN_CNT; i++) { |
70 » » if (i==DT_RELASZ || i==DT_RELSZ) continue; | 77 if (i == DT_RELASZ || i == DT_RELSZ) |
71 » » if (!dyn[i]) continue; | 78 continue; |
72 » » for (j=0; dyn[i]-segs[j].p_vaddr >= segs[j].p_memsz; j++); | 79 if (!dyn[i]) |
73 » » dyn[i] += segs[j].addr - segs[j].p_vaddr; | 80 continue; |
74 » } | 81 for (j = 0; dyn[i] - segs[j].p_vaddr >= segs[j].p_memsz; j++) |
75 » base = 0; | 82 ; |
| 83 dyn[i] += segs[j].addr - segs[j].p_vaddr; |
| 84 } |
| 85 base = 0; |
76 | 86 |
77 » const Sym *syms = (void *)dyn[DT_SYMTAB]; | 87 const Sym* syms = (void*)dyn[DT_SYMTAB]; |
78 | 88 |
79 » rel = (void *)dyn[DT_RELA]; | 89 rel = (void*)dyn[DT_RELA]; |
80 » rel_size = dyn[DT_RELASZ]; | 90 rel_size = dyn[DT_RELASZ]; |
81 » for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) { | 91 for (; rel_size; rel += 3, rel_size -= 3 * sizeof(size_t)) { |
82 » » if (!IS_RELATIVE(rel[1], syms)) continue; | 92 if (!IS_RELATIVE(rel[1], syms)) |
83 » » for (j=0; rel[0]-segs[j].p_vaddr >= segs[j].p_memsz; j++); | 93 continue; |
84 » » size_t *rel_addr = (void *) | 94 for (j = 0; rel[0] - segs[j].p_vaddr >= segs[j].p_memsz; j++) |
85 » » » (rel[0] + segs[j].addr - segs[j].p_vaddr); | 95 ; |
86 » » if (R_TYPE(rel[1]) == REL_FUNCDESC_VAL) { | 96 size_t* rel_addr = (void*)(rel[0] + segs[j].addr - segs[j].p_vaddr); |
87 » » » *rel_addr += segs[rel_addr[1]].addr | 97 if (R_TYPE(rel[1]) == REL_FUNCDESC_VAL) { |
88 » » » » - segs[rel_addr[1]].p_vaddr | 98 *rel_addr += segs[rel_addr[1]].addr - segs[rel_addr[1]].p_vaddr + |
89 » » » » + syms[R_SYM(rel[1])].st_value; | 99 syms[R_SYM(rel[1])].st_value; |
90 » » » rel_addr[1] = dyn[DT_PLTGOT]; | 100 rel_addr[1] = dyn[DT_PLTGOT]; |
91 » » } else { | 101 } else { |
92 » » » size_t val = syms[R_SYM(rel[1])].st_value; | 102 size_t val = syms[R_SYM(rel[1])].st_value; |
93 » » » for (j=0; val-segs[j].p_vaddr >= segs[j].p_memsz; j++); | 103 for (j = 0; val - segs[j].p_vaddr >= segs[j].p_memsz; j++) |
94 » » » *rel_addr = rel[2] + segs[j].addr - segs[j].p_vaddr + va
l; | 104 ; |
95 » » } | 105 *rel_addr = rel[2] + segs[j].addr - segs[j].p_vaddr + val; |
96 » } | 106 } |
| 107 } |
97 #else | 108 #else |
98 » /* If the dynamic linker is invoked as a command, its load | 109 /* If the dynamic linker is invoked as a command, its load |
99 » * address is not available in the aux vector. Instead, compute | 110 * address is not available in the aux vector. Instead, compute |
100 » * the load address as the difference between &_DYNAMIC and the | 111 * the load address as the difference between &_DYNAMIC and the |
101 » * virtual address in the PT_DYNAMIC program header. */ | 112 * virtual address in the PT_DYNAMIC program header. */ |
102 » base = aux[AT_BASE]; | 113 base = aux[AT_BASE]; |
103 » if (!base) { | 114 if (!base) { |
104 » » size_t phnum = aux[AT_PHNUM]; | 115 size_t phnum = aux[AT_PHNUM]; |
105 » » size_t phentsize = aux[AT_PHENT]; | 116 size_t phentsize = aux[AT_PHENT]; |
106 » » Phdr *ph = (void *)aux[AT_PHDR]; | 117 Phdr* ph = (void*)aux[AT_PHDR]; |
107 » » for (i=phnum; i--; ph = (void *)((char *)ph + phentsize)) { | 118 for (i = phnum; i--; ph = (void*)((char*)ph + phentsize)) { |
108 » » » if (ph->p_type == PT_DYNAMIC) { | 119 if (ph->p_type == PT_DYNAMIC) { |
109 » » » » base = (size_t)dynv - ph->p_vaddr; | 120 base = (size_t)dynv - ph->p_vaddr; |
110 » » » » break; | 121 break; |
111 » » » } | 122 } |
112 » » } | 123 } |
113 » } | 124 } |
114 | 125 |
115 » /* MIPS uses an ugly packed form for GOT relocations. Since we | 126 /* MIPS uses an ugly packed form for GOT relocations. Since we |
116 » * can't make function calls yet and the code is tiny anyway, | 127 * can't make function calls yet and the code is tiny anyway, |
117 » * it's simply inlined here. */ | 128 * it's simply inlined here. */ |
118 » if (NEED_MIPS_GOT_RELOCS) { | 129 if (NEED_MIPS_GOT_RELOCS) { |
119 » » size_t local_cnt = 0; | 130 size_t local_cnt = 0; |
120 » » size_t *got = (void *)(base + dyn[DT_PLTGOT]); | 131 size_t* got = (void*)(base + dyn[DT_PLTGOT]); |
121 » » for (i=0; dynv[i]; i+=2) if (dynv[i]==DT_MIPS_LOCAL_GOTNO) | 132 for (i = 0; dynv[i]; i += 2) |
122 » » » local_cnt = dynv[i+1]; | 133 if (dynv[i] == DT_MIPS_LOCAL_GOTNO) |
123 » » for (i=0; i<local_cnt; i++) got[i] += base; | 134 local_cnt = dynv[i + 1]; |
124 » } | 135 for (i = 0; i < local_cnt; i++) |
| 136 got[i] += base; |
| 137 } |
125 | 138 |
126 » rel = (void *)(base+dyn[DT_REL]); | 139 rel = (void*)(base + dyn[DT_REL]); |
127 » rel_size = dyn[DT_RELSZ]; | 140 rel_size = dyn[DT_RELSZ]; |
128 » for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) { | 141 for (; rel_size; rel += 2, rel_size -= 2 * sizeof(size_t)) { |
129 » » if (!IS_RELATIVE(rel[1], 0)) continue; | 142 if (!IS_RELATIVE(rel[1], 0)) |
130 » » size_t *rel_addr = (void *)(base + rel[0]); | 143 continue; |
131 » » *rel_addr += base; | 144 size_t* rel_addr = (void*)(base + rel[0]); |
132 » } | 145 *rel_addr += base; |
| 146 } |
133 | 147 |
134 » rel = (void *)(base+dyn[DT_RELA]); | 148 rel = (void*)(base + dyn[DT_RELA]); |
135 » rel_size = dyn[DT_RELASZ]; | 149 rel_size = dyn[DT_RELASZ]; |
136 » for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) { | 150 for (; rel_size; rel += 3, rel_size -= 3 * sizeof(size_t)) { |
137 » » if (!IS_RELATIVE(rel[1], 0)) continue; | 151 if (!IS_RELATIVE(rel[1], 0)) |
138 » » size_t *rel_addr = (void *)(base + rel[0]); | 152 continue; |
139 » » *rel_addr = base + rel[2]; | 153 size_t* rel_addr = (void*)(base + rel[0]); |
140 » } | 154 *rel_addr = base + rel[2]; |
| 155 } |
141 #endif | 156 #endif |
142 | 157 |
143 » stage2_func dls2; | 158 stage2_func dls2; |
144 » GETFUNCSYM(&dls2, __dls2, base+dyn[DT_PLTGOT]); | 159 GETFUNCSYM(&dls2, __dls2, base + dyn[DT_PLTGOT]); |
145 » dls2((void *)base, sp); | 160 dls2((void*)base, sp); |
146 } | 161 } |
OLD | NEW |