Subversion Repositories HelenOS-historic

Rev

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

Rev 952 Rev 963
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 <mm/slab.h>
36
#include <print.h>
36
#include <print.h>
37
#include <align.h>
37
#include <align.h>
38
#include <memstr.h>
38
#include <memstr.h>
39
#include <macros.h>
39
#include <macros.h>
40
 
40
 
41
static char *error_codes[] = {
41
static char *error_codes[] = {
42
    "no error",
42
    "no error",
43
    "invalid image",
43
    "invalid image",
44
    "address space error",
44
    "address space error",
45
    "incompatible image",
45
    "incompatible image",
46
    "unsupported image type",
46
    "unsupported image type",
47
    "irrecoverable error"
47
    "irrecoverable error"
48
};
48
};
49
 
49
 
50
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, 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);
51
static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as);
52
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
52
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
53
 
53
 
54
/** ELF loader
54
/** ELF loader
55
 *
55
 *
56
 * @param header Pointer to ELF header in memory
56
 * @param header Pointer to ELF header in memory
57
 * @param as Created and properly mapped address space
57
 * @param as Created and properly mapped address space
58
 * @return EE_OK on success
58
 * @return EE_OK on success
59
 */
59
 */
60
int elf_load(elf_header_t *header, as_t * as)
60
int elf_load(elf_header_t *header, as_t * as)
61
{
61
{
62
    int i, rc;
62
    int i, rc;
63
 
63
 
64
    /* Identify ELF */
64
    /* Identify ELF */
65
    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 ||
66
        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) {
67
        return EE_INVALID;
67
        return EE_INVALID;
68
    }
68
    }
69
   
69
   
70
    /* Identify ELF compatibility */
70
    /* Identify ELF compatibility */
71
    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 ||
72
        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 ||
73
        header->e_ident[EI_CLASS] != ELF_CLASS) {
73
        header->e_ident[EI_CLASS] != ELF_CLASS) {
74
        return EE_INCOMPATIBLE;
74
        return EE_INCOMPATIBLE;
75
    }
75
    }
76
 
76
 
77
    if (header->e_phentsize != sizeof(elf_segment_header_t))
77
    if (header->e_phentsize != sizeof(elf_segment_header_t))
78
        return EE_INCOMPATIBLE;
78
        return EE_INCOMPATIBLE;
79
 
79
 
80
    if (header->e_shentsize != sizeof(elf_section_header_t))
80
    if (header->e_shentsize != sizeof(elf_section_header_t))
81
        return EE_INCOMPATIBLE;
81
        return EE_INCOMPATIBLE;
82
 
82
 
83
    /* Check if the object type is supported. */
83
    /* Check if the object type is supported. */
84
    if (header->e_type != ET_EXEC)
84
    if (header->e_type != ET_EXEC)
85
        return EE_UNSUPPORTED;
85
        return EE_UNSUPPORTED;
86
 
86
 
87
    /* Walk through all segment headers and process them. */
87
    /* Walk through all segment headers and process them. */
88
    for (i = 0; i < header->e_phnum; i++) {
88
    for (i = 0; i < header->e_phnum; i++) {
89
        rc = segment_header(&((elf_segment_header_t *)(((__u8 *) header) + header->e_phoff))[i], header, as);
89
        rc = segment_header(&((elf_segment_header_t *)(((__u8 *) header) + header->e_phoff))[i], header, as);
90
        if (rc != EE_OK)
90
        if (rc != EE_OK)
91
            return rc;
91
            return rc;
92
    }
92
    }
93
 
93
 
94
    /* Inspect all section headers and proccess them. */
94
    /* Inspect all section headers and proccess them. */
95
    for (i = 0; i < header->e_shnum; i++) {
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);
96
        rc = section_header(&((elf_section_header_t *)(((__u8 *) header) + header->e_shoff))[i], header, as);
97
        if (rc != EE_OK)
