Subversion Repositories HelenOS

Rev

Rev 938 | Rev 963 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 938 Rev 952
Line 30... Line 30...
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
Line 68... Line 72...
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;
Line 98... Line 112...
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:
Line 130... Line 145...
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
        }
Line 159... Line 177...
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
}