00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
00094 if (header->e_type != ET_EXEC)
00095 return EE_UNSUPPORTED;
00096
00097
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
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
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
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