Subversion Repositories HelenOS

Rev

Rev 2071 | Rev 2574 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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