Subversion Repositories HelenOS

Rev

Rev 4377 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4377 Rev 4692
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
#define DPRINTF(...)
60
#define DPRINTF(...)
61
 
61
 
62
static char *error_codes[] = {
62
static char *error_codes[] = {
63
    "no error",
63
    "no error",
64
    "invalid image",
64
    "invalid image",
65
    "address space error",
65
    "address space error",
66
    "incompatible image",
66
    "incompatible image",
67
    "unsupported image type",
67
    "unsupported image type",
68
    "irrecoverable error"
68
    "irrecoverable error"
69
};
69
};
70
 
70
 
71
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
71
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
72
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
72
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
73
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
73
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
74
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
74
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
75
 
75
 
76
/** Read until the buffer is read in its entirety. */
76
/** Read until the buffer is read in its entirety. */
77
static int my_read(int fd, char *buf, size_t len)
77
static int my_read(int fd, void *buf, size_t len)
78
{
78
{
79
    int cnt = 0;
79
    int cnt = 0;
80
    do {
80
    do {
81
        buf += cnt;
81
        buf += cnt;
82
        len -= cnt;
82
        len -= cnt;
83
        cnt = read(fd, buf, len);
83
        cnt = read(fd, buf, len);
84
    } while ((cnt > 0) && ((len - cnt) > 0));
84
    } while ((cnt > 0) && ((len - cnt) > 0));
85
 
85
 
86
    return cnt;
86
    return cnt;
87
}
87
}
88
 
88
 
89
/** Load ELF binary from a file.
89
/** Load ELF binary from a file.
90
 *
90
 *
91
 * Load an ELF binary from the specified file. If the file is
91
 * Load an ELF binary from the specified file. If the file is
92
 * an executable program, it is loaded unbiased. If it is a shared
92
 * an executable program, it is loaded unbiased. If it is a shared
93
 * object, it is loaded with the bias @a so_bias. Some information
93
 * object, it is loaded with the bias @a so_bias. Some information
94
 * extracted from the binary is stored in a elf_info_t structure
94
 * extracted from the binary is stored in a elf_info_t structure
95
 * pointed to by @a info.
95
 * pointed to by @a info.
96
 *
96
 *
97
 * @param file_name Path to the ELF file.
97
 * @param file_name Path to the ELF file.
98
 * @param so_bias   Bias to use if the file is a shared object.
98
 * @param so_bias   Bias to use if the file is a shared object.
99
 * @param info      Pointer to a structure for storing information
99
 * @param info      Pointer to a structure for storing information
100
 *          extracted from the binary.
100
 *          extracted from the binary.
101
 *
101
 *
102
 * @return EOK on success or negative error code.
102
 * @return EOK on success or negative error code.
103
 */
103
 */
104
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
104
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
105
{
105
{
106
    elf_ld_t elf;
106
    elf_ld_t elf;
107
 
107
 
108
    int fd;
108
    int fd;
109
    int rc;
109
    int rc;
110
 
110
 
111
    fd = open(file_name, O_RDONLY);
111
    fd = open(file_name, O_RDONLY);
112
    if (fd < 0) {
112
    if (fd < 0) {
113
        DPRINTF("failed opening file\n");
113
        DPRINTF("failed opening file\n");
114
        return -1;
114
        return -1;
115
    }
115
    }
116
 
116
 
117
    elf.fd = fd;
117
    elf.fd = fd;
118
    elf.info = info;
118
    elf.info = info;
119
 
119
 
120
    rc = elf_load(&elf, so_bias);
120
    rc = elf_load(&elf, so_bias);
121
 
121
 
122
    close(fd);
122
    close(fd);
123
 
123
 
124
    return rc;
124
    return rc;
125
}
125
}
126
 
126
 
127
/** Run an ELF executable.
127
/** Run an ELF executable.
128
 *
128
 *
129
 * Transfers control to the entry point of an ELF executable loaded
129
 * Transfers control to the entry point of an ELF executable loaded
130
 * earlier with elf_load_file(). This function does not return.
130
 * earlier with elf_load_file(). This function does not return.
131
 *
131
 *
132
 * @param info  Info structure filled earlier by elf_load_file()
132
 * @param info  Info structure filled earlier by elf_load_file()
133
 */
