Adding upstream version 6.00+dfgs.
[syslinux-debian/hramrach.git] / com32 / lib / sys / module / elf_module.c
blobe3d9928ab47d36dfa68ae621525d7c0cf6531a00
1 /*
2 * elf_module.c
4 * Created on: Aug 11, 2008
5 * Author: Stefan Bucur <stefanb@zytor.com>
6 */
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>
16 #include <linux/list.h>
17 #include <sys/module.h>
18 #include <sys/exec.h>
20 #include "elfutils.h"
21 #include "common.h"
23 static int check_header(Elf_Ehdr *elf_hdr) {
24 int res;
26 res = check_header_common(elf_hdr);
28 if (res != 0)
29 return res;
31 if (elf_hdr->e_type != MODULE_ELF_TYPE) {
32 DBG_PRINT("The ELF file must be a shared object\n");
33 return -1;
36 if (elf_hdr->e_phoff == 0x00000000) {
37 DBG_PRINT("PHT missing\n");
38 return -1;
41 return 0;
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.
50 extern int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr);
52 static int prepare_dynlinking(struct elf_module *module) {
53 Elf_Dyn *dyn_entry = module->dyn_table;
55 while (dyn_entry->d_tag != DT_NULL) {
56 switch (dyn_entry->d_tag) {
57 case DT_NEEDED:
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.
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;
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;
98 dyn_entry++;
101 return 0;
104 void undefined_symbol(void)
106 printf("Error: An undefined symbol was referenced\n");
107 kaboom();
110 extern int perform_relocation(struct elf_module *module, Elf_Rel *rel);
111 extern int resolve_symbols(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;
119 ctors_start = module_find_symbol("__ctors_start", module);
120 ctors_end = module_find_symbol("__ctors_end", module);
122 if (ctors_start && ctors_end) {
123 module_ctor_t *start, *end;
124 int nr_ctors = 0;
125 int i, size;
127 start = module_get_absolute(ctors_start->st_value, module);
128 end = module_get_absolute(ctors_end->st_value, module);
130 nr_ctors = end - start;
132 size = nr_ctors * sizeof(module_ctor_t);
133 size += sizeof(module_ctor_t); /* NULL entry */
135 ctors = malloc(size);
136 if (!ctors) {
137 printf("Unable to alloc memory for ctors\n");
138 return -1;
141 memset(ctors, 0, size);
142 for (i = 0; i < nr_ctors; i++)
143 ctors[i] = start[i];
145 module->ctors = ctors;
148 dtors_start = module_find_symbol("__dtors_start", module);
149 dtors_end = module_find_symbol("__dtors_end", module);
151 if (dtors_start && dtors_end) {
152 module_ctor_t *start, *end;
153 int nr_dtors = 0;
154 int i, size;
156 start = module_get_absolute(dtors_start->st_value, module);
157 end = module_get_absolute(dtors_end->st_value, module);
159 nr_dtors = end - start;
161 size = nr_dtors * sizeof(module_ctor_t);
162 size += sizeof(module_ctor_t); /* NULL entry */
164 dtors = malloc(size);
165 if (!dtors) {
166 printf("Unable to alloc memory for dtors\n");
167 free(ctors);
168 return -1;
171 memset(dtors, 0, size);
172 for (i = 0; i < nr_dtors; i++)
173 dtors[i] = start[i];
175 module->dtors = dtors;
178 return 0;
181 // Loads the module into the system
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;
189 // Do not allow duplicate modules
190 if (module_find(module->name) != NULL) {
191 DBG_PRINT("Module %s is already loaded.\n", module->name);
192 return EEXIST;
195 // Get a mapping/copy of the ELF file in memory
196 res = image_load(module);
198 if (res < 0) {
199 return res;
202 // The module is a fully featured dynamic library
203 module->shallow = 0;
205 CHECKED(res, image_read(&elf_hdr, sizeof(Elf_Ehdr), module), error);
206 //printf("check... 1\n");
208 //print_elf_ehdr(&elf_hdr);
210 // Checking the header signature and members
211 CHECKED(res, check_header(&elf_hdr), error);
212 //printf("check... 2\n");
214 // Load the segments in the memory
215 CHECKED(res, load_segments(module, &elf_hdr), error);
216 //printf("bleah... 3\n");
217 // Obtain dynamic linking information
218 CHECKED(res, prepare_dynlinking(module), error);
219 //printf("check... 4\n");
221 head = module_current();
223 /* Find modules we need to load as dependencies */
224 if (module->str_table) {
225 int i;
228 * Note that we have to load the dependencies in
229 * reverse order.
231 for (i = module->nr_needed - 1; i >= 0; i--) {
232 char *dep, *p;
233 char *argv[2] = { NULL, NULL };
235 dep = module->str_table + module->needed[i];
237 /* strip everything but the last component */
238 if (!strlen(dep))
239 continue;
241 if (strchr(dep, '/')) {
242 p = strrchr(dep, '/');
243 p++;
244 } else
245 p = dep;
247 argv[0] = p;
248 res = spawn_load(p, 1, argv);
249 if (res < 0) {
250 printf("Failed to load %s\n", p);
251 goto error;
256 // Check the symbols for duplicates / missing definitions
257 CHECKED(res, check_symbols(module), error);
258 //printf("check... 5\n");
260 main_sym = module_find_symbol("main", module);
261 if (main_sym)
262 module->main_func =
263 module_get_absolute(main_sym->st_value, module);
265 //printf("check... 6\n");
267 // Add the module at the beginning of the module list
268 list_add(&module->list, &modules_head);
270 // Perform the relocations
271 resolve_symbols(module);
273 // Obtain constructors and destructors
274 CHECKED(res, extract_operations(module), error);
276 //dprintf("module->symtable_size = %d\n", module->symtable_size);
278 //print_elf_symbols(module);
280 // The file image is no longer needed
281 image_unload(module);
284 DBG_PRINT("MODULE %s LOADED SUCCESSFULLY (main@%p, init@%p, exit@%p)\n",
285 module->name,
286 (module->main_func == NULL) ? NULL : *(module->main_func),
287 (module->init_func == NULL) ? NULL : *(module->init_func),
288 (module->exit_func == NULL) ? NULL : *(module->exit_func));
291 for (ctor = module->ctors; ctor && *ctor; ctor++)
292 (*ctor) ();
294 return 0;
296 error:
297 if (head)
298 unload_modules_since(head->name);
300 // Remove the module from the module list (if applicable)
301 list_del_init(&module->list);
303 if (module->module_addr != NULL) {
304 elf_free(module->module_addr);
305 module->module_addr = NULL;
308 image_unload(module);
310 // Clear the execution part of the module buffer
311 memset(&module->u, 0, sizeof module->u);
313 return res;