source: mainline/kernel/generic/src/lib/elf.c@ bf2042f9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bf2042f9 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 6.9 KB
Line 
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 <assert.h>
40#include <lib/elf.h>
41#include <typedefs.h>
42#include <mm/as.h>
43#include <mm/frame.h>
44#include <mm/slab.h>
45#include <align.h>
46#include <macros.h>
47#include <arch.h>
48
49#include <lib/elf_load.h>
50
51static const char *error_codes[] = {
52 "no error",
53 "invalid image",
54 "address space error",
55 "incompatible image",
56 "unsupported image type",
57 "irrecoverable error"
58};
59
60static int segment_header(elf_segment_header_t *, elf_header_t *, as_t *,
61 unsigned int);
62static int section_header(elf_section_header_t *, elf_header_t *, as_t *);
63static int load_segment(elf_segment_header_t *, elf_header_t *, as_t *);
64
65/** ELF loader
66 *
67 * @param header Pointer to ELF header in memory
68 * @param as Created and properly mapped address space
69 * @param flags A combination of ELD_F_*
70 *
71 * @return EE_OK on success
72 *
73 */
74unsigned int elf_load(elf_header_t *header, as_t *as, unsigned int flags)
75{
76 /* Identify ELF */
77 if ((header->e_ident[EI_MAG0] != ELFMAG0) ||
78 (header->e_ident[EI_MAG1] != ELFMAG1) ||
79 (header->e_ident[EI_MAG2] != ELFMAG2) ||
80 (header->e_ident[EI_MAG3] != ELFMAG3))
81 return EE_INVALID;
82
83 /* Identify ELF compatibility */
84 if ((header->e_ident[EI_DATA] != ELF_DATA_ENCODING) ||
85 (header->e_machine != ELF_MACHINE) ||
86 (header->e_ident[EI_VERSION] != EV_CURRENT) ||
87 (header->e_version != EV_CURRENT) ||
88 (header->e_ident[EI_CLASS] != ELF_CLASS))
89 return EE_INCOMPATIBLE;
90
91 if (header->e_phentsize != sizeof(elf_segment_header_t))
92 return EE_INCOMPATIBLE;
93
94 if (header->e_shentsize != sizeof(elf_section_header_t))
95 return EE_INCOMPATIBLE;
96
97 /* Check if the object type is supported. */
98 if (header->e_type != ET_EXEC)
99 return EE_UNSUPPORTED;
100
101 /* Check if the ELF image starts on a page boundary */
102 if (ALIGN_UP((uintptr_t) header, PAGE_SIZE) != (uintptr_t) header)
103 return EE_UNSUPPORTED;
104
105 /* Walk through all segment headers and process them. */
106 elf_half i;
107 for (i = 0; i < header->e_phnum; i++) {
108 elf_segment_header_t *seghdr =
109 &((elf_segment_header_t *)(((uint8_t *) header) +
110 header->e_phoff))[i];
111
112 int rc = segment_header(seghdr, header, as, flags);
113 if (rc != EE_OK)
114 return rc;
115 }
116
117 /* Inspect all section headers and process them. */
118 for (i = 0; i < header->e_shnum; i++) {
119 elf_section_header_t *sechdr =
120 &((elf_section_header_t *)(((uint8_t *) header) +
121 header->e_shoff))[i];
122
123 int rc = section_header(sechdr, header, as);
124 if (rc != EE_OK)
125 return rc;
126 }
127
128 return EE_OK;
129}
130
131/** Print error message according to error code.
132 *
133 * @param rc Return code returned by elf_load().
134 *
135 * @return NULL terminated description of error.
136 *
137 */
138const char *elf_error(unsigned int rc)
139{
140 assert(rc < sizeof(error_codes) / sizeof(char *));
141
142 return error_codes[rc];
143}
144
145/** Process segment header.
146 *
147 * @param entry Segment header.
148 * @param elf ELF header.
149 * @param as Address space into wich the ELF is being loaded.
150 *
151 * @return EE_OK on success, error code otherwise.
152 *
153 */
154static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
155 as_t *as, unsigned int flags)
156{
157 switch (entry->p_type) {
158 case PT_NULL:
159 case PT_PHDR:
160 case PT_NOTE:
161 break;
162 case PT_LOAD:
163 return load_segment(entry, elf, as);
164 case PT_TLS:
165 break;
166 case PT_DYNAMIC:
167 case PT_INTERP:
168 // FIXME
169 /*
170 char *interp = (char *) elf + entry->p_offset;
171 if (memcmp((uintptr_t) interp, (uintptr_t) ELF_INTERP_ZSTR,
172 ELF_INTERP_ZLEN) != 0) {
173 return EE_UNSUPPORTED;
174 } */
175 if ((flags & ELD_F_LOADER) == 0)
176 return EE_LOADER;
177 break;
178 case PT_SHLIB:
179 case PT_LOPROC:
180 case PT_HIPROC:
181 default:
182 return EE_UNSUPPORTED;
183 }
184 return EE_OK;
185}
186
187/** Load segment described by program header entry.
188 *
189 * @param entry Program header entry describing segment to be loaded.
190 * @param elf ELF header.
191 * @param as Address space into wich the ELF is being loaded.
192 *
193 * @return EE_OK on success, error code otherwise.
194 *
195 */
196int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
197{
198 mem_backend_data_t backend_data;
199 backend_data.elf = elf;
200 backend_data.segment = entry;
201
202 if (entry->p_align > 1) {
203 if ((entry->p_offset % entry->p_align) !=
204 (entry->p_vaddr % entry->p_align))
205 return EE_INVALID;
206 }
207
208 unsigned int flags = 0;
209
210 if (entry->p_flags & PF_X)
211 flags |= AS_AREA_EXEC;
212
213 if (entry->p_flags & PF_W)
214 flags |= AS_AREA_WRITE;
215
216 if (entry->p_flags & PF_R)
217 flags |= AS_AREA_READ;
218
219 flags |= AS_AREA_CACHEABLE;
220
221 /*
222 * Align vaddr down, inserting a little "gap" at the beginning.
223 * Adjust area size, so that its end remains in place.
224 *
225 */
226 uintptr_t base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
227 size_t mem_sz = entry->p_memsz + (entry->p_vaddr - base);
228
229 as_area_t *area = as_area_create(as, flags, mem_sz,
230 AS_AREA_ATTR_NONE, &elf_backend, &backend_data, &base, 0);
231 if (!area)
232 return EE_MEMORY;
233
234 /*
235 * The segment will be mapped on demand by elf_page_fault().
236 *
237 */
238
239 return EE_OK;
240}
241
242/** Process section header.
243 *
244 * @param entry Segment header.
245 * @param elf ELF header.
246 * @param as Address space into wich the ELF is being loaded.
247 *
248 * @return EE_OK on success, error code otherwise.
249 *
250 */
251static int section_header(elf_section_header_t *entry, elf_header_t *elf,
252 as_t *as)
253{
254 switch (entry->sh_type) {
255 case SHT_PROGBITS:
256 if (entry->sh_flags & SHF_TLS) {
257 /* .tdata */
258 }
259 break;
260 case SHT_NOBITS:
261 if (entry->sh_flags & SHF_TLS) {
262 /* .tbss */
263 }
264 break;
265 default:
266 break;
267 }
268
269 return EE_OK;
270}
271
272/** @}
273 */
Note: See TracBrowser for help on using the repository browser.