Subversion Repositories HelenOS

Rev

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

Rev 3222 Rev 3223
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
 * Copyright (c) 2008 Jiri Svoboda
4
 * Copyright (c) 2008 Jiri Svoboda
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 *
10
 *
11
 * - Redistributions of source code must retain the above copyright
11
 * - Redistributions of source code must retain the above copyright
12
 *   notice, this list of conditions and the following disclaimer.
12
 *   notice, this list of conditions and the following disclaimer.
13
 * - Redistributions in binary form must reproduce the above copyright
13
 * - Redistributions in binary form must reproduce the above copyright
14
 *   notice, this list of conditions and the following disclaimer in the
14
 *   notice, this list of conditions and the following disclaimer in the
15
 *   documentation and/or other materials provided with the distribution.
15
 *   documentation and/or other materials provided with the distribution.
16
 * - The name of the author may not be used to endorse or promote products
16
 * - The name of the author may not be used to endorse or promote products
17
 *   derived from this software without specific prior written permission.
17
 *   derived from this software without specific prior written permission.
18
 *
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
29
 */
30
 
30
 
31
/** @addtogroup generic
31
/** @addtogroup generic
32
 * @{
32
 * @{
33
 */
33
 */
34
 
34
 
35
/**
35
/**
36
 * @file
36
 * @file
37
 * @brief   Userspace ELF loader.
37
 * @brief   Userspace ELF loader.
38
 *
38
 *
39
 * This module allows loading ELF binaries (both executables and
39
 * This module allows loading ELF binaries (both executables and
40
 * shared objects) from VFS. The current implementation allocates
40
 * shared objects) from VFS. The current implementation allocates
41
 * anonymous memory, fills it with segment data and then adjusts
41
 * anonymous memory, fills it with segment data and then adjusts
42
 * the memory areas' flags to the final value. In the future,
42
 * the memory areas' flags to the final value. In the future,
43
 * the segments will be mapped directly from the file.
43
 * the segments will be mapped directly from the file.
44
 */
44
 */
45
 
45
 
46
#include <stdio.h>
46
#include <stdio.h>
47
#include <sys/types.h>
47
#include <sys/types.h>
48
#include <align.h>
48
#include <align.h>
49
#include <assert.h>
49
#include <assert.h>
50
#include <as.h>
50
#include <as.h>
51
#include <unistd.h>
51
#include <unistd.h>
52
#include <fcntl.h>
52
#include <fcntl.h>
53
#include <smc.h>
53
#include <smc.h>
54
#include <loader/pcb.h>
54
#include <loader/pcb.h>
55
 
55
 
56
#include "elf.h"
56
#include "elf.h"
57
#include "elf_load.h"
57
#include "elf_load.h"
58
#include "arch.h"
58
#include "arch.h"
59
 
59
 
60
static char *error_codes[] = {
60
static char *error_codes[] = {
61
    "no error",
61
    "no error",
62
    "invalid image",
62
    "invalid image",
63
    "address space error",
63
    "address space error",
64
    "incompatible image",
64
    "incompatible image",
65
    "unsupported image type",
65
    "unsupported image type",
66
    "irrecoverable error"
66
    "irrecoverable error"
67
};
67
};
68
 
68
 
69
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
69
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
70
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
70
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
71
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
71
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
72
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
72
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
73
 
73
 
74
/** Load ELF binary from a file.
74
/** Load ELF binary from a file.
75
 *
75
 *
76
 * Load an ELF binary from the specified file. If the file is
76
 * Load an ELF binary from the specified file. If the file is
77
 * an executable program, it is loaded unbiased. If it is a shared
77
 * an executable program, it is loaded unbiased. If it is a shared
78
 * object, it is loaded with the bias @a so_bias. Some information
78
 * object, it is loaded with the bias @a so_bias. Some information
79
 * extracted from the binary is stored in a elf_info_t structure
79
 * extracted from the binary is stored in a elf_info_t structure
80
 * pointed to by @a info.
80
 * pointed to by @a info.
81
 *
81
 *
82
 * @param file_name Path to the ELF file.
82
 * @param file_name Path to the ELF file.
83
 * @param so_bias   Bias to use if the file is a shared object.
83
 * @param so_bias   Bias to use if the file is a shared object.
84
 * @param info      Pointer to a structure for storing information
84
 * @param info      Pointer to a structure for storing information
85
 *          extracted from the binary.
85
 *          extracted from the binary.
86
 *
86
 *
87
 * @return EOK on success or negative error code.
87
 * @return EOK on success or negative error code.
88
 */
