|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/exec/exec_elf.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /* 2 * Copyright (c) 2005-2006, Kohsuke Ohtani 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * exec_elf.c - ELF file loader 32 */ 33 34 #include <sys/prex.h> 35 #include <ipc/fs.h> 36 #include <ipc/proc.h> 37 #include <sys/elf.h> 38 #include <sys/param.h> 39 40 #include <string.h> 41 #include <limits.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <errno.h> 45 46 #include "exec.h" 47 48 #define SHF_VALID (SHF_ALLOC | SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE) 49 50 #ifndef CONFIG_MMU 51 static char *sect_addr[32]; /* Array of section address */ 52 #endif 53 54 #ifdef CONFIG_MMU 55 /* 56 * Load executable ELF file 57 */ 58 static int 59 load_exec(Elf32_Ehdr *ehdr, task_t task, int fd, vaddr_t *entry) 60 { 61 Elf32_Phdr *phdr; 62 void *addr, *mapped; 63 size_t size = 0; 64 int i; 65 66 phdr = (Elf32_Phdr *)((u_long)ehdr + ehdr->e_phoff); 67 if (phdr == NULL) 68 return ENOEXEC; 69 70 for (i = 0; i < (int)ehdr->e_phnum; i++, phdr++) { 71 if (phdr->p_type != PT_LOAD) 72 continue; 73 74 addr = (void *)phdr->p_vaddr; 75 size = phdr->p_memsz; 76 if (size == 0) 77 continue; 78 79 if (vm_allocate(task, &addr, size, 0) != 0) 80 return ENOMEM; 81 82 if (vm_map(task, (void *)phdr->p_vaddr, size, &mapped) != 0) 83 return ENOEXEC; 84 if (phdr->p_filesz > 0) { 85 if (lseek(fd, (off_t)phdr->p_offset, SEEK_SET) 86 == -(off_t)1) 87 goto err; 88 if (read(fd, mapped, phdr->p_filesz) < 0) 89 goto err; 90 } 91 92 vm_free(task_self(), mapped); 93 94 /* Set read-only to text */ 95 if (phdr->p_flags & PF_X) { 96 if (vm_attribute(task, addr, PROT_READ) != 0) 97 return ENOEXEC; 98 } 99 } 100 *entry = (vaddr_t)ehdr->e_entry; 101 return 0; 102 103 err: 104 vm_free(task_self(), mapped); 105 return EIO; 106 } 107 #else /* !CONFIG_MMU */ 108 109 static int 110 relocate_section_rela(Elf32_Sym *sym_table, Elf32_Rela *rela, 111 char *target_sect, int nr_reloc) 112 { 113 Elf32_Sym *sym; 114 Elf32_Addr sym_val; 115 int i; 116 117 for (i = 0; i < nr_reloc; i++) { 118 sym = &sym_table[ELF32_R_SYM(rela->r_info)]; 119 if (sym->st_shndx != STN_UNDEF) { 120 sym_val = (Elf32_Addr)sect_addr[sym->st_shndx] 121 + sym->st_value; 122 if (relocate_rela(rela, sym_val, target_sect) != 0) 123 return -1; 124 } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) { 125 DPRINTF(("undefined weak symbol for rela[%d]\n", i)); 126 } 127 rela++; 128 } 129 return 0; 130 } 131 132 static int 133 relocate_section_rel(Elf32_Sym *sym_table, Elf32_Rel *rel, 134 char *target_sect, int nr_reloc) 135 { 136 Elf32_Sym *sym; 137 Elf32_Addr sym_val; 138 int i; 139 140 for (i = 0; i < nr_reloc; i++) { 141 sym = &sym_table[ELF32_R_SYM(rel->r_info)]; 142 if (sym->st_shndx != STN_UNDEF) { 143 sym_val = (Elf32_Addr)sect_addr[sym->st_shndx] 144 + sym->st_value; 145 if (relocate_rel(rel, sym_val, target_sect) != 0) 146 return -1; 147 } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) { 148 DPRINTF(("undefined weak symbol for rel[%d]\n", i)); 149 } 150 rel++; 151 } 152 return 0; 153 } 154 155 /* 156 * Relocate ELF sections 157 */ 158 static int 159 relocate_section(Elf32_Shdr *shdr, char *rel_data) 160 { 161 Elf32_Sym *sym_table; 162 char *target_sect; 163 int nr_reloc, error; 164 165 if (shdr->sh_entsize == 0) 166 return 0; 167 if ((target_sect = sect_addr[shdr->sh_info]) == 0) 168 return -1; 169 if ((sym_table = (Elf32_Sym *)sect_addr[shdr->sh_link]) == 0) 170 return -1; 171 172 nr_reloc = (int)(shdr->sh_size / shdr->sh_entsize); 173 switch (shdr->sh_type) { 174 case SHT_REL: 175 error = relocate_section_rel(sym_table, (Elf32_Rel *)rel_data, 176 target_sect, nr_reloc); 177 break; 178 179 case SHT_RELA: 180 error = relocate_section_rela(sym_table, (Elf32_Rela *)rel_data, 181 target_sect, nr_reloc); 182 break; 183 184 default: 185 error = -1; 186 break; 187 } 188 return error; 189 } 190 191 /* 192 * Load ELF relocatable file. 193 */ 194 static int 195 load_reloc(Elf32_Ehdr *ehdr, task_t task, int fd, vaddr_t *entry) 196 { 197 Elf32_Shdr *shdr; 198 char *buf; 199 void *base, *addr, *mapped; 200 size_t shdr_size, total_size; 201 int i, error = 0; 202 203 DPRINTF(("exec: load_reloc\n")); 204 205 /* Read section header */ 206 shdr_size = ehdr->e_shentsize * ehdr->e_shnum; 207 if ((buf = malloc(shdr_size)) == NULL) { 208 error = ENOMEM; 209 goto out0; 210 } 211 212 if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) { 213 error = EIO; 214 goto out1; 215 } 216 if (read(fd, buf, shdr_size) < 0) { 217 error = EIO; 218 goto out1; 219 } 220 221 /* Allocate memory for text, data and bss. */ 222 shdr = (Elf32_Shdr *)buf; 223 total_size = 0; 224 for (i = 0; i < ehdr->e_shnum; i++, shdr++) { 225 if (shdr->sh_type == SHT_NOBITS) { /* bss? */ 226 total_size = shdr->sh_addr + shdr->sh_size; 227 break; 228 } 229 } 230 if (total_size == 0) { 231 error = ENOEXEC; 232 goto out1; 233 } 234 if (vm_allocate(task, &base, total_size, 1) != 0) { 235 DPRINTF(("exec: out of text\n")); 236 error = ENOMEM; 237 goto out1; 238 } 239 240 if (vm_map(task, base, total_size, &mapped) != 0) { 241 error = ENOMEM; 242 goto out1; 243 } 244 245 /* Copy sections */ 246 shdr = (Elf32_Shdr *)buf; 247 for (i = 0; i < ehdr->e_shnum; i++, shdr++) { 248 /* 249 *DPRINTF(("section: type=%x addr=%x size=%d offset=%x flags=%x\n", 250 * shdr->sh_type, shdr->sh_addr, shdr->sh_size, 251 * shdr->sh_offset, shdr->sh_flags)); 252 */ 253 sect_addr[i] = 0; 254 if (shdr->sh_type == SHT_PROGBITS) { 255 switch (shdr->sh_flags & SHF_VALID) { 256 case (SHF_ALLOC | SHF_EXECINSTR): /* text */ 257 case (SHF_ALLOC | SHF_WRITE): /* data */ 258 case SHF_ALLOC: /* rodata */ 259 break; 260 default: 261 continue; 262 } 263 addr = (char *)((u_long)mapped + shdr->sh_addr); 264 if (shdr->sh_size == 0) { 265 continue; 266 } 267 } else if (shdr->sh_type == SHT_NOBITS) { 268 /* bss */ 269 sect_addr[i] = \ 270 (char *)((u_long)mapped + shdr->sh_addr); 271 continue; 272 } else if (shdr->sh_type == SHT_SYMTAB || 273 shdr->sh_type == SHT_RELA || 274 shdr->sh_type == SHT_REL) 275 { 276 277 if ((addr = malloc(shdr->sh_size)) == NULL) { 278 error = ENOMEM; 279 goto out2; 280 } 281 } else 282 continue; 283 284 if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) { 285 error = EIO; 286 goto out2; 287 } 288 if (read(fd, addr, shdr->sh_size) < 0) { 289 error = EIO; 290 goto out2; 291 } 292 sect_addr[i] = addr; 293 } 294 295 /* Process relocation */ 296 shdr = (Elf32_Shdr *)buf; 297 for (i = 0; i < ehdr->e_shnum; i++, shdr++) { 298 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) { 299 if (relocate_section(shdr, sect_addr[i]) != 0) { 300 error = EIO; 301 DPRINTF(("exec: relocation failed\n")); 302 goto out2; 303 } 304 } 305 } 306 *entry = (vaddr_t)((u_long)mapped + ehdr->e_entry); 307 DPRINTF(("exec: entry=%x\n", *entry)); 308 out2: 309 /* Release symbol table */ 310 shdr = (Elf32_Shdr *)buf; 311 for (i = 0; i < ehdr->e_shnum; i++, shdr++) { 312 if (shdr->sh_type == SHT_SYMTAB || 313 shdr->sh_type == SHT_RELA || 314 shdr->sh_type == SHT_REL) { 315 if (sect_addr[i]) 316 free(sect_addr[i]); 317 } 318 } 319 vm_free(task_self(), mapped); 320 out1: 321 free(buf); 322 out0: 323 DPRINTF(("exec: load_reloc ret=%d\n", error)); 324 return error; 325 } 326 327 #endif /* !CONFIG_MMU */ 328 329 330 /* 331 * Load ELF file 332 */ 333 int 334 elf_load(struct exec *exec) 335 { 336 int error, fd; 337 338 /* 339 * Check permission. 340 */ 341 if (access(exec->path, X_OK) == -1) { 342 DPRINTF(("exec: no exec access\n")); 343 return errno; 344 } 345 346 if ((fd = open(exec->path, O_RDONLY)) == -1) 347 return ENOENT; 348 349 #ifdef CONFIG_MMU 350 error = load_exec((Elf32_Ehdr *)exec->header, exec->task, 351 fd, &exec->entry); 352 #else 353 error = load_reloc((Elf32_Ehdr *)exec->header, exec->task, 354 fd, &exec->entry); 355 #endif 356 close(fd); 357 return error; 358 } 359 360 /* 361 * Probe ELF file 362 */ 363 int 364 elf_probe(struct exec *exec) 365 { 366 Elf32_Ehdr *ehdr; 367 368 /* Check ELF header */ 369 ehdr = (Elf32_Ehdr *)exec->header; 370 DPRINTF(("exec: ELF magic %c %c %c %c\n", 371 ehdr->e_ident[EI_MAG0], 372 ehdr->e_ident[EI_MAG1], 373 ehdr->e_ident[EI_MAG2], 374 ehdr->e_ident[EI_MAG3])); 375 376 if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) || 377 (ehdr->e_ident[EI_MAG1] != ELFMAG1) || 378 (ehdr->e_ident[EI_MAG2] != ELFMAG2) || 379 (ehdr->e_ident[EI_MAG3] != ELFMAG3)) 380 return PROBE_ERROR; 381 382 #ifdef CONFIG_MMU 383 if (ehdr->e_type != ET_EXEC) 384 return PROBE_ERROR; 385 #else 386 if (ehdr->e_type != ET_REL) 387 return PROBE_ERROR; 388 #endif 389 return PROBE_MATCH; 390 } 391 392 void 393 elf_init(void) 394 { 395 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |