Subversion Repositories HelenOS

Rev

Rev 2071 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Sergey Bondari
  3.  * Copyright (c) 2006 Jakub Jermar
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. /** @addtogroup generic
  31.  * @{
  32.  */
  33.  
  34. /**
  35.  * @file
  36.  * @brief   Kernel ELF loader.
  37.  */
  38.  
  39. #include <lib/elf.h>
  40. #include <debug.h>
  41. #include <arch/types.h>
  42. #include <mm/as.h>
  43. #include <mm/frame.h>
  44. #include <mm/slab.h>
  45. #include <align.h>
  46. #include <memstr.h>
  47. #include <macros.h>
  48. #include <arch.h>
  49.  
  50. static char *error_codes[] = {
  51.     "no error",
  52.     "invalid image",
  53.     "address space error",
  54.     "incompatible image",
  55.     "unsupported image type",
  56.     "irrecoverable error"
  57. };
  58.  
  59. static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
  60. static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as);
  61. static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
  62.  
  63. /** ELF loader
  64.  *
  65.  * @param header Pointer to ELF header in memory
  66.  * @param as Created and properly mapped address space
  67.  * @return EE_OK on success
  68.  */
  69. int elf_load(elf_header_t *header, as_t * as)
  70. {
  71.     int i, rc;
  72.  
  73.     /* Identify ELF */
  74.     if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 ||
  75.         header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3) {
  76.         return EE_INVALID;
  77.     }
  78.    
  79.     /* Identify ELF compatibility */
  80.     if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || header->e_machine != ELF_MACHINE ||
  81.         header->e_ident[EI_VERSION] != EV_CURRENT || header->e_version != EV_CURRENT ||
  82.         header->e_ident[EI_CLASS] != ELF_CLASS) {
  83.         return EE_INCOMPATIBLE;
  84.     }
  85.  
  86.     if (header->e_phentsize != sizeof(elf_segment_header_t))
  87.         return EE_INCOMPATIBLE;
  88.  
  89.     if (header->e_shentsize != sizeof(elf_section_header_t))
  90.         return EE_INCOMPATIBLE;
  91.  
  92.     /* Check if the object type is supported. */
  93.     if (header->e_type != ET_EXEC)
  94.         return EE_UNSUPPORTED;
  95.  
  96.     /* Walk through all segment headers and process them. */
  97.     for (i = 0; i < header->e_phnum; i++) {
  98.         rc = segment_header(&((elf_segment_header_t *)(((uint8_t *) header) + header->e_phoff))[i], header, as);
  99.         if (rc != EE_OK)
  100.             return rc;
  101.     }
  102.  
  103.     /* Inspect all section headers and proccess them. */
  104.     for (i = 0; i < header->e_shnum; i++) {
  105.         rc = section_header(&((elf_section_header_t *)(((uint8_t *) header) + header->e_shoff))[i], header, as);
  106.         if (rc != EE_OK)
  107.             return rc;
  108.     }
  109.  
  110.     return EE_OK;
  111. }
  112.  
  113. /** Print error message according to error code.
  114.  *
  115.  * @param rc Return code returned by elf_load().
  116.  *
  117.  * @return NULL terminated description of error.
  118.  */
  119. char *elf_error(int rc)
  120. {
  121.     ASSERT(rc < sizeof(error_codes)/sizeof(char *));
  122.  
  123.     return error_codes[rc];
  124. }
  125.  
  126. /** Process segment header.
  127.  *
  128.  * @param entry Segment header.
  129.  * @param elf ELF header.
  130.  * @param as Address space into wich the ELF is being loaded.
  131.  *
  132.  * @return EE_OK on success, error code otherwise.
  133.  */
  134. static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
  135. {
  136.     switch (entry->p_type) {
  137.     case PT_NULL:
  138.     case PT_PHDR:
  139.         break;
  140.     case PT_LOAD:
  141.         return load_segment(entry, elf, as);
  142.         break;
  143.     case PT_DYNAMIC:
  144.     case PT_INTERP:
  145.     case PT_SHLIB:
  146.     case PT_NOTE:
  147.     case PT_LOPROC:
  148.     case PT_HIPROC:
  149.     default:
  150.         return EE_UNSUPPORTED;
  151.         break;
  152.     }
  153.     return EE_OK;
  154. }
  155.  
  156. /** Load segment described by program header entry.
  157.  *
  158.  * @param entry Program header entry describing segment to be loaded.
  159.  * @param elf ELF header.
  160.  * @param as Address space into wich the ELF is being loaded.
  161.  *
  162.  * @return EE_OK on success, error code otherwise.
  163.  */
  164. int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
  165. {
  166.     as_area_t *a;
  167.     int flags = 0;
  168.     mem_backend_data_t backend_data;
  169.    
  170.     backend_data.elf = elf;
  171.     backend_data.segment = entry;
  172.  
  173.     if (entry->p_align > 1) {
  174.         if ((entry->p_offset % entry->p_align) != (entry->p_vaddr % entry->p_align)) {
  175.             return EE_INVALID;
  176.         }
  177.     }
  178.  
  179.     if (entry->p_flags & PF_X)
  180.         flags |= AS_AREA_EXEC;
  181.     if (entry->p_flags & PF_W)
  182.         flags |= AS_AREA_WRITE;
  183.     if (entry->p_flags & PF_R)
  184.         flags |= AS_AREA_READ;
  185.     flags |= AS_AREA_CACHEABLE;
  186.  
  187.     /*
  188.      * Check if the virtual address starts on page boundary.
  189.      */
  190.     if (ALIGN_UP(entry->p_vaddr, PAGE_SIZE) != entry->p_vaddr)
  191.         return EE_UNSUPPORTED;
  192.  
  193.     a = as_area_create(as, flags, entry->p_memsz, entry->p_vaddr, AS_AREA_ATTR_NONE,
  194.         &elf_backend, &backend_data);
  195.     if (!a)
  196.         return EE_MEMORY;
  197.    
  198.     /*
  199.      * The segment will be mapped on demand by elf_page_fault().
  200.      */
  201.  
  202.     return EE_OK;
  203. }
  204.  
  205. /** Process section header.
  206.  *
  207.  * @param entry Segment header.
  208.  * @param elf ELF header.
  209.  * @param as Address space into wich the ELF is being loaded.
  210.  *
  211.  * @return EE_OK on success, error code otherwise.
  212.  */
  213. static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as)
  214. {
  215.     switch (entry->sh_type) {
  216.     default:
  217.         break;
  218.     }
  219.    
  220.     return EE_OK;
  221. }
  222.  
  223. /** @}
  224.  */
  225.