88
 */
89
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
89
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
90
{
90
{
91
    elf_ld_t elf;
91
    elf_ld_t elf;
92
 
92
 
93
    int fd;
93
    int fd;
94
    int rc;
94
    int rc;
95
 
95
 
96
//  printf("open and read '%s'...\n", file_name);
96
//  printf("open and read '%s'...\n", file_name);
97
 
97
 
98
    fd = open(file_name, O_RDONLY);
98
    fd = open(file_name, O_RDONLY);
99
    if (fd < 0) {
99
    if (fd < 0) {
100
        printf("failed opening file\n");
100
        printf("failed opening file\n");
101
        return -1;
101
        return -1;
102
    }
102
    }
103
 
103
 
104
    elf.fd = fd;
104
    elf.fd = fd;
105
    elf.info = info;
105
    elf.info = info;
106
 
106
 
107
    rc = elf_load(&elf, so_bias);
107
    rc = elf_load(&elf, so_bias);
108
 
108
 
109
    close(fd);
109
    close(fd);
110
 
110
 
111
    return rc;
111
    return rc;
112
}
112
}
113
 
113
 
114
/** Run an ELF executable.
114
/** Run an ELF executable.
115
 *
115
 *
116
 * Transfers control to the entry point of an ELF executable loaded
116
 * Transfers control to the entry point of an ELF executable loaded
117
 * earlier with elf_load_file(). This function does not return.
117
 * earlier with elf_load_file(). This function does not return.
118
 *
118
 *
119
 * @param info  Info structure filled earlier by elf_load_file()
119
 * @param info  Info structure filled earlier by elf_load_file()
120
 */
120
 */
121
void elf_run(elf_info_t *info, pcb_t *pcb)
121
void elf_run(elf_info_t *info, pcb_t *pcb)
122
{
122
{
123
    program_run(info->entry, pcb);
123
    program_run(info->entry, pcb);
124
 
124
 
125
    /* not reached */
125
    /* not reached */
126
}
126
}
127
 
127
 
128
/** Create the program control block (PCB).
128
/** Create the program control block (PCB).
129
 *
129
 *
130
 * Fills the program control block @a pcb with information from
130
 * Fills the program control block @a pcb with information from
131
 * @a info.
131
 * @a info.
132
 *
132
 *
133
 * @param info  Program info structure
133
 * @param info  Program info structure
134
 * @return EOK on success or negative error code
134
 * @return EOK on success or negative error code
135
 */
135
 */
136
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
136
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
137
{
137
{
138
    pcb->entry = info->entry;
138
    pcb->entry = info->entry;
139
    pcb->dynamic = info->dynamic;
139
    pcb->dynamic = info->dynamic;
140
}
140
}
141
 
141
 
142
 
142
 
143
/** Load an ELF binary.
143
/** Load an ELF binary.
144
 *
144
 *
145
 * The @a elf structure contains the loader state, including
145
 * The @a elf structure contains the loader state, including
146
 * an open file, from which the binary will be loaded,
146
 * an open file, from which the binary will be loaded,
147
 * a pointer to the @c info structure etc.
147
 * a pointer to the @c info structure etc.
148
 *
148
 *
149
 * @param elf       Pointer to loader state buffer.
149
 * @param elf       Pointer to loader state buffer.
150
 * @param so_bias   Bias to use if the file is a shared object.
150
 * @param so_bias   Bias to use if the file is a shared object.
151
 * @return EE_OK on success or EE_xx error code.
151
 * @return EE_OK on success or EE_xx error code.
152
 */
152
 */
