stdlibc: ~several fixes
[meinos.git] / kernel2 / elf.c
blob37f1aaf5f7b113641abd0ab7b3a0cf2850d2c3ca
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <elf.h>
21 #include <paging.h>
22 #include <memuser.h>
23 #include <memmap.h>
24 #include <string.h>
25 #include <debug.h>
26 #include <cpu.h>
28 int elf_validate(elf_header_t *header) {
29 if (header->ident[EI_MAG0]!=ELFMAG0 || header->ident[EI_MAG1]!=ELFMAG1 || header->ident[EI_MAG2]!=ELFMAG2 || header->ident[EI_MAG3]!=ELFMAG3) return -1;
30 if (header->machine!=EM_386) return -1;
31 if (header->ident[EI_CLASS]!=ELFCLASS32) return -1;
32 if (header->ident[EI_DATA]!=ELFDATA2LSB) return -1;
33 if (header->ident[EI_VERSION]!=header->version) return -1;
34 return 0;
37 /**
38 * Loads an ELF segment in address space
39 * @param memaddr Destination address in memory
40 * @param memsize Size in memory
41 * @param fileaddr Source address in file (absolute)
42 * @param filesize Size in file
43 * @param addrspace User address space
44 * @param writable If segment is writeable
46 int elf_loadseg(void *memaddr,size_t memsize,void *fileaddr,size_t filesize,addrspace_t *addrspace,int writable) {
47 size_t i;
49 if (memaddr<(void*)USERDATA_ADDRESS) return -1;
50 if (memuser_load_addrspace(addrspace)==-1) return -1;
51 for (i=0;i<memsize;i+=PAGE_SIZE) {
52 if (memuser_alloc_at(addrspace,memaddr+i,i<filesize?paging_getphysaddr(fileaddr+i):NULL,writable)==-1) return -1;
54 if (filesize<memsize) memset(memaddr+filesize,0,memsize-filesize);
55 return 0;
58 /**
59 * Loads an ELF file in an address space
60 * @param addrspace Address space
61 * @param file Pointer to ELF file
62 * @param filesize Size of ELF file
63 * @return Entrypoint
65 void *elf_load(addrspace_t *addrspace,void *file,size_t filesize) {
66 elf_header_t *header = file;
67 elf_progheader_t *progheader;
68 void *entrypoint;
69 size_t i;
71 if (elf_validate(header)==-1) return NULL;
73 entrypoint = (void*)(header->entry);
74 progheader = file+header->phoff;
76 for (i=0;i<header->phnum;i++) {
77 if (progheader[i].type==PT_LOAD) {
78 if (elf_loadseg((void*)(progheader[i].vaddr),progheader[i].memsz,file+progheader[i].offset,progheader[i].filesz,addrspace,(progheader[i].flags&PF_W)==PF_W?1:0)==-1) return NULL;
82 return entrypoint;