elf.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Sergey Bondari
00003  * Copyright (C) 2006 Jakub Jermar
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * - Redistributions of source code must retain the above copyright
00011  *   notice, this list of conditions and the following disclaimer.
00012  * - Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in the
00014  *   documentation and/or other materials provided with the distribution.
00015  * - The name of the author may not be used to endorse or promote products
00016  *   derived from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00019  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00023  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00027  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00039 #include <elf.h>
00040 #include <debug.h>
00041 #include <arch/types.h>
00042 #include <typedefs.h>
00043 #include <mm/as.h>
00044 #include <mm/frame.h>
00045 #include <mm/slab.h>
00046 #include <align.h>
00047 #include <memstr.h>
00048 #include <macros.h>
00049 #include <arch.h>
00050 
00051 static char *error_codes[] = {
00052         "no error",
00053         "invalid image",
00054         "address space error",
00055         "incompatible image",
00056         "unsupported image type",
00057         "irrecoverable error"
00058 };
00059 
00060 static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
00061 static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as);
00062 static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
00063 
00070 int elf_load(elf_header_t *header, as_t * as)
00071 {
00072         int i, rc;
00073 
00074         /* Identify ELF */
00075         if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 || 
00076             header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3) {
00077                 return EE_INVALID;
00078         }
00079         
00080         /* Identify ELF compatibility */
00081         if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || header->e_machine != ELF_MACHINE || 
00082             header->e_ident[EI_VERSION] != EV_CURRENT || header->e_version != EV_CURRENT ||
00083             header->e_ident[EI_CLASS] != ELF_CLASS) {
00084                 return EE_INCOMPATIBLE;
00085         }
00086 
00087         if (header->e_phentsize != sizeof(elf_segment_header_t))
00088                 return EE_INCOMPATIBLE;
00089 
00090         if (header->e_shentsize != sizeof(elf_section_header_t))
00091                 return EE_INCOMPATIBLE;
00092 
00093         /* Check if the object type is supported. */
00094         if (header->e_type != ET_EXEC)
00095                 return EE_UNSUPPORTED;
00096 
00097         /* Walk through all segment headers and process them. */
00098         for (i = 0; i < header->e_phnum; i++) {
00099                 rc = segment_header(&((elf_segment_header_t *)(((__u8 *) header) + header->e_phoff))[i], header, as);
00100                 if (rc != EE_OK)
00101                         return rc;
00102         }
00103 
00104         /* Inspect all section headers and proccess them. */
00105         for (i = 0; i < header->e_shnum; i++) {
00106                 rc = section_header(&((elf_section_header_t *)(((__u8 *) header) + header->e_shoff))[i], header, as);
00107                 if (rc != EE_OK)
00108                         return rc;
00109         }
00110 
00111         return EE_OK;
00112 }
00113 
00120 char *elf_error(int rc)
00121 {
00122         ASSERT(rc < sizeof(error_codes)/sizeof(char *));
00123 
00124         return error_codes[rc];
00125 }
00126 
00135 static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
00136 {
00137         switch (entry->p_type) {
00138             case PT_NULL:
00139             case PT_PHDR:
00140                 break;
00141             case PT_LOAD:
00142                 return load_segment(entry, elf, as);
00143                 break;
00144             case PT_DYNAMIC:
00145             case PT_INTERP:
00146             case PT_SHLIB:
00147             case PT_NOTE:
00148             case PT_LOPROC:
00149             case PT_HIPROC:
00150             default:
00151                 return EE_UNSUPPORTED;
00152                 break;
00153         }
00154         return EE_OK;
00155 }
00156 
00165 int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
00166 {
00167         as_area_t *a;
00168         int flags = 0;
00169         mem_backend_data_t backend_data;
00170         
00171         backend_data.elf = elf;
00172         backend_data.segment = entry;
00173 
00174         if (entry->p_align > 1) {
00175                 if ((entry->p_offset % entry->p_align) != (entry->p_vaddr % entry->p_align)) {
00176                         return EE_INVALID;
00177                 }
00178         }
00179 
00180         if (entry->p_flags & PF_X)
00181                 flags |= AS_AREA_EXEC;
00182         if (entry->p_flags & PF_W)
00183                 flags |= AS_AREA_WRITE;
00184         if (entry->p_flags & PF_R)
00185                 flags |= AS_AREA_READ;
00186         flags |= AS_AREA_CACHEABLE;
00187 
00188         /*
00189          * Check if the virtual address starts on page boundary.
00190          */
00191         if (ALIGN_UP(entry->p_vaddr, PAGE_SIZE) != entry->p_vaddr)
00192                 return EE_UNSUPPORTED;
00193 
00194         a = as_area_create(as, flags, entry->p_memsz, entry->p_vaddr, AS_AREA_ATTR_NONE,
00195                 &elf_backend, &backend_data);
00196         if (!a)
00197                 return EE_MEMORY;
00198         
00199         /*
00200          * The segment will be mapped on demand by elf_page_fault().
00201          */
00202 
00203         return EE_OK;
00204 }
00205 
00214 static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as)
00215 {
00216         switch (entry->sh_type) {
00217             default:
00218                 break;
00219         }
00220         
00221         return EE_OK;
00222 }
00223 

Generated on Sun Jun 18 16:26:58 2006 for HelenOS Kernel (amd64) by  doxygen 1.4.6