153
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
153
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
154
{
154
{
155
    elf_header_t header_buf;
155
    elf_header_t header_buf;
156
    elf_header_t *header = &header_buf;
156
    elf_header_t *header = &header_buf;
157
    int i, rc;
157
    int i, rc;
158
 
158
 
159
    rc = read(elf->fd, header, sizeof(elf_header_t));
159
    rc = read(elf->fd, header, sizeof(elf_header_t));
160
    if (rc < 0) {
160
    if (rc < 0) {
161
        printf("read error\n");
161
        printf("read error\n");
162
        return EE_INVALID;
162
        return EE_INVALID;
163
    }
163
    }
164
 
164
 
165
    elf->header = header;
165
    elf->header = header;
166
 
166
 
167
//  printf("ELF-load:");
167
//  printf("ELF-load:");
168
    /* Identify ELF */
168
    /* Identify ELF */
169
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
169
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
170
        header->e_ident[EI_MAG1] != ELFMAG1 ||
170
        header->e_ident[EI_MAG1] != ELFMAG1 ||
171
        header->e_ident[EI_MAG2] != ELFMAG2 ||
171
        header->e_ident[EI_MAG2] != ELFMAG2 ||
172
        header->e_ident[EI_MAG3] != ELFMAG3) {
172
        header->e_ident[EI_MAG3] != ELFMAG3) {
173
        printf("invalid header\n");
173
        printf("invalid header\n");
174
        return EE_INVALID;
174
        return EE_INVALID;
175
    }
175
    }
176
   
176
   
177
    /* Identify ELF compatibility */
177
    /* Identify ELF compatibility */
178
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
178
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
179
        header->e_machine != ELF_MACHINE ||
179
        header->e_machine != ELF_MACHINE ||
180
        header->e_ident[EI_VERSION] != EV_CURRENT ||
180
        header->e_ident[EI_VERSION] != EV_CURRENT ||
181
        header->e_version != EV_CURRENT ||
181
        header->e_version != EV_CURRENT ||
182
        header->e_ident[EI_CLASS] != ELF_CLASS) {
182
        header->e_ident[EI_CLASS] != ELF_CLASS) {
183
        printf("incompatible data/version/class\n");
183
        printf("incompatible data/version/class\n");
184
        return EE_INCOMPATIBLE;
184
        return EE_INCOMPATIBLE;
185
    }
185
    }
186
 
186
 
187
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
187
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
188
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
188
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
189
            sizeof(elf_segment_header_t));
189
            sizeof(elf_segment_header_t));
190
        return EE_INCOMPATIBLE;
190
        return EE_INCOMPATIBLE;
191
    }
191
    }
192
 
192
 
193
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
193
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
194
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
194
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
195
            sizeof(elf_section_header_t));
195
            sizeof(elf_section_header_t));
196
        return EE_INCOMPATIBLE;
196
        return EE_INCOMPATIBLE;
197
    }
197
    }
198
 
198
 
199
    /* Check if the object type is supported. */
199
    /* Check if the object type is supported. */
200
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
200
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
201
        printf("Object type %d is not supported\n", header->e_type);
201
        printf("Object type %d is not supported\n", header->e_type);
202
        return EE_UNSUPPORTED;
202
        return EE_UNSUPPORTED;
203
    }
203
    }
204
 
204
 
205
    /* Shared objects can be loaded with a bias */
205
    /* Shared objects can be loaded with a bias */
206
//  printf("Object type: %d\n", header->e_type);
206
//  printf("Object type: %d\n", header->e_type);
207
    if (header->e_type == ET_DYN)
207
    if (header->e_type == ET_DYN)
208
        elf->bias = so_bias;
208
        elf->bias = so_bias;
209
    else
209
    else
210
        elf->bias = 0;
210
        elf->bias = 0;
211
 
211
 
212
//  printf("Bias set to 0x%x\n", elf->bias);
212
//  printf("Bias set to 0x%x\n", elf->bias);
213
    elf->info->interp = NULL;
213
    elf->info->interp = NULL;
214
    elf->info->dynamic = NULL;
214
    elf->info->dynamic = NULL;
215
 
215
 
216
//  printf("parse segments\n");
216
//  printf("parse segments\n");
217
 
217
 
218
    /* Walk through all segment headers and process them. */
218
    /* Walk through all segment headers and process them. */
