source: mainline/generic/src/lib/elf.c@ de6b301

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since de6b301 was de6b301, checked in by Jakub Jermar <jakub@…>, 20 years ago

Basic support for loading ELF object files.
ia64, amd64, ia32 working.
mips32 requires some attention.

  • Property mode set to 100644
File size: 5.0 KB
Line 
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
38static 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
47static int program_header_entry(elf_header_t *header, elf_ph_entry_t *entry, as_t *as);
48static 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 */
56int 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 */
96char *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 */
110static 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 */
139int 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}
Note: See TracBrowser for help on using the repository browser.