97
        if (rc != EE_OK)
98
            return rc;
98
            return rc;
99
    }
99
    }
100
 
100
 
101
    return EE_OK;
101
    return EE_OK;
102
}
102
}
103
 
103
 
104
/** Print error message according to error code.
104
/** Print error message according to error code.
105
 *
105
 *
106
 * @param rc Return code returned by elf_load().
106
 * @param rc Return code returned by elf_load().
107
 *
107
 *
108
 * @return NULL terminated description of error.
108
 * @return NULL terminated description of error.
109
 */
109
 */
110
char *elf_error(int rc)
110
char *elf_error(int rc)
111
{
111
{
112
    ASSERT(rc < sizeof(error_codes)/sizeof(char *));
112
    ASSERT(rc < sizeof(error_codes)/sizeof(char *));
113
 
113
 
114
    return error_codes[rc];
114
    return error_codes[rc];
115
}
115
}
116
 
116
 
117
/** Process segment header.
117
/** Process segment header.
118
 *
118
 *
119
 * @param entry Segment header.
119
 * @param entry Segment header.
120
 * @param elf ELF header.
120
 * @param elf ELF header.
121
 * @param as Address space into wich the ELF is being loaded.
121
 * @param as Address space into wich the ELF is being loaded.
122
 *
122
 *
123
 * @return EE_OK on success, error code otherwise.
123
 * @return EE_OK on success, error code otherwise.
124
 */
124
 */
125
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
125
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
126
{
126
{
127
    switch (entry->p_type) {
127
    switch (entry->p_type) {
128
        case PT_NULL:
128
        case PT_NULL:
129
        case PT_PHDR:
129
        case PT_PHDR:
130
        break;
130
        break;
131
        case PT_LOAD:
131
        case PT_LOAD:
132
        return load_segment(entry, elf, as);
132
        return load_segment(entry, elf, as);
133
        break;
133
        break;
134
        case PT_DYNAMIC:
134
        case PT_DYNAMIC:
135
        case PT_INTERP:
135
        case PT_INTERP:
136
        case PT_SHLIB:
136
        case PT_SHLIB:
137
        case PT_NOTE:
137
        case PT_NOTE:
138
        case PT_LOPROC:
138
        case PT_LOPROC:
139
        case PT_HIPROC:
139
        case PT_HIPROC:
140
        default:
140
        default:
141
        return EE_UNSUPPORTED;
141
        return EE_UNSUPPORTED;
142
        break;
142
        break;
143
    }
143
    }
144
    return EE_OK;
144
    return EE_OK;
145
}
145
}
146
 
146
 
147
/** Load segment described by program header entry.
147
/** Load segment described by program header entry.
148
 *
148
 *
149
 * @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.
150
 * @param elf ELF header.
151
 * @parma as Address space into wich the ELF is being loaded.
151
 * @parma as Address space into wich the ELF is being loaded.
152
 *
152
 *
153
 * @return EE_OK on success, error code otherwise.
153
 * @return EE_OK on success, error code otherwise.
154
 */
154
 */
155
int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
155
int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as)
156
{
156
{
157
    as_area_t *a;
157
    as_area_t *a;
158
    int i, type = 0;
158
    int i, type = 0;
159
    size_t segment_size;
159
    size_t segment_size;
160
    __u8 *segment;
160
    __u8 *segment;
161
 
161
 
162
    if (entry->p_align > 1) {
162
    if (entry->p_align > 1) {
163
        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)) {
164
            return EE_INVALID;
164
            return EE_INVALID;
165
        }
165
        }
166
    }
166
    }
167
 
167
 
168
    /*
168
    /*
169
     * Check if the segment doesn't interfere with kernel address space.
169
     * Check if the segment doesn't interfere with kernel address space.
170
     */
170
     */
171
    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)
172
        return EE_MEMORY;
172
        return EE_MEMORY;
173
   
173
   