219
    for (i = 0; i < header->e_phnum; i++) {
219
    for (i = 0; i < header->e_phnum; i++) {
220
        elf_segment_header_t segment_hdr;
220
        elf_segment_header_t segment_hdr;
221
 
221
 
222
        /* Seek to start of segment header */
222
        /* Seek to start of segment header */
223
        lseek(elf->fd, header->e_phoff
223
        lseek(elf->fd, header->e_phoff
224
                + i * sizeof(elf_segment_header_t), SEEK_SET);
224
                + i * sizeof(elf_segment_header_t), SEEK_SET);
225
 
225
 
226
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
226
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
-
 
227
        if (rc < 0) {
227
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
228
            printf("read error\n");
-
 
229
            return EE_INVALID;
-
 
230
        }
228
 
231
 
229
        rc = segment_header(elf, &segment_hdr);
232
        rc = segment_header(elf, &segment_hdr);
230
        if (rc != EE_OK)
233
        if (rc != EE_OK)
231
            return rc;
234
            return rc;
232
    }
235
    }
233
 
236
 
234
//  printf("parse sections\n");
237
//  printf("parse sections\n");
235
 
238
 
236
    /* Inspect all section headers and proccess them. */
239
    /* Inspect all section headers and proccess them. */
237
    for (i = 0; i < header->e_shnum; i++) {
240
    for (i = 0; i < header->e_shnum; i++) {
238
        elf_section_header_t section_hdr;
241
        elf_section_header_t section_hdr;
239
 
242
 
240
        /* Seek to start of section header */
243
        /* Seek to start of section header */
241
        lseek(elf->fd, header->e_shoff
244
        lseek(elf->fd, header->e_shoff
242
            + i * sizeof(elf_section_header_t), SEEK_SET);
245
            + i * sizeof(elf_section_header_t), SEEK_SET);
243
 
246
 
244
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
247
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
-
 
248
        if (rc < 0) {
245
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
249
            printf("read error\n");
-
 
250
            return EE_INVALID;
-
 
251
        }
246
 
252
 
247
        rc = section_header(elf, &section_hdr);
253
        rc = section_header(elf, &section_hdr);
248
        if (rc != EE_OK)
254
        if (rc != EE_OK)
249
            return rc;
255
            return rc;
250
    }
256
    }
251
 
257
 
252
    elf->info->entry =
258
    elf->info->entry =
253
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
259
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
254
 
260
 
255
//  printf("done\n");
261
//  printf("done\n");
256
 
262
 
257
    return EE_OK;
263
    return EE_OK;
258
}
264
}
259
 
265
 
260
/** Print error message according to error code.
266
/** Print error message according to error code.
261
 *
267
 *
262
 * @param rc Return code returned by elf_load().
268
 * @param rc Return code returned by elf_load().
263
 *
269
 *
264
 * @return NULL terminated description of error.
270
 * @return NULL terminated description of error.
265
 */
271
 */
266
char *elf_error(unsigned int rc)
272
char *elf_error(unsigned int rc)
267
{
273
{
268
    assert(rc < sizeof(error_codes) / sizeof(char *));
274
    assert(rc < sizeof(error_codes) / sizeof(char *));
269
 
275
 
270
    return error_codes[rc];
276
    return error_codes[rc];
271
}
277
}
272
 
278
 
273
/** Process segment header.
279
/** Process segment header.
274
 *
280
 *
275
 * @param entry Segment header.
281
 * @param entry Segment header.
276
 *
282
 *
277
 * @return EE_OK on success, error code otherwise.
283
 * @return EE_OK on success, error code otherwise.
278
 */
284
 */
279
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
285
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
280
{
286
{
281
    switch (entry->p_type) {
287
    switch (entry->p_type) {
282
    case PT_NULL:
288
    case PT_NULL:
283
    case PT_PHDR:
289
    case PT_PHDR:
284
        break;
290
        break;
285
    case PT_LOAD:
291
    case PT_LOAD:
286
        return load_segment(elf, entry);
292
        return load_segment(elf, entry);
287
        break;
293
        break;
288
    case PT_INTERP:
294
    case PT_INTERP:
289
        /* Assume silently interp == "/rtld.so" */
295
        /* Assume silently interp == "/rtld.so" */
290
        elf->info->interp = "/rtld.so";
296
        elf->info->interp = "/rtld.so";
291
        break;
297
        break;
292
    case PT_DYNAMIC:
298
    case PT_DYNAMIC:
293
    case PT_SHLIB:
299
    case PT_SHLIB:
294
    case PT_NOTE:
300
    case PT_NOTE:
295
    case PT_LOPROC:
301
    case PT_LOPROC:
296
    case PT_HIPROC:
302
    case PT_HIPROC:
297
    default:
303
    default:
298
        printf("segment p_type %d unknown\n", entry->p_type);
304
        printf("segment p_type %d unknown\n", entry->p_type);
299
        return EE_UNSUPPORTED;
305
        return EE_UNSUPPORTED;
300
        break;
306
        break;
301
    }
307
    }
302
    return EE_OK;
308
    return EE_OK;
303
}
309
}
304
 