133
 */
134
void elf_run(elf_info_t *info, pcb_t *pcb)
134
void elf_run(elf_info_t *info, pcb_t *pcb)
135
{
135
{
136
    program_run(info->entry, pcb);
136
    program_run(info->entry, pcb);
137
 
137
 
138
    /* not reached */
138
    /* not reached */
139
}
139
}
140
 
140
 
141
/** Create the program control block (PCB).
141
/** Create the program control block (PCB).
142
 *
142
 *
143
 * Fills the program control block @a pcb with information from
143
 * Fills the program control block @a pcb with information from
144
 * @a info.
144
 * @a info.
145
 *
145
 *
146
 * @param info  Program info structure
146
 * @param info  Program info structure
147
 * @return EOK on success or negative error code
147
 * @return EOK on success or negative error code
148
 */
148
 */
149
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
149
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
150
{
150
{
151
    pcb->entry = info->entry;
151
    pcb->entry = info->entry;
152
    pcb->dynamic = info->dynamic;
152
    pcb->dynamic = info->dynamic;
153
}
153
}
154
 
154
 
155
 
155
 
156
/** Load an ELF binary.
156
/** Load an ELF binary.
157
 *
157
 *
158
 * The @a elf structure contains the loader state, including
158
 * The @a elf structure contains the loader state, including
159
 * an open file, from which the binary will be loaded,
159
 * an open file, from which the binary will be loaded,
160
 * a pointer to the @c info structure etc.
160
 * a pointer to the @c info structure etc.
161
 *
161
 *
162
 * @param elf       Pointer to loader state buffer.
162
 * @param elf       Pointer to loader state buffer.
163
 * @param so_bias   Bias to use if the file is a shared object.
163
 * @param so_bias   Bias to use if the file is a shared object.
164
 * @return EE_OK on success or EE_xx error code.
164
 * @return EE_OK on success or EE_xx error code.
165
 */
165
 */
166
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
166
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
167
{
167
{
168
    elf_header_t header_buf;
168
    elf_header_t header_buf;
169
    elf_header_t *header = &header_buf;
169
    elf_header_t *header = &header_buf;
170
    int i, rc;
170
    int i, rc;
171
 
171
 
172
    rc = my_read(elf->fd, header, sizeof(elf_header_t));
172
    rc = my_read(elf->fd, header, sizeof(elf_header_t));
173
    if (rc < 0) {
173
    if (rc < 0) {
174
        DPRINTF("Read error.\n");
174
        DPRINTF("Read error.\n");
175
        return EE_INVALID;
175
        return EE_INVALID;
176
    }
176
    }
177
 
177
 
178
    elf->header = header;
178
    elf->header = header;
179
 
179
 
180
    /* Identify ELF */
180
    /* Identify ELF */
181
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
181
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
182
        header->e_ident[EI_MAG1] != ELFMAG1 ||
182
        header->e_ident[EI_MAG1] != ELFMAG1 ||
183
        header->e_ident[EI_MAG2] != ELFMAG2 ||
183
        header->e_ident[EI_MAG2] != ELFMAG2 ||
184
        header->e_ident[EI_MAG3] != ELFMAG3) {
184
        header->e_ident[EI_MAG3] != ELFMAG3) {
185
        DPRINTF("Invalid header.\n");
185
        DPRINTF("Invalid header.\n");
186
        return EE_INVALID;
186
        return EE_INVALID;
187
    }
187
    }
188
   
188
   
189
    /* Identify ELF compatibility */
189
    /* Identify ELF compatibility */
190
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
190
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
191
        header->e_machine != ELF_MACHINE ||
191
        header->e_machine != ELF_MACHINE ||
192
        header->e_ident[EI_VERSION] != EV_CURRENT ||
192
        header->e_ident[EI_VERSION] != EV_CURRENT ||
193
        header->e_version != EV_CURRENT ||
193
        header->e_version != EV_CURRENT ||
