Subversion Repositories HelenOS-historic

Rev

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

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