Subversion Repositories HelenOS

Rev

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

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