Subversion Repositories HelenOS

Rev

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

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