194
        header->e_ident[EI_CLASS] != ELF_CLASS) {
194
        header->e_ident[EI_CLASS] != ELF_CLASS) {
195
        DPRINTF("Incompatible data/version/class.\n");
195
        DPRINTF("Incompatible data/version/class.\n");
196
        return EE_INCOMPATIBLE;
196
        return EE_INCOMPATIBLE;
197
    }
197
    }
198
 
198
 
199
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
199
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
200
        DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
200
        DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
201
            sizeof(elf_segment_header_t));
201
            sizeof(elf_segment_header_t));
202
        return EE_INCOMPATIBLE;
202
        return EE_INCOMPATIBLE;
203
    }
203
    }
204
 
204
 
205
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
205
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
206
        DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
206
        DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
207
            sizeof(elf_section_header_t));
207
            sizeof(elf_section_header_t));
208
        return EE_INCOMPATIBLE;
208
        return EE_INCOMPATIBLE;
209
    }
209
    }
210
 
210
 
211
    /* Check if the object type is supported. */
211
    /* Check if the object type is supported. */
212
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
212
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
213
        DPRINTF("Object type %d is not supported\n", header->e_type);
213
        DPRINTF("Object type %d is not supported\n", header->e_type);
214
        return EE_UNSUPPORTED;
214
        return EE_UNSUPPORTED;
215
    }
215
    }
216
 
216
 
217
    /* Shared objects can be loaded with a bias */
217
    /* Shared objects can be loaded with a bias */
218
    if (header->e_type == ET_DYN)
218
    if (header->e_type == ET_DYN)
219
        elf->bias = so_bias;
219
        elf->bias = so_bias;
220
    else
220
    else
221
        elf->bias = 0;
221
        elf->bias = 0;
222
 
222
 
223
    elf->info->interp = NULL;
223
    elf->info->interp = NULL;
224
    elf->info->dynamic = NULL;
224
    elf->info->dynamic = NULL;
225
 
225
 
226
    /* Walk through all segment headers and process them. */
226
    /* Walk through all segment headers and process them. */
227
    for (i = 0; i < header->e_phnum; i++) {
227
    for (i = 0; i < header->e_phnum; i++) {
228
        elf_segment_header_t segment_hdr;
228
        elf_segment_header_t segment_hdr;
229
 
229
 
230
        /* Seek to start of segment header */
230
        /* Seek to start of segment header */
231
        lseek(elf->fd, header->e_phoff
231
        lseek(elf->fd, header->e_phoff
232
                + i * sizeof(elf_segment_header_t), SEEK_SET);
232
                + i * sizeof(elf_segment_header_t), SEEK_SET);
233
 
233
 
234
        rc = my_read(elf->fd, &segment_hdr,
234
        rc = my_read(elf->fd, &segment_hdr,
235
            sizeof(elf_segment_header_t));
235
            sizeof(elf_segment_header_t));
236
        if (rc < 0) {
236
        if (rc < 0) {
237
            DPRINTF("Read error.\n");
237
            DPRINTF("Read error.\n");
238
            return EE_INVALID;
238
            return EE_INVALID;
239
        }
239
        }
240
 
240
 
241
        rc = segment_header(elf, &segment_hdr);
241
        rc = segment_header(elf, &segment_hdr);
242
        if (rc != EE_OK)
242
        if (rc != EE_OK)
243
            return rc;
243
            return rc;
244
    }
244
    }
245
 
245
 
246
    DPRINTF("Parse sections.\n");
246
    DPRINTF("Parse sections.\n");
247
 
247
 
248
    /* Inspect all section headers and proccess them. */
248
    /* Inspect all section headers and proccess them. */
