source: bootcd/isolinux/syslinux-6.03/com32/lib/sys/module/elf_module.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 7.1 KB
Line 
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
23static 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 */
50extern int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr);
51
52static 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
104void undefined_symbol(void)
105{
106        printf("Error: An undefined symbol was referenced\n");
107        kaboom();
108}
109
110extern int perform_relocation(struct elf_module *module, Elf_Rel *rel);
111extern int resolve_symbols(struct elf_module *module);
112
113static 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
182int 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
297error:
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
Note: See TracBrowser for help on using the repository browser.