174
    if (entry->p_flags & PF_X) {
174
    if (entry->p_flags & PF_X) {
175
        type = AS_AREA_TEXT;
175
        type = AS_AREA_TEXT;
176
    } else if (entry->p_flags & PF_W) {
176
    } else if (entry->p_flags & PF_W) {
177
        type = AS_AREA_DATA;
177
        type = AS_AREA_DATA;
178
    } else {
178
    } else {
179
        return EE_UNSUPPORTED;
179
        return EE_UNSUPPORTED;
180
    }
180
    }
181
 
181
 
182
    /*
182
    /*
183
     * Check if the virtual address starts on page boundary.
183
     * Check if the virtual address starts on page boundary.
184
     */
184
     */
185
    if (ALIGN_UP(entry->p_vaddr, PAGE_SIZE) != entry->p_vaddr)
185
    if (ALIGN_UP(entry->p_vaddr, PAGE_SIZE) != entry->p_vaddr)
186
        return EE_UNSUPPORTED;
186
        return EE_UNSUPPORTED;
187
 
187
 
188
    /*
188
    /*
189
     * Copying the segment out is certainly necessary for segments with p_filesz < p_memsz
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
190
     * because of the effect of .bss-like sections. For security reasons, it looks like a
191
     * good idea to copy the segment anyway.
191
     * good idea to copy the segment anyway.
192
     */
192
     */
193
    segment_size = ALIGN_UP(max(entry->p_filesz, entry->p_memsz), PAGE_SIZE);
193
    segment_size = ALIGN_UP(max(entry->p_filesz, entry->p_memsz), PAGE_SIZE);
194
    segment = malloc(segment_size, 0);
194
    segment = malloc(segment_size, 0);
195
    if (entry->p_filesz < entry->p_memsz)
195
    if (entry->p_filesz < entry->p_memsz)
196
        memsetb((__address) (segment + entry->p_filesz), segment_size - entry->p_filesz, 0);
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);
197
    memcpy(segment, (void *) (((__address) elf) + entry->p_offset), entry->p_filesz);
198
 
198
 
199
    a = as_area_create(as, AS_AREA_TEXT, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
199
    a = as_area_create(as, type, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
200
    if (!a)
200
    if (!a)
201
        return EE_IRRECOVERABLE;
201
        return EE_IRRECOVERABLE;
202
   
202
   
203
    for (i = 0; i < SIZE2FRAMES(entry->p_filesz); i++) {
203
    for (i = 0; i < SIZE2FRAMES(entry->p_filesz); i++) {
204
        as_set_mapping(as, entry->p_vaddr + i*PAGE_SIZE, KA2PA(((__address) segment) + i*PAGE_SIZE));
204
        as_set_mapping(as, entry->p_vaddr + i*PAGE_SIZE, KA2PA(((__address) segment) + i*PAGE_SIZE));
205
    }
205
    }
206
   
206
   
207
    return EE_OK;
207
    return EE_OK;
208
}
208
}
209
 
209
 
210
/** Process section header.
210
/** Process section header.
211
 *
211
 *
212
 * @param entry Segment header.
212
 * @param entry Segment header.
213
 * @param elf ELF header.
213
 * @param elf ELF header.
214
 * @param as Address space into wich the ELF is being loaded.
214
 * @param as Address space into wich the ELF is being loaded.
215
 *
215
 *
216
 * @return EE_OK on success, error code otherwise.
216
 * @return EE_OK on success, error code otherwise.
217
 */
217
 */
218
static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as)
218
static int section_header(elf_section_header_t *entry, elf_header_t *elf, as_t *as)
219
{
219
{
220
    switch (entry->sh_type) {
220
    switch (entry->sh_type) {
221
        default:
221
        default:
222
        break;
222
        break;
223
    }
223
    }
224
   
224
   
225
    return EE_OK;
225
    return EE_OK;
226
}
226
}
227
 
227