249
    for (i = 0; i < header->e_shnum; i++) {
249
    for (i = 0; i < header->e_shnum; i++) {
250
        elf_section_header_t section_hdr;
250
        elf_section_header_t section_hdr;
251
 
251
 
252
        /* Seek to start of section header */
252
        /* Seek to start of section header */
253
        lseek(elf->fd, header->e_shoff
253
        lseek(elf->fd, header->e_shoff
254
            + i * sizeof(elf_section_header_t), SEEK_SET);
254
            + i * sizeof(elf_section_header_t), SEEK_SET);
255
 
255
 
256
        rc = my_read(elf->fd, &section_hdr,
256
        rc = my_read(elf->fd, &section_hdr,
257
            sizeof(elf_section_header_t));
257
            sizeof(elf_section_header_t));
258
        if (rc < 0) {
258
        if (rc < 0) {
259
            DPRINTF("Read error.\n");
259
            DPRINTF("Read error.\n");
260
            return EE_INVALID;
260
            return EE_INVALID;
261
        }
261
        }
262
 
262
 
263
        rc = section_header(elf, &section_hdr);
263
        rc = section_header(elf, &section_hdr);
264
        if (rc != EE_OK)
264
        if (rc != EE_OK)
265
            return rc;
265
            return rc;
266
    }
266
    }
267
 
267
 
268
    elf->info->entry =
268
    elf->info->entry =
269
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
269
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
270
 
270
 
271
    DPRINTF("Done.\n");
271
    DPRINTF("Done.\n");
272
 
272
 
273
    return EE_OK;
273
    return EE_OK;
274
}
274
}
275
 
275
 
276
/** Print error message according to error code.
276
/** Print error message according to error code.
277
 *
277
 *
278
 * @param rc Return code returned by elf_load().
278
 * @param rc Return code returned by elf_load().
279
 *
279
 *
280
 * @return NULL terminated description of error.
280
 * @return NULL terminated description of error.
281
 */
281
 */
282
char *elf_error(unsigned int rc)
282
char *elf_error(unsigned int rc)
283
{
283
{
284
    assert(rc < sizeof(error_codes) / sizeof(char *));
284
    assert(rc < sizeof(error_codes) / sizeof(char *));
285
 
285
 
286
    return error_codes[rc];
286
    return error_codes[rc];
287
}
287
}
288
 
288
 
289
/** Process segment header.
289
/** Process segment header.
290
 *
290
 *
291
 * @param entry Segment header.
291
 * @param entry Segment header.
292
 *
292
 *
293
 * @return EE_OK on success, error code otherwise.
293
 * @return EE_OK on success, error code otherwise.
294
 */
294
 */
295
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
295
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
296
{
296
{
297
    switch (entry->p_type) {
297
    switch (entry->p_type) {
298
    case PT_NULL:
298
    case PT_NULL:
299
    case PT_PHDR:
299
    case PT_PHDR:
300
        break;
300
        break;
301
    case PT_LOAD:
301
    case PT_LOAD:
302
        return load_segment(elf, entry);
302
        return load_segment(elf, entry);
303
        break;
303
        break;
304
    case PT_INTERP:
304
    case PT_INTERP:
305
        /* Assume silently interp == "/rtld.so" */
305
        /* Assume silently interp == "/rtld.so" */
306
        elf->info->interp = "/rtld.so";
306
        elf->info->interp = "/rtld.so";
307
        break;
307
        break;
308
    case PT_DYNAMIC:
308
    case PT_DYNAMIC:
309
    case PT_SHLIB:
309
    case PT_SHLIB:
310
    case PT_NOTE:
310
    case PT_NOTE:
311
    case PT_LOPROC:
311
    case PT_LOPROC:
312
    case PT_HIPROC:
312
    case PT_HIPROC:
313
    default:
313
    default:
314
        DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
314
        DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
315
        return EE_UNSUPPORTED;
315
        return EE_UNSUPPORTED;
316
        break;
316
        break;
317
    }
317
    }
318
    return EE_OK;
318
    return EE_OK;
319
}
319
}
320
 
320
 
321
/** Load segment described by program header entry.
321
/** Load segment described by program header entry.
322
 *
322
 *
323
 * @param elf   Loader state.
323
 * @param elf   Loader state.
324
 * @param entry Program header entry describing segment to be loaded.
324
 * @param entry Program header entry describing segment to be loaded.
325
 *
325
 *
326
 * @return EE_OK on success, error code otherwise.
326
 * @return EE_OK on success, error code otherwise.
327
 */
327
 */
