Subversion Repositories HelenOS-historic

Rev

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

  1. /*
  2.  * Copyright (C) 2006 Sergey Bondari
  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.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <elf.h>
  30. #include <debug.h>
  31. #include <arch/types.h>
  32. #include <typedefs.h>
  33. #include <mm/as.h>
  34. #include <mm/frame.h>
  35. #include <print.h>
  36. #include <align.h>
  37.  
  38. static char *error_codes[] = {
  39.     "no error",
  40.     "invalid image",
  41.     "address space error",
  42.     "incompatible image",
  43.     "unsupported image type",
  44.     "irrecoverable error"
  45. };
  46.  
  47. static int program_header_entry(elf_header_t *header, elf_ph_entry_t *entry, as_t *as);
  48. static int load_segment(elf_header_t *header, elf_ph_entry_t *entry, as_t *as);
  49.  
  50. /** ELF loader
  51.  *
  52.  * @param header Pointer to ELF header in memory
  53.  * @param as Created and properly mapped address space
  54.  * @return EE_OK on success
  55.  */
  56. int elf_load(elf_header_t *header, as_t * as)
  57. {
  58.     int i, rc;
  59.  
  60.     /* Identify ELF */
  61.     if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 ||
  62.         header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3) {
  63.         return EE_INVALID;
  64.     }
  65.    
  66.     /* Identify ELF compatibility */
  67.     if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING || header->e_machine != ELF_MACHINE ||
  68.         header->e_ident[EI_VERSION] != EV_CURRENT || header->e_version != EV_CURRENT ||
  69.         header->e_ident[EI_CLASS] != ELF_CLASS) {
  70.         return EE_INCOMPATIBLE;
  71.     }
  72.  
  73.     if (header->e_phentsize != sizeof(elf_ph_entry_t))
  74.         return EE_INCOMPATIBLE;
  75.  
  76.     /* Check if the object type is supported. */
  77.     if (header->e_type != ET_EXEC)
  78.         return EE_UNSUPPORTED;
  79.  
  80.     /* Walk through all program header entries and process them. */
  81.     for (i = 0; i < header->e_phnum; i++) {
  82.         rc = program_header_entry(header, &((elf_ph_entry_t *)(((__u8 *) header) + header->e_phoff))[i], as);
  83.         if (rc != EE_OK)
  84.             return rc;
  85.     }
  86.  
  87.     return EE_OK;
  88. }
  89.  
  90. /** Print error message according to error code.
  91.  *
  92.  * @param rc Return code returned by elf_load().
  93.  *
  94.  * @return NULL terminated description of error.
  95.  */
  96. char *elf_error(int rc)
  97. {
  98.     ASSERT(rc < sizeof(error_codes)/sizeof(char *));
  99.  
  100.     return error_codes[rc];
  101. }
  102.  
  103. /** Process program header entry.
  104.  *
  105.  * @param entry Program header entry.
  106.  * @param as Address space into wich the ELF is being loaded.
  107.  *
  108.  * @return EE_OK on success, error code otherwise.
  109.  */
  110. static int program_header_entry(elf_header_t *header, elf_ph_entry_t *entry, as_t *as)
  111. {
  112.     switch (entry->p_type) {
  113.         case PT_NULL:
  114.         case PT_PHDR:
  115.         break;
  116.         case PT_LOAD:
  117.         return load_segment(header, entry, as);
  118.         break;
  119.         case PT_DYNAMIC:
  120.         case PT_INTERP:
  121.         case PT_SHLIB:
  122.         case PT_NOTE:
  123.         case PT_LOPROC:
  124.         case PT_HIPROC:
  125.         default:
  126.         return EE_UNSUPPORTED;
  127.         break;
  128.     }
  129.     return EE_OK;
  130. }
  131.  
  132. /** Load segment described by program header entry.
  133.  *
  134.  * @param entry Program header entry describing segment to be loaded.
  135.  * @parma as Address space into wich the ELF is being loaded.
  136.  *
  137.  * @return EE_OK on success, error code otherwise.
  138.  */
  139. int load_segment(elf_header_t *header, elf_ph_entry_t *entry, as_t *as)
  140. {
  141.     as_area_t *a;
  142.     int i, type = 0;
  143.  
  144.     if (entry->p_align > 1) {
  145.         if ((entry->p_offset % entry->p_align) != (entry->p_vaddr % entry->p_align)) {
  146.             return EE_INVALID;
  147.         }
  148.     }
  149.  
  150.     /*
  151.      * Check if the segment doesn't interfere with kernel address space.
  152.      */
  153.     if (entry->p_vaddr + ALIGN_UP(entry->p_memsz, PAGE_SIZE) >= USER_ADDRESS_SPACE_END)
  154.         return EE_MEMORY;
  155.    
  156.     if (entry->p_flags & PF_X) {
  157.         type = AS_AREA_TEXT;
  158.     } else if (entry->p_flags & PF_W) {
  159.         type = AS_AREA_DATA;
  160.     } else {
  161.         return EE_UNSUPPORTED;
  162.     }
  163.  
  164.     a = as_area_create(as, AS_AREA_TEXT, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
  165.     if (!a)
  166.         return EE_IRRECOVERABLE;
  167.    
  168.     for (i = 0; i < SIZE2FRAMES(entry->p_filesz); i++) {
  169.         as_set_mapping(as, entry->p_vaddr + i*PAGE_SIZE, KA2PA(((__address) header) + entry->p_offset + i*PAGE_SIZE));
  170.     }
  171.    
  172.     return EE_OK;
  173. }
  174.