Subversion Repositories HelenOS-historic

Rev

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

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