1 /* 2 * elf_module.c 3 * 4 * Created on: Aug 11, 2008 5 * Author: Stefan Bucur <stefanb (at) 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 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 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 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 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 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