328
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
328
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
329
{
329
{
330
    void *a;
330
    void *a;
331
    int flags = 0;
331
    int flags = 0;
332
    uintptr_t bias;
332
    uintptr_t bias;
333
    uintptr_t base;
333
    uintptr_t base;
-
 
334
    void *seg_ptr;
-
 
335
    uintptr_t seg_addr;
334
    size_t mem_sz;
336
    size_t mem_sz;
335
    int rc;
337
    int rc;
336
 
338
 
337
    DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
-
 
338
        entry->p_memsz);
-
 
339
   
-
 
340
    bias = elf->bias;
339
    bias = elf->bias;
341
 
340
 
-
 
341
    seg_addr = entry->p_vaddr + bias;
-
 
342
    seg_ptr = (void *) seg_addr;
-
 
343
 
-
 
344
    DPRINTF("Load segment at addr 0x%x, size 0x%x\n", seg_addr,
-
 
345
        entry->p_memsz);   
-
 
346
 
342
    if (entry->p_align > 1) {
347
    if (entry->p_align > 1) {
343
        if ((entry->p_offset % entry->p_align) !=
348
        if ((entry->p_offset % entry->p_align) !=
344
            (entry->p_vaddr % entry->p_align)) {
349
            (seg_addr % entry->p_align)) {
345
            DPRINTF("Align check 1 failed offset%%align=%d, "
350
            DPRINTF("Align check 1 failed offset%%align=%d, "
346
                "vaddr%%align=%d\n",
351
                "vaddr%%align=%d\n",
347
                entry->p_offset % entry->p_align,
352
                entry->p_offset % entry->p_align,
348
                entry->p_vaddr % entry->p_align
353
                seg_addr % entry->p_align
349
            );
354
            );
350
            return EE_INVALID;
355
            return EE_INVALID;
351
        }
356
        }
352
    }
357
    }
353
 
358
 
354
    /* Final flags that will be set for the memory area */
359
    /* Final flags that will be set for the memory area */
355
 
360
 
356
    if (entry->p_flags & PF_X)
361
    if (entry->p_flags & PF_X)
357
        flags |= AS_AREA_EXEC;
362
        flags |= AS_AREA_EXEC;
358
    if (entry->p_flags & PF_W)
363
    if (entry->p_flags & PF_W)
359
        flags |= AS_AREA_WRITE;
364
        flags |= AS_AREA_WRITE;
360
    if (entry->p_flags & PF_R)
365
    if (entry->p_flags & PF_R)
361
        flags |= AS_AREA_READ;
366
        flags |= AS_AREA_READ;
362
    flags |= AS_AREA_CACHEABLE;
367
    flags |= AS_AREA_CACHEABLE;
363
   
368
   
364
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
369
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
365
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
370
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
366
 
371
 
367
    DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias,
372
    DPRINTF("Map to seg_addr=0x%x-0x%x.\n", seg_addr,
368
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
373
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
369
 
374
 
370
    /*
375
    /*
371
     * For the course of loading, the area needs to be readable
376
     * For the course of loading, the area needs to be readable
372
     * and writeable.
377
     * and writeable.
373
     */
378
     */
374
    a = as_area_create((uint8_t *)base + bias, mem_sz,
379
    a = as_area_create((uint8_t *)base + bias, mem_sz,
375
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
380
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
376
    if (a == (void *)(-1)) {
381
    if (a == (void *)(-1)) {
377
        DPRINTF("Memory mapping failed.\n");
382
        DPRINTF("Memory mapping failed.\n");
378
        return EE_MEMORY;
383
        return EE_MEMORY;
379
    }
384
    }
380
 
385
 
381
    DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
386
    DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
382
        entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
387
        base + bias, mem_sz, flags, (uintptr_t)a);
383
 
388
 
384
    /*
389
    /*
385
     * Load segment data
390
     * Load segment data
386
     */
391
     */
387
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
392
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
388
    if (rc < 0) {
393
    if (rc < 0) {
389
        printf("seek error\n");
394
        printf("seek error\n");
390
        return EE_INVALID;
395
        return EE_INVALID;
391
    }
396
    }
392
 
397
 
393
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
398
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
394
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
399
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
395
 
400
 
396
    /* Long reads are not possible yet. Load segment piecewise. */
401
    /* Long reads are not possible yet. Load segment piecewise. */
397
 
402
 
398
    unsigned left, now;
403
    unsigned left, now;
399
    uint8_t *dp;
404
    uint8_t *dp;
400
 
405
 
401
    left = entry->p_filesz;
406
    left = entry->p_filesz;
402
    dp = (uint8_t *)(entry->p_vaddr + bias);
407
    dp = seg_ptr;
403
 
408
 
404
    while (left > 0) {
409
    while (left > 0) {
405
        now = 16384;
410
        now = 16384;
406
        if (now > left) now = left;
411
        if (now > left) now = left;
407
 
412
 
408
        rc = my_read(elf->fd, dp, now);
413
        rc = my_read(elf->fd, dp, now);
409
 
414
 
410
        if (rc < 0) {
415
        if (rc < 0) {
411
            DPRINTF("Read error.\n");
416
            DPRINTF("Read error.\n");
412
            return EE_INVALID;
417
            return EE_INVALID;
413
        }
418
        }
414
 
419
 
415
        left -= now;
420
        left -= now;
416
        dp += now;
421
        dp += now;
417
    }
422
    }
418
 
423
 
419
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
424
    rc = as_area_change_flags(seg_ptr, flags);
420
    if (rc != 0) {
425
    if (rc != 0) {
421
        DPRINTF("Failed to set memory area flags.\n");
426
        DPRINTF("Failed to set memory area flags.\n");
422
        return EE_MEMORY;
427
        return EE_MEMORY;
423
    }
428
    }
424
 
429
 
425
    if (flags & AS_AREA_EXEC) {
430
    if (flags & AS_AREA_EXEC) {
426
        /* Enforce SMC coherence for the segment */
431
        /* Enforce SMC coherence for the segment */
427
        if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
432
        if (smc_coherence(seg_ptr, entry->p_filesz))
428
            return EE_MEMORY;
433
            return EE_MEMORY;
429
    }
434
    }
430
 
435
 
431
    return EE_OK;
436
    return EE_OK;
432
}
437
}
433
 
438
 
434
/** Process section header.
439
/** Process section header.
435
 *
440
 *
436
 * @param elf   Loader state.
441
 * @param elf   Loader state.
437
 * @param entry Segment header.
442
 * @param entry Segment header.
438
 *
443
 *
439
 * @return EE_OK on success, error code otherwise.
444
 * @return EE_OK on success, error code otherwise.
440
 */
445
 */
441
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
446
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
442
{
447
{
443
    switch (entry->sh_type) {
448
    switch (entry->sh_type) {
444
    case SHT_PROGBITS:
449
    case SHT_PROGBITS:
445
        if (entry->sh_flags & SHF_TLS) {
450
        if (entry->sh_flags & SHF_TLS) {
446
            /* .tdata */
451
            /* .tdata */
447
        }
452
        }
448
        break;
453
        break;
449
    case SHT_NOBITS:
454
    case SHT_NOBITS:
450
        if (entry->sh_flags & SHF_TLS) {
455
        if (entry->sh_flags & SHF_TLS) {
451
            /* .tbss */
456
            /* .tbss */
452
        }
457
        }
453
        break;
458
        break;
454
    case SHT_DYNAMIC:
459
    case SHT_DYNAMIC:
455
        /* Record pointer to dynamic section into info structure */
460
        /* Record pointer to dynamic section into info structure */
456
        elf->info->dynamic =
461
        elf->info->dynamic =
457
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
462
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
458
        DPRINTF("Dynamic section found at 0x%x.\n",
463
        DPRINTF("Dynamic section found at 0x%x.\n",
459
            (uintptr_t)elf->info->dynamic);
464
            (uintptr_t)elf->info->dynamic);
460
        break;
465
        break;
461
    default:
466
    default:
462
        break;
467
        break;
463
    }
468
    }
464
   
469
   
465
    return EE_OK;
470
    return EE_OK;
466
}
471
}
467
 
472
 
468
/** @}
473
/** @}
469
 */
474
 */
470
 
475