Subversion Repositories HelenOS-historic

Rev

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

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