1 /*
2 * elf_module.c
3 *
4 * Created on: Aug 11, 2008
5 * Author: Stefan Bucur <stefanb@zytor.com>
6 */
7
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <elf.h>
13 #include <dprintf.h>
14 #include <core.h>
15
16 #include <linux/list.h>
17 #include <sys/module.h>
18 #include <sys/exec.h>
19
20 #include "elfutils.h"
21 #include "common.h"
22
check_header(Elf_Ehdr * elf_hdr)23 static int check_header(Elf_Ehdr *elf_hdr) {
24 int res;
25
26 res = check_header_common(elf_hdr);
27
28 if (res != 0)
29 return res;
30
31 if (elf_hdr->e_type != MODULE_ELF_TYPE) {
32 dprintf("The ELF file must be a shared object\n");
33 return -1;
34 }
35
36 if (elf_hdr->e_phoff == 0x00000000) {
37 dprintf("PHT missing\n");
38 return -1;
39 }
40
41 return 0;
42 }
43
44 /*
45 *
46 * The implementation assumes that the loadable segments are present
47 * in the PHT sorted by their offsets, so that only forward seeks would
48 * be necessary.
49 */
50 extern int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr);
51
prepare_dynlinking(struct elf_module * module)52 static int prepare_dynlinking(struct elf_module *module) {
53 Elf_Dyn *dyn_entry = module->dyn_table;
54
55 while (dyn_entry->d_tag != DT_NULL) {
56 switch (dyn_entry->d_tag) {
57 case DT_NEEDED:
58 /*
59 * It's unlikely there'll be more than
60 * MAX_NR_DEPS DT_NEEDED entries but if there
61 * are then inform the user that we ran out of
62 * space.
63 */
64 if (module->nr_needed < MAX_NR_DEPS)
65 module->needed[module->nr_needed++] = dyn_entry->d_un.d_ptr;
66 else {
67 printf("Too many dependencies!\n");
68 return -1;
69 }
70 break;
71 case DT_HASH:
72 module->hash_table =
73 (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
74 break;
75 case DT_GNU_HASH:
76 module->ghash_table =
77 (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
78 break;
79 case DT_STRTAB:
80 module->str_table =
81 (char*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
82 break;
83 case DT_SYMTAB:
84 module->sym_table =
85 module_get_absolute(dyn_entry->d_un.d_ptr, module);
86 break;
87 case DT_STRSZ:
88 module->strtable_size = dyn_entry->d_un.d_val;
89 break;
90 case DT_SYMENT:
91 module->syment_size = dyn_entry->d_un.d_val;
92 break;
93 case DT_PLTGOT: // The first entry in the GOT
94 module->got = module_get_absolute(dyn_entry->d_un.d_ptr, module);
95 break;
96 }
97
98 dyn_entry++;
99 }
100
101 return 0;
102 }
103
undefined_symbol(void)104 void undefined_symbol(void)
105 {
106 printf("Error: An undefined symbol was referenced\n");
107 kaboom();
108 }
109
110 extern int perform_relocation(struct elf_module *module, Elf_Rel *rel);
111 extern int resolve_symbols(struct elf_module *module);
112
extract_operations(struct elf_module * module)113 static int extract_operations(struct elf_module *module) {
114 Elf_Sym *ctors_start, *ctors_end;
115 Elf_Sym *dtors_start, *dtors_end;
116 module_ctor_t *ctors = NULL;
117 module_ctor_t *dtors = NULL;
118
119 ctors_start = module_find_symbol("__ctors_start", module);
120 ctors_end = module_find_symbol("__ctors_end", module);
121
122 if (ctors_start && ctors_end) {
123 module_ctor_t *start, *end;
124 int nr_ctors = 0;
125 int i, size;
126
127 start = module_get_absolute(ctors_start->st_value, module);
128 end = module_get_absolute(ctors_end->st_value, module);
129
130 nr_ctors = end - start;
131
132 size = nr_ctors * sizeof(module_ctor_t);
133 size += sizeof(module_ctor_t); /* NULL entry */
134
135 ctors = malloc(size);
136 if (!ctors) {
137 printf("Unable to alloc memory for ctors\n");
138 return -1;
139 }
140
141 memset(ctors, 0, size);
142 for (i = 0; i < nr_ctors; i++)
143 ctors[i] = start[i];
144
145 module->ctors = ctors;
146 }
147
148 dtors_start = module_find_symbol("__dtors_start", module);
149 dtors_end = module_find_symbol("__dtors_end", module);
150
151 if (dtors_start && dtors_end) {
152 module_ctor_t *start, *end;
153 int nr_dtors = 0;
154 int i, size;
155
156 start = module_get_absolute(dtors_start->st_value, module);
157 end = module_get_absolute(dtors_end->st_value, module);
158
159 nr_dtors = end - start;
160
161 size = nr_dtors * sizeof(module_ctor_t);
162 size += sizeof(module_ctor_t); /* NULL entry */
163
164 dtors = malloc(size);
165 if (!dtors) {
166 printf("Unable to alloc memory for dtors\n");
167 free(ctors);
168 return -1;
169 }
170
171 memset(dtors, 0, size);
172 for (i = 0; i < nr_dtors; i++)
173 dtors[i] = start[i];
174
175 module->dtors = dtors;
176 }
177
178 return 0;
179 }
180
181 // Loads the module into the system
module_load(struct elf_module * module)182 int module_load(struct elf_module *module) {
183 int res;
184 Elf_Sym *main_sym;
185 Elf_Ehdr elf_hdr;
186 module_ctor_t *ctor;
187 struct elf_module *head = NULL;
188
189 // Do not allow duplicate modules
190 if (module_find(module->name) != NULL) {
191 dprintf("Module %s is already loaded.\n", module->name);
192 return EEXIST;
193 }
194
195 // Get a mapping/copy of the ELF file in memory
196 res = image_load(module);
197
198 if (res < 0) {
199 dprintf("Image load failed for %s\n", module->name);
200 return res;
201 }
202
203 // The module is a fully featured dynamic library
204 module->shallow = 0;
205
206 CHECKED(res, image_read(&elf_hdr, sizeof(Elf_Ehdr), module), error);
207 //printf("check... 1\n");
208
209 //print_elf_ehdr(&elf_hdr);
210
211 // Checking the header signature and members
212 CHECKED(res, check_header(&elf_hdr), error);
213 //printf("check... 2\n");
214
215 // Load the segments in the memory
216 CHECKED(res, load_segments(module, &elf_hdr), error);
217 //printf("bleah... 3\n");
218 // Obtain dynamic linking information
219 CHECKED(res, prepare_dynlinking(module), error);
220 //printf("check... 4\n");
221
222 head = module_current();
223
224 /* Find modules we need to load as dependencies */
225 if (module->str_table) {
226 int i;
227
228 /*
229 * Note that we have to load the dependencies in
230 * reverse order.
231 */
232 for (i = module->nr_needed - 1; i >= 0; i--) {
233 char *dep, *p;
234 char *argv[2] = { NULL, NULL };
235
236 dep = module->str_table + module->needed[i];
237
238 /* strip everything but the last component */
239 if (!strlen(dep))
240 continue;
241
242 if (strchr(dep, '/')) {
243 p = strrchr(dep, '/');
244 p++;
245 } else
246 p = dep;
247
248 argv[0] = p;
249 res = spawn_load(p, 1, argv);
250 if (res < 0) {
251 printf("Failed to load %s\n", p);
252 goto error;
253 }
254 }
255 }
256
257 // Check the symbols for duplicates / missing definitions
258 CHECKED(res, check_symbols(module), error);
259 //printf("check... 5\n");
260
261 main_sym = module_find_symbol("main", module);
262 if (main_sym)
263 module->main_func =
264 module_get_absolute(main_sym->st_value, module);
265
266 //printf("check... 6\n");
267
268 // Add the module at the beginning of the module list
269 list_add(&module->list, &modules_head);
270
271 // Perform the relocations
272 resolve_symbols(module);
273
274 // Obtain constructors and destructors
275 CHECKED(res, extract_operations(module), error);
276
277 //dprintf("module->symtable_size = %d\n", module->symtable_size);
278
279 //print_elf_symbols(module);
280
281 // The file image is no longer needed
282 image_unload(module);
283
284 /*
285 dprintf("MODULE %s LOADED SUCCESSFULLY (main@%p, init@%p, exit@%p)\n",
286 module->name,
287 (module->main_func == NULL) ? NULL : *(module->main_func),
288 (module->init_func == NULL) ? NULL : *(module->init_func),
289 (module->exit_func == NULL) ? NULL : *(module->exit_func));
290 */
291
292 for (ctor = module->ctors; ctor && *ctor; ctor++)
293 (*ctor) ();
294
295 return 0;
296
297 error:
298 if (head)
299 unload_modules_since(head->name);
300
301 // Remove the module from the module list (if applicable)
302 list_del_init(&module->list);
303
304 if (module->module_addr != NULL) {
305 elf_free(module->module_addr);
306 module->module_addr = NULL;
307 }
308
309 image_unload(module);
310
311 // Clear the execution part of the module buffer
312 memset(&module->u, 0, sizeof module->u);
313
314 return res;
315 }
316
317