310
 
305
/** Load segment described by program header entry.
311
/** Load segment described by program header entry.
306
 *
312
 *
307
 * @param elf   Loader state.
313
 * @param elf   Loader state.
308
 * @param entry Program header entry describing segment to be loaded.
314
 * @param entry Program header entry describing segment to be loaded.
309
 *
315
 *
310
 * @return EE_OK on success, error code otherwise.
316
 * @return EE_OK on success, error code otherwise.
311
 */
317
 */
312
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
318
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
313
{
319
{
314
    void *a;
320
    void *a;
315
    int flags = 0;
321
    int flags = 0;
316
    uintptr_t bias;
322
    uintptr_t bias;
317
    uintptr_t base;
323
    uintptr_t base;
318
    size_t mem_sz;
324
    size_t mem_sz;
319
    int rc;
325
    int rc;
320
 
326
 
321
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
327
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
322
//      entry->p_memsz);
328
//      entry->p_memsz);
323
   
329
   
324
    bias = elf->bias;
330
    bias = elf->bias;
325
 
331
 
326
    if (entry->p_align > 1) {
332
    if (entry->p_align > 1) {
327
        if ((entry->p_offset % entry->p_align) !=
333
        if ((entry->p_offset % entry->p_align) !=
328
            (entry->p_vaddr % entry->p_align)) {
334
            (entry->p_vaddr % entry->p_align)) {
329
            printf("align check 1 failed offset%%align=%d, vaddr%%align=%d\n",
335
            printf("align check 1 failed offset%%align=%d, "
-
 
336
                "vaddr%%align=%d\n",
330
            entry->p_offset % entry->p_align,
337
                entry->p_offset % entry->p_align,
331
            entry->p_vaddr % entry->p_align
338
                entry->p_vaddr % entry->p_align
332
            );
339
            );
333
            return EE_INVALID;
340
            return EE_INVALID;
334
        }
341
        }
335
    }
342
    }
336
 
343
 
337
    /* Final flags that will be set for the memory area */
344
    /* Final flags that will be set for the memory area */
338
 
345
 
339
    if (entry->p_flags & PF_X)
346
    if (entry->p_flags & PF_X)
340
        flags |= AS_AREA_EXEC;
347
        flags |= AS_AREA_EXEC;
341
    if (entry->p_flags & PF_W)
348
    if (entry->p_flags & PF_W)
342
        flags |= AS_AREA_WRITE;
349
        flags |= AS_AREA_WRITE;
343
    if (entry->p_flags & PF_R)
350
    if (entry->p_flags & PF_R)
344
        flags |= AS_AREA_READ;
351
        flags |= AS_AREA_READ;
345
    flags |= AS_AREA_CACHEABLE;
352
    flags |= AS_AREA_CACHEABLE;
346
   
353
   
347
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
354
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
348
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
355
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
349
 
356
 
350
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
357
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
351
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
358
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
352
 
359
 
353
    /*
360
    /*
354
     * For the course of loading, the area needs to be readable
361
     * For the course of loading, the area needs to be readable
355
     * and writeable.
362
     * and writeable.
356
     */
363
     */
357
    a = as_area_create((uint8_t *)base + bias,
364
    a = as_area_create((uint8_t *)base + bias,
358
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
365
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
359
    if (a == (void *)(-1)) {
366
    if (a == (void *)(-1)) {
360
        printf("memory mapping failed\n");
367
        printf("memory mapping failed\n");
361
        return EE_MEMORY;
368
        return EE_MEMORY;
362
    }
369
    }
363
 
370
 
364
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
371
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
365
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
372
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
366
 
373
 
367
    /*
374
    /*
368
     * Load segment data
375
     * Load segment data
369
     */
376
     */
370
//  printf("seek to %d\n", entry->p_offset);
377
//  printf("seek to %d\n", entry->p_offset);
371
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
378
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
-
 
379
    if (rc < 0) {
372
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
380
        printf("seek error\n");
-
 
381
        return EE_INVALID;
-
 
382
    }
373
 
383
 
374
//  printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
384
//  printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
375
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
385
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
376
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
386
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
377
 
387
 
378
    /* Long reads are not possible yet. Load segment picewise */
388
    /* Long reads are not possible yet. Load segment picewise */
379
 
389
 
380
    unsigned left, now;
390
    unsigned left, now;
381
    uint8_t *dp;
391
    uint8_t *dp;
382
 
392
 
383
    left = entry->p_filesz;
393
    left = entry->p_filesz;
384
    dp = (uint8_t *)(entry->p_vaddr + bias);
394
    dp = (uint8_t *)(entry->p_vaddr + bias);
385
 
395
 
386
    while (left > 0) {
396
    while (left > 0) {
387
        now = 16384;
397
        now = 16384;
388
        if (now > left) now = left;
398
        if (now > left) now = left;
389
 
399
 
390
//      printf("read %d...", now);
400
//      printf("read %d...", now);
391
        rc = read(elf->fd, dp, now);
401
        rc = read(elf->fd, dp, now);
392
//      printf("->%d\n", rc);
402
//      printf("->%d\n", rc);
393
 
403
 
-
 
404
        if (rc < 0) {
394
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
405
            printf("read error\n");
-
 
406
            return EE_INVALID;
-
 
407
        }
395
 
408
 
396
        left -= now;
409
        left -= now;
397
        dp += now;
410
        dp += now;
398
    }
411
    }
399
 
412
 
400
//  printf("set area flags to %d\n", flags);
413
//  printf("set area flags to %d\n", flags);
401
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
414
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
402
    if (rc != 0) {
415
    if (rc != 0) {
403
        printf("failed to set memory area flags\n");
416
        printf("failed to set memory area flags\n");
404
        return EE_MEMORY;
417
        return EE_MEMORY;
405
    }
418
    }
406
 
419
 
407
    if (flags & AS_AREA_EXEC) {
420
    if (flags & AS_AREA_EXEC) {
408
        /* Enforce SMC coherence for the segment */
421
        /* Enforce SMC coherence for the segment */
409
        if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
422
        if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
410
            return EE_MEMORY;
423
            return EE_MEMORY;
411
    }
424
    }
412
 
425
 
413
    return EE_OK;
426
    return EE_OK;
414
}
427
}
415
 
428
 
416
/** Process section header.
429
/** Process section header.
417
 *
430
 *
418
 * @param elf   Loader state.
431
 * @param elf   Loader state.
419
 * @param entry Segment header.
432
 * @param entry Segment header.
420
 *
433
 *
421
 * @return EE_OK on success, error code otherwise.
434
 * @return EE_OK on success, error code otherwise.
422
 */
435
 */
423
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
436
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
424
{
437
{
425
    switch (entry->sh_type) {
438
    switch (entry->sh_type) {
426
    case SHT_PROGBITS:
439
    case SHT_PROGBITS:
427
        if (entry->sh_flags & SHF_TLS) {
440
        if (entry->sh_flags & SHF_TLS) {
428
            /* .tdata */
441
            /* .tdata */
429
        }
442
        }
430
        break;
443
        break;
431
    case SHT_NOBITS:
444
    case SHT_NOBITS:
432
        if (entry->sh_flags & SHF_TLS) {
445
        if (entry->sh_flags & SHF_TLS) {
433
            /* .tbss */
446
            /* .tbss */
434
        }
447
        }
435
        break;
448
        break;
436
    case SHT_DYNAMIC:
449
    case SHT_DYNAMIC:
437
        /* Record pointer to dynamic section into info structure */
450
        /* Record pointer to dynamic section into info structure */
438
        elf->info->dynamic =
451
        elf->info->dynamic =
439
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
452
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
440
        printf("dynamic section found at 0x%x\n",
453
        printf("dynamic section found at 0x%x\n",
441
            (uintptr_t)elf->info->dynamic);
454
            (uintptr_t)elf->info->dynamic);
442
        break;
455
        break;
443
    default:
456
    default:
444
        break;
457
        break;
445
    }
458
    }
446
   
459
   
447
    return EE_OK;
460
    return EE_OK;
448
}
461
}
449
 
462
 
450
/** @}
463
/** @}
451
 */
464
 */
452
 
465