Subversion Repositories HelenOS

Rev

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

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