Subversion Repositories HelenOS

Rev

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

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