Annotation of prex-old/usr/server/exec/elf.c, Revision 1.1.1.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) {
85: if (lseek(fd, phdr->p_offset, SEEK_SET) == -(off_t)1)
86: goto err;
87: if (read(fd, mapped, phdr->p_filesz) < 0)
88: goto err;
89: }
90:
91: vm_free(task_self(), mapped);
92:
93: /* Set read-only to text */
94: if (phdr->p_flags & PF_X) {
95: if (vm_attribute(task, addr, VMA_READ) != 0)
96: return ENOEXEC;
97: }
98: }
99: *entry = (void *)ehdr->e_entry;
100: return 0;
101:
102: err:
103: vm_free(task_self(), mapped);
104: return EIO;
105: }
106: #else /* !CONFIG_MMU */
107:
108: static int
109: relocate_section_rela(Elf32_Sym *sym_table, Elf32_Rela *rela,
110: char *target_sect, int nr_reloc)
111: {
112: Elf32_Sym *sym;
113: Elf32_Addr sym_val;
114: int i;
115:
116: for (i = 0; i < nr_reloc; i++) {
117: sym = &sym_table[ELF32_R_SYM(rela->r_info)];
118: if (sym->st_shndx != STN_UNDEF) {
119: sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
120: + sym->st_value;
121: if (relocate_rela(rela, sym_val, target_sect) != 0)
122: return -1;
123: } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK)
124: dprintf("undefined weak symbol for rela[%d]\n", i);
125: rela++;
126: }
127: return 0;
128: }
129:
130: static int
131: relocate_section_rel(Elf32_Sym *sym_table, Elf32_Rel *rel,
132: char *target_sect, int nr_reloc)
133: {
134: Elf32_Sym *sym;
135: Elf32_Addr sym_val;
136: int i;
137:
138: for (i = 0; i < nr_reloc; i++) {
139: sym = &sym_table[ELF32_R_SYM(rel->r_info)];
140: if (sym->st_shndx != STN_UNDEF) {
141: sym_val = (Elf32_Addr)sect_addr[sym->st_shndx]
142: + sym->st_value;
143: if (relocate_rel(rel, sym_val, target_sect) != 0)
144: return -1;
145: } else if (ELF32_ST_BIND(sym->st_info) == STB_WEAK)
146: dprintf("undefined weak symbol for rel[%d]\n", i);
147: rel++;
148: }
149: return 0;
150: }
151:
152: /*
153: * Relocate ELF sections
154: */
155: static int
156: relocate_section(Elf32_Shdr *shdr, char *rel_data)
157: {
158: Elf32_Sym *sym_table;
159: char *target_sect;
160: int nr_reloc, err;
161:
162: dprintf("relocate_sec\n");
163: if (shdr->sh_entsize == 0)
164: return 0;
165: if ((target_sect = sect_addr[shdr->sh_info]) == 0)
166: return -1;
167: if ((sym_table = (Elf32_Sym *)sect_addr[shdr->sh_link]) == 0)
168: return -1;
169:
170: nr_reloc = (int)(shdr->sh_size / shdr->sh_entsize);
171: switch (shdr->sh_type) {
172: case SHT_REL:
173: err = relocate_section_rel(sym_table, (Elf32_Rel *)rel_data,
174: target_sect, nr_reloc);
175: break;
176:
177: case SHT_RELA:
178: err = relocate_section_rela(sym_table, (Elf32_Rela *)rel_data,
179: target_sect, nr_reloc);
180: break;
181:
182: default:
183: err = -1;
184: break;
185: }
186: return err;
187: }
188:
189: /*
190: * Load ELF relocatable file.
191: */
192: static int
193: load_reloc(Elf32_Ehdr *ehdr, task_t task, int fd, void **entry)
194: {
195: Elf32_Shdr *shdr;
196: char *buf;
197: void *base, *addr, *mapped;
198: size_t shdr_size, total_size;
199: int i, err = 0;
200:
201: /* Read section header */
202: shdr_size = ehdr->e_shentsize * ehdr->e_shnum;
203: if ((buf = malloc(shdr_size)) == NULL)
204: return ENOMEM;
205:
206: if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) {
207: err = EIO;
208: goto out1;
209: }
210: if (read(fd, buf, shdr_size) < 0) {
211: err = EIO;
212: goto out1;
213: }
214: /* Allocate memory for text, data and bss. */
215: shdr = (Elf32_Shdr *)buf;
216: total_size = 0;
217: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
218: if (shdr->sh_type == SHT_NOBITS) { /* bss? */
219: total_size = shdr->sh_addr + shdr->sh_size;
220: break;
221: }
222: }
223: if (total_size == 0) {
224: err = ENOEXEC;
225: goto out1;
226: }
227: if (vm_allocate(task, &base, total_size, 1) != 0) {
228: err = ENOMEM;
229: goto out1;
230: }
231:
232: if (vm_map(task, base, total_size, &mapped) != 0) {
233: err = ENOMEM;
234: goto out1;
235: }
236: /* Copy sections */
237: shdr = (Elf32_Shdr *)buf;
238: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
239: /*
240: *dprintf("section: type=%x addr=%x size=%d offset=%x flags=%x\n",
241: * shdr->sh_type, shdr->sh_addr, shdr->sh_size,
242: * shdr->sh_offset, shdr->sh_flags);
243: */
244: sect_addr[i] = 0;
245: if (shdr->sh_type == SHT_PROGBITS) {
246: switch (shdr->sh_flags & SHF_VALID) {
247: case (SHF_ALLOC | SHF_EXECINSTR): /* text */
248: case (SHF_ALLOC | SHF_WRITE): /* data */
249: case SHF_ALLOC: /* rodata */
250: break;
251: default:
252: continue;
253: }
254: addr = (char *)((u_long)mapped + shdr->sh_addr);
255: if (shdr->sh_size == 0) {
256: continue;
257: }
258: } else if (shdr->sh_type == SHT_NOBITS) {
259: /* bss */
260: sect_addr[i] = \
261: (char *)((u_long)mapped + shdr->sh_addr);
262: continue;
263: } else if (shdr->sh_type == SHT_SYMTAB ||
264: shdr->sh_type == SHT_RELA ||
265: shdr->sh_type == SHT_REL)
266: {
267:
268: if ((addr = malloc(shdr->sh_size)) == NULL) {
269: err = ENOMEM;
270: goto out2;
271: }
272: } else
273: continue;
274:
275: if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) {
276: err = EIO;
277: goto out2;
278: }
279: if (read(fd, addr, shdr->sh_size) < 0) {
280: err = EIO;
281: goto out2;
282: }
283: sect_addr[i] = addr;
284: }
285: /* Process relocation */
286: shdr = (Elf32_Shdr *)buf;
287: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
288: if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
289: if (relocate_section(shdr, sect_addr[i]) != 0) {
290: err = EIO;
291: sys_log("exec: relocation failed\n");
292: goto out2;
293: }
294: }
295: }
296: *entry = (void *)((u_long)mapped + ehdr->e_entry);
297: out2:
298: /* Release symbol table */
299: shdr = (Elf32_Shdr *)buf;
300: for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
301: if (shdr->sh_type == SHT_SYMTAB ||
302: shdr->sh_type == SHT_RELA ||
303: shdr->sh_type == SHT_REL) {
304: if (sect_addr[i])
305: free(sect_addr[i]);
306: }
307: }
308: vm_free(task_self(), mapped);
309: out1:
310: free(buf);
311: return err;
312: }
313:
314: #endif /* !CONFIG_MMU */
315:
316:
317: /*
318: * Load ELF file
319: */
320: int
321: elf_load(void *header, task_t task, int fd, void **entry)
322: {
323: int err;
324:
325: #ifdef CONFIG_MMU
326: err = load_exec((Elf32_Ehdr *)header, task, fd, entry);
327: #else
328: err = load_reloc((Elf32_Ehdr *)header, task, fd, entry);
329: #endif
330: return err;
331: }
332:
333: /*
334: * Probe ELF file
335: */
336: int
337: elf_probe(void *header)
338: {
339: Elf32_Ehdr *ehdr;
340:
341: /* Check ELF header */
342: ehdr = (Elf32_Ehdr *)header;
343: if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
344: (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
345: (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
346: (ehdr->e_ident[EI_MAG3] != ELFMAG3))
347: return -1;
348: #ifdef CONFIG_MMU
349: if (ehdr->e_type != ET_EXEC)
350: return -1;
351: #else
352: if (ehdr->e_type != ET_REL)
353: return -1;
354: #endif
355: return 0;
356: }
357:
358: void
359: elf_init(void)
360: {
361: }
CVSweb