Annotation of prex-old/usr/server/exec/elf.c, Revision 1.1.1.1.2.1
1.1 nbrk 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: * elf.c - ELF file loader
32: */
33:
34: #include <prex/prex.h>
35: #include <server/fs.h>
36: #include <server/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, void **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) {
1.1.1.1.2.1! nbrk 85: if (lseek(fd, (off_t)phdr->p_offset, SEEK_SET)
! 86: == -(off_t)1)
1.1 nbrk 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, VMA_READ) != 0)
97: return ENOEXEC;
98: }
99: }
100: *entry = (void *)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;
1.1.1.1.2.1! nbrk 124: } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
! 125: DPRINTF(("undefined weak symbol for rela[%d]\n", i));
! 126: }
1.1 nbrk 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;
1.1.1.1.2.1! nbrk 147: } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK) {
! 148: DPRINTF(("undefined weak symbol for rel[%d]\n", i));
! 149: }
1.1 nbrk 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, err;
164:
1.1.1.1.2.1! nbrk 165: DPRINTF(("relocate_sec\n"));
1.1 nbrk 166: if (shdr->sh_entsize == 0)
167: return 0;
168: if ((target_sect = sect_addr[shdr->sh_info]) == 0)
169: return -1;
170: if ((sym_table = (Elf32_Sym *)sect_addr[shdr->sh_link]) == 0)
171: return -1;
172:
173: nr_reloc = (int)(shdr->sh_size / shdr->sh_entsize);
174: switch (shdr->sh_type) {
175: case SHT_REL:
176: err = relocate_section_rel(sym_table, (Elf32_Rel *)rel_data,
177: target_sect, nr_reloc);
178: break;
179:
180: case SHT_RELA:
181: err = relocate_section_rela(sym_table, (Elf32_Rela *)rel_data,
182: target_sect, nr_reloc);
183: break;
184:
185: default:
186: err = -1;
187: break;
188: }
189: return err;
190: }
191:
192: /*
193: * Load ELF relocatable file.
194: */
195: static int
196: load_reloc(Elf32_Ehdr *ehdr, task_t task, int fd, void **entry)
197: {
198: Elf32_Shdr *shdr;
199: char *buf;
200: void *base, *addr, *mapped;
201: size_t shdr_size, total_size;
202: int i, err = 0;
203:
204: /* Read section header */
205: shdr_size = ehdr->e_shentsize * ehdr->e_shnum;
206: if ((buf = malloc(shdr_size)) == NULL)
207: return ENOMEM;
208:
209: if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) {
210: err = EIO;
211: goto out1;
212: }
213: if (read(fd, buf, shdr_size) < 0) {
214: err = EIO;
215: goto out1;
216: }
217: /* Allocate memory for text, data and bss. */
218: shdr = (Elf32_Shdr *)buf;
219: total_size = 0;
220: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
221: if (shdr->sh_type == SHT_NOBITS) { /* bss? */
222: total_size = shdr->sh_addr + shdr->sh_size;
223: break;
224: }
225: }
226: if (total_size == 0) {
227: err = ENOEXEC;
228: goto out1;
229: }
230: if (vm_allocate(task, &base, total_size, 1) != 0) {
231: err = ENOMEM;
232: goto out1;
233: }
234:
235: if (vm_map(task, base, total_size, &mapped) != 0) {
236: err = ENOMEM;
237: goto out1;
238: }
239: /* Copy sections */
240: shdr = (Elf32_Shdr *)buf;
241: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
242: /*
1.1.1.1.2.1! nbrk 243: *DPRINTF(("section: type=%x addr=%x size=%d offset=%x flags=%x\n",
1.1 nbrk 244: * shdr->sh_type, shdr->sh_addr, shdr->sh_size,
1.1.1.1.2.1! nbrk 245: * shdr->sh_offset, shdr->sh_flags));
1.1 nbrk 246: */
247: sect_addr[i] = 0;
248: if (shdr->sh_type == SHT_PROGBITS) {
249: switch (shdr->sh_flags & SHF_VALID) {
250: case (SHF_ALLOC | SHF_EXECINSTR): /* text */
251: case (SHF_ALLOC | SHF_WRITE): /* data */
252: case SHF_ALLOC: /* rodata */
253: break;
254: default:
255: continue;
256: }
257: addr = (char *)((u_long)mapped + shdr->sh_addr);
258: if (shdr->sh_size == 0) {
259: continue;
260: }
261: } else if (shdr->sh_type == SHT_NOBITS) {
262: /* bss */
263: sect_addr[i] = \
264: (char *)((u_long)mapped + shdr->sh_addr);
265: continue;
266: } else if (shdr->sh_type == SHT_SYMTAB ||
267: shdr->sh_type == SHT_RELA ||
268: shdr->sh_type == SHT_REL)
269: {
270:
271: if ((addr = malloc(shdr->sh_size)) == NULL) {
272: err = ENOMEM;
273: goto out2;
274: }
275: } else
276: continue;
277:
278: if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) {
279: err = EIO;
280: goto out2;
281: }
282: if (read(fd, addr, shdr->sh_size) < 0) {
283: err = EIO;
284: goto out2;
285: }
286: sect_addr[i] = addr;
287: }
288: /* Process relocation */
289: shdr = (Elf32_Shdr *)buf;
290: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
291: if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
292: if (relocate_section(shdr, sect_addr[i]) != 0) {
293: err = EIO;
1.1.1.1.2.1! nbrk 294: DPRINTF(("exec: relocation failed\n"));
1.1 nbrk 295: goto out2;
296: }
297: }
298: }
299: *entry = (void *)((u_long)mapped + ehdr->e_entry);
300: out2:
301: /* Release symbol table */
302: shdr = (Elf32_Shdr *)buf;
303: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
304: if (shdr->sh_type == SHT_SYMTAB ||
305: shdr->sh_type == SHT_RELA ||
306: shdr->sh_type == SHT_REL) {
307: if (sect_addr[i])
308: free(sect_addr[i]);
309: }
310: }
311: vm_free(task_self(), mapped);
312: out1:
313: free(buf);
314: return err;
315: }
316:
317: #endif /* !CONFIG_MMU */
318:
319:
320: /*
321: * Load ELF file
322: */
323: int
324: elf_load(void *header, task_t task, int fd, void **entry)
325: {
326: int err;
327:
328: #ifdef CONFIG_MMU
329: err = load_exec((Elf32_Ehdr *)header, task, fd, entry);
330: #else
331: err = load_reloc((Elf32_Ehdr *)header, task, fd, entry);
332: #endif
333: return err;
334: }
335:
336: /*
337: * Probe ELF file
338: */
339: int
340: elf_probe(void *header)
341: {
342: Elf32_Ehdr *ehdr;
343:
344: /* Check ELF header */
345: ehdr = (Elf32_Ehdr *)header;
346: if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
347: (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
348: (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
349: (ehdr->e_ident[EI_MAG3] != ELFMAG3))
350: return -1;
351: #ifdef CONFIG_MMU
352: if (ehdr->e_type != ET_EXEC)
353: return -1;
354: #else
355: if (ehdr->e_type != ET_REL)
356: return -1;
357: #endif
358: return 0;
359: }
360:
361: void
362: elf_init(void)
363: {
364